Timestamp: https://freetsa.org/tsr Info: Timestamp generated with GitTrustedTimestamps by Mabulous GmbH Version: 1 Policy OID: tsa_policy1 Hash Algorithm: sha1 Message data: 0000 - ab 61 69 44 47 8d 0b f8-83 33 09 ce 8f 5a 38 6f .aiDG....3...Z8o 0010 - aa 10 14 11 .... Serial number: 0x33DEAF Time stamp: Feb 17 01:38:00 2021 GMT Accuracy: unspecified Ordering: yes Nonce: 0x808CA07E1BC45718 TSA: DirName:/O=Free TSA/OU=TSA/description=This certificate digitally signs documents and time stamp requests made using the freetsa.org online services/CN=www.freetsa.org/emailAddress=busilezas@gmail.com/L=Wuerzburg/C=DE/ST=Bayern Extensions: -----BEGIN RFC3161 TOKEN----- MIIFNwYJKoZIhvcNAQcCoIIFKDCCBSQCAQMxDzANBglghkgBZQMEAgMFADCCAX4G CyqGSIb3DQEJEAEEoIIBbQSCAWkwggFlAgEBBgQqAwQBMCEwCQYFKw4DAhoFAAQU q2FpREeNC/iDMwnOj1o4b6oQFBECAzPerxgPMjAyMTAyMTcwMTM4MDBaAQH/AgkA gIygfhvEVxigggERpIIBDTCCAQkxETAPBgNVBAoTCEZyZWUgVFNBMQwwCgYDVQQL EwNUU0ExdjB0BgNVBA0TbVRoaXMgY2VydGlmaWNhdGUgZGlnaXRhbGx5IHNpZ25z IGRvY3VtZW50cyBhbmQgdGltZSBzdGFtcCByZXF1ZXN0cyBtYWRlIHVzaW5nIHRo ZSBmcmVldHNhLm9yZyBvbmxpbmUgc2VydmljZXMxGDAWBgNVBAMTD3d3dy5mcmVl dHNhLm9yZzEiMCAGCSqGSIb3DQEJARYTYnVzaWxlemFzQGdtYWlsLmNvbTESMBAG A1UEBxMJV3VlcnpidXJnMQswCQYDVQQGEwJERTEPMA0GA1UECBMGQmF5ZXJuMYID ijCCA4YCAQEwgaMwgZUxETAPBgNVBAoTCEZyZWUgVFNBMRAwDgYDVQQLEwdSb290 IENBMRgwFgYDVQQDEw93d3cuZnJlZXRzYS5vcmcxIjAgBgkqhkiG9w0BCQEWE2J1 c2lsZXphc0BnbWFpbC5jb20xEjAQBgNVBAcTCVd1ZXJ6YnVyZzEPMA0GA1UECBMG QmF5ZXJuMQswCQYDVQQGEwJERQIJAMHphhYNqOmCMA0GCWCGSAFlAwQCAwUAoIG4 MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjEw MjE3MDEzODAwWjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBSRbaPYYOzKguNLxZ0X k+fpaIdfFDBPBgkqhkiG9w0BCQQxQgRAojL6sR/FVjYstZqJoyjlDDXK2MnpyavS EkmsLHhdQKr75AOGVKS167FDFpFsaX2YNidVW84uRh3yLjbk9rIKjjANBgkqhkiG 9w0BAQEFAASCAgCvCAflm40iGvP/qJhKB2YEMxJDW4KkVUEhAaiExe0HxMICJ2BY heNpuRlQB1k0OL3BP204ENdZDFi2dFxEKbBjYKf5oqNXHBgxN2Hhdd5zuRIrbyDi AdjcTNw8idxZJgO1wuWf5JsSgaFf1cd+5oCIoZj5522f6YtIGE5J+Hh5KW3GoNl5 x3H0VIi1Ql0tHDfSOQT1jSIRQB2Z4lL9S++/Wg4Tx6mYNANOTRdgnnzP4Zm065O7 mvqamDu7w5S6YHV1Exij/C/HghwhvGKsHscI6lEPQYILvgM3MELhdqYc6kV4+VgH LNee5oeZlJl231/rh934mm+0RcEz9ReuDj9FC8KQW6l4z1MN1HHzwBwAp7eqxGB9 1ulTVWcTetzfrm0z/V39bbrIHHEnYbg5OBC5W8aKHZZtFlsdlDMmCYG8Qu/tM9mI 0JOiIdzATIuv1h4sZdGpYnAM1WTbFH3/I1d8CDBDXpSyQe5xXJgLCJ7RlzsVhqmv 9s1Clp9yDY0tAJDdb2e+vA0oYATzv1uULMY66aKP4y6aHPlIn5502f+V5ItacTPV LC7kqdyGO7zrvctNgbd2DPBrv1J2aX8PHrECbOW9iarRG0FyS1twSw1MRCCZpipq q/uILTD0ORaf0hM/kgPPmnuwo1IYl25M48+JuKNhDR+r5T5xF1mSXQiN7w== -----END RFC3161 TOKEN----- Timestamp: http://timestamp.digicert.com/ Info: Timestamp generated with GitTrustedTimestamps by Mabulous GmbH Version: 1 Policy OID: 2.16.840.1.114412.7.1 Hash Algorithm: sha1 Message data: 0000 - ab 61 69 44 47 8d 0b f8-83 33 09 ce 8f 5a 38 6f .aiDG....3...Z8o 0010 - aa 10 14 11 .... Serial number: 0xA620C40730AC5B01F70BB20222CF8BF7 Time stamp: Feb 17 01:38:04 2021 GMT Accuracy: unspecified Ordering: no Nonce: 0x9E92BC55512BC6EA TSA: unspecified Extensions: -----BEGIN RFC3161 TOKEN----- MIINFAYJKoZIhvcNAQcCoIINBTCCDQECAQMxCzAJBgUrDgMCGgUAMHMGCyqGSIb3 DQEJEAEEoGQEYjBgAgEBBglghkgBhv1sBwEwITAJBgUrDgMCGgUABBSrYWlER40L +IMzCc6PWjhvqhAUEQIRAKYgxAcwrFsB9wuyAiLPi/cYDzIwMjEwMjE3MDEzODA0 WgIJAJ6SvFVRK8bqoIIKNzCCBP4wggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0w DQYJKoZIhvcNAQELBQAwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0 IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNl cnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAw MDBaFw0zMTAxMDYwMDAwMDBaMEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdp Q2VydCwgSW5jLjEgMB4GA1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoR Qr0KdXVNlLQMULUmEP4dyG+RawyW5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop +N0rcIXeAhjzeG28ffnHbQk9vmp2h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8b Ordh1nPsTm0zinxdRS1LsVDmQTo3VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa 9E14RuMDgzEpSlwMMYpKjIjF9zBa+RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mC tNv8VlS8H6GHq756WwogL0sJyZWnjbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMB AAGjggG4MIIBtDAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUB Af8EDDAKBggrBgEFBQcDCDBBBgNVHSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsG AQUFBwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU 9LbhIB3+Ka7S5GGlsqIlssgXNW4wHQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3j anq8MHEGA1UdHwRqMGgwMqAwoC6GLGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9z aGEyLWFzc3VyZWQtdHMuY3JsMDKgMKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5j b20vc2hhMi1hc3N1cmVkLXRzLmNybDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUF BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6 Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1l c3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6O Z0b9QnJRdAojR6OrktIlxHBZvhSg5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP 9rhwz2Lo9VFKeHk2eie38+dSn5On7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jp g4L6GlPtkMyNoRdzDfTzZTlwS/Oc1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/E EXLnG2RJ2CKadRVC9S0yOIHa9GCiurRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cu G08THfdKDXF+l7f0P4TrweOjSaH6zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4em ii8wggUxMIIEGaADAgECAhAKoSXW1jIbfkHkBdo2l8IVMA0GCSqGSIb3DQEBCwUA MGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT EHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQg Um9vdCBDQTAeFw0xNjAxMDcxMjAwMDBaFw0zMTAxMDcxMjAwMDBaMHIxCzAJBgNV BAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdp Y2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1l c3RhbXBpbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC90DLu S82Pf92puoKZxTlUKFe2I0rEDgdFM1EQfdD5fU1ofue2oPSNs4jkl79jIZCYvxO8 V9PD4X4I1moUADj3Lh477sym9jJZ/l9lP+Cb6+NGRwYaVX4LJ37AovWg4N4iPw7/ fpX786O6Ij4YrBHk8JkDbTuFfAnT7l3ImgtU46gJcWvgzyIQD3XPcXJOCq3fQDpc t1HhoXkUxk0kIzBdvOw8YGqsLwfM/fDqR9mIUF79Zm5WYScpiYRR5oLnRlD9lCos p+R1PrqYD4R/nzEU1q3V8mTLex4F0IQZchfxFwbvPc3WTe8GQv2iUypPhR3EHTyv z9qsEPXdrKzpVv+TAgMBAAGjggHOMIIByjAdBgNVHQ4EFgQU9LbhIB3+Ka7S5GGl sqIlssgXNW4wHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wEgYDVR0T AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUH AwgweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaG NGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD QS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFz c3VyZWRJRFJvb3RDQS5jcmwwUAYDVR0gBEkwRzA4BgpghkgBhv1sAAIEMCowKAYI KwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCwYJYIZIAYb9 bAcBMA0GCSqGSIb3DQEBCwUAA4IBAQBxlRLpUYdWac3v3dp8qmN6s3jPBjdAhO9L hL/KzwMC/cWnww4gQiyvd/MrHwwhWiq3BTQdaq6Z+CeiZr8JqmDfdqQ6kw/4stHY fBli6F6CJR7Euhx7LCHi1lssFDVDBGiy23UC4HLHmNY8ZOUfSBAYX4k4YU1iRiSH Y4yRUiyvKYnleB/WCxSlgNcSR3CzddWThZN+tpJn+1Nhiaj1a5bA9FhpDXzIAbG5 KHW3mWOFIoxhynmUfln8jA/jb7UBJrZspe6HUSHkWGCbugwtK22ixH67xCUrRwII fEmuE7bhfEJCKMYYVs9BNLZmXbZ0e/VWMyIvIjayS6JKldj1po5SMYICPTCCAjkC AQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcG A1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBB c3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TAJBgUr DgMCGgUAoIGMMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0B CQUxDxcNMjEwMjE3MDEzODA0WjAjBgkqhkiG9w0BCQQxFgQURzVJC8GaY0T9kHT9 CRzpu9QtP4IwKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU4deCqOGRvu9ryhaRtaq0 lKYkm/MwDQYJKoZIhvcNAQEBBQAEggEAJVzsoZjH7ZU2PVa13ejdKUehX8LPc0sj qDDyvT+FLIECtNMDkE7JqjXfgeDxHuoOwaRLTvdjlNVlCTowYD+2inzL83K0W/Cc K/PtqXElrV1YQQFsEECOjhxMlI4IsRA8eU5BKMzdWgb1FHsgSB2lAvEa9KuYutmf nsw8SFubcQZWhxHgK8HJLnSpw6DHUSVJPllg9PCggV0ZxjwPm0/VbeXOOKtz+z2D BVVPabMre1bTew9P4bkmu7njEF5WQz/xU2hpFiuMaaEotfkVAM84nLNJvtF7rAZ6 tcwqa3LyALr7MKvuYnbkkVR+X38vAUpYL7IuocK7thaq3EkEhNVjvQ== -----END RFC3161 TOKEN-----
GitTrustedTimestamps
RFC3161 and RFC5816 Timestamping for git repositories.
By using this post-commit hook in a repository and thereby adding secure timestamps to the commits it contains, the repository gains the following properties:
- Authenticity: trusted, non-refutable time when data was commited
- Integrity: protection of the timestamped data as well as the timestamps themselves from tampering without detection
- Timeliness: proof that the time of the digital signature (if used together with PGP signatures) was in fact the actual time
- An evidentiary trail of authenticity for legal sufficiency
How to use this software
- (optional, but recommended) If you're ceating a new repository, it is strongly recommended to use SHA256 hashes (git uses SHA1 by default at the time of writing) by initializing the reopository using
git init --object-format=sha256(Note: If you want to use a public hosting server such as github for your repository, you should check whether they already support SHA256 repositories). For more information, see https://git-scm.com/docs/hash-function-transition/ - Copy the four bash scripts in the hooks folder of this project into the .git/hooks folder of the project you want to timestamp.
- Configure the TSA url you want to use (in this example https://freetsa.org/tsr) using
git config --local timestamping.tsa0.url https://freetsa.org/tsr - You must declare that you trust this TSA by copying the root certificate of that TSA's trust chain into the .git/hooks/trustanchors folder (create it if it doesn't exist yet). The certificate MUST be in PEM format and the filename MUST be "subject_hash.0" where
subject_hashis what openssl returns for the--subject_hashargument for x509 cetificates (https://www.openssl.org/docs/man1.1.1/man1/x509.html).
For your convenience, there is the hooks/trust.sh script which will do this for you. To use it, simply run.git/hooks/trust.sh https://freetsa.org/tsrfrom your Git-Bash and confirm adding the certificate (Note: The certificates stored in .git/hooks/trustanchors are ONLY used to validate timestamp tokens, no other trust is established). - (optional) If you want to use multiple TSAs, just set additional urls for tsa1, tsa2 and so on. Make sure that they are all defined consecutively, for example, if you have a url defined for tsa0 and for tsa2, but not for tsa1, then tsa2 will be ignored. Since timestamp tokens will become forever invalid should a TSA's private key leak, using at least two trusted TSAs is a good strategy to protect against this unlikely eventuality (see chapter 4. "Security Considerations" of RFC3161 specification).
- (optional) By default, a commit will fail if a timestamp token cannot be retrieved. If you want to make timestamping optional for a certain tsa, you can set
git config --local --type=bool timestamping.tsa0.optional true.
Ifoptionalis set to true and a timestamping token cannot be retrieved, you will receive a warning but the commit will be created nevertheless.
From now on, every git commit will tigger an additional commit that securely timestamps this commit.
What are RFC3161 and RFC5816 Timestamps
RFC3161 (https://tools.ietf.org/html/rfc3161) and its extension RFC5816 (https://tools.ietf.org/html/rfc5816) are protocol specifications timestamp data using cryptographically secure tokens issued by an external, trusted third party TSA (Time Stamping Authority). By timestamping data this way, it is possible to prove to anyone who trusts this TSA service that the data existed already at the time of timestamping and has not been tampered with ever since. Only a secure hash of the data, without any identification, is being sent to the TSA service, so the data itself remains secret.
Alternatives
Before writing this software, I evaluated alternatives available at the time of writing (Feb 2021). I will briefly list and discuss my findings here to outline the differences.
-
There is a stackoverflow question (https://stackoverflow.com/questions/11913228/how-can-i-use-rfc3161-trusted-timestamps-to-prove-the-age-of-commits-in-my-git) and subsequently posted code review (https://codereview.stackexchange.com/questions/15380/adding-trusted-timestamps-to-git-commits):
This script allows to manually create timestamps for revisions and store them in git-notes. This was not sufficient for me since having timestamps stored in git-notes makes them "cryptographically dangling" in the sense that the timestamped repository does not depend on them (meaning that they can be "lost" without being noticed). This may be the preferred solution for someone who just wants to be able to prove the time the code was created if he so desires, without creating a repository which is tamperproof (and without the benefits discussed further down). Also, the script does not take CRLs into consideration for validation. -
GitLock (https://www.npmjs.com/package/gitlock):
GitLock adds timestamps as tags, which, like git-notes, also won't make the timestamped repository cryptographically depend on the timestamps themselves and thus offers the same advantages/disadvantages as the script above. It also creates a parallel SHA256 hierarchy (which isn't necessary anymore, since git now provides native SHA256 support) and depends on a Node.js application that must be installed and used manually. This solution may be preferred if the same conditions hold as with the first altenative and additionally SHA256 is required but a public git server which does not yet support native SHA256 commit hashes is used. -
There is this fork of git:
The fork was created as part of a university project to add native support for RFC3161 tokens to git. There is a corresponding discussion in the archived git mailing list (http://git.661346.n2.nabble.com/Adding-RFC-3161-timestamps-to-git-tags-td7650116.html). Since it requires a custom build of git and wasn't adopted by the official repo, I did not further investigate this implementation. -
There is this article discussing timestamping git repositories:
It is using the OriginStamp (https://originstamp.com/) timestamping service. This solution does not use RFC3161 but instead relies on publication of hashes in public blockchains using the OriginStamp service (which comes with the advantages and disadvantages of blockchain transactions, such as long confirmation times and high fees). -
Zeitgitter (https://pypi.org/project/git-timestamp/):
Zeitgitter seems to use a custom timestamping protocol and rely on developers cross-verifying their timestamps. Since it requires a custom client and server application and does not rely on RFC3161, I did not further investigate this implementation.
Implementation design
The design goals of this implementation are transparent simplicity (security without obscurity), using only "vanilla" git features to add the timestamps in order to stay as forward compatible as possible, as well as to not rely on new binaries (which would need to be trusted too). The software therefore is implemented as bash scripts and uses OpenSSL (https://www.openssl.org/) and git itself for all cryptographic operations.
Additionally a further goal was that new commits will depend on previous timestamps, so that they cryptographically seal the older timestamps which makes the repository both tamperproof and protects older timestamps from some forms of invalidation.
How are timestamps added to commits
For each commit that is being timestamped, an additional timestamp commit is created, for which the commit that is being timestamped is the direct parent. The hash that is contained in the timestamp token corresponds to the git hash of the commit being timestamped. Since git itself is implemented as a Merkle Tree, this hash depends on every bit of every commited file as well as the entire commit history, making it impossible to change anything without invalidating the timestamp. The timestamping token (one for each TSA for which a timestamp was retrieved) is then added in PEM encoding (plus some info about the token in readable form) as a trailer to the commit message of the timestamp commit. Chosing this design to add the timestamps has several advantages:
- The commit hash always depends on the entire data of that commit (including the pgp signature that commit is signed with) and its history, meaning that not a single bit of data being committed (or the history it depends on) could be changed without creating a completely different commit hash.
- It is most likely the most forward-compatible option. If new commit headers or other commit data will be added to git in the future, they will most likely also be captured by the commit hash.
- By storing the tokens inside the commit message, which is hashed itself, rather than in git-notes or tags, subsequent commits will seal these timestamps, making it impossible to "lose" them, which gives the timestamping of the repository a non-repudiation property (https://en.wikipedia.org/wiki/Non-repudiation), meaning it will be impossible to "rewrite history" unnoticed.
- Since newer timestamps seal older timestamps (i.e. the older timestamps are part of what is being timestamped), this protects old timestamps from becoming invalid in some situations. For example: Say in 2021 all commits are timestamped using a TSA that uses "certificateA" to sign its timestamps. Then in 2022 a TSA is used which uses "certificateB" to sign its timestamps. Then in 2023 the private key of "certificateA" leaks. Normally, if a TSA's private key leaks, all old timestamps become invalid and can't be trusted anymore (because the private key could be used to "backdate" data) - however, since in this case the timestamps of 2021, which are signed with the still trusted "certificateB" sealed the older timestamps, these old timestamps can still be considered valid, since they were provably created before the "certificateA" private key leaked. The same applies to old timestamps becoming invalid for example due to the algorithm used for them not being deemed secure anymore.
An altenative design that was considered but dismissed was to include the timestamps right into the commit message of the commit that is being timestamped (in order to keep the commit history more tidy), in a similar fashion as PGP signatures are added. PGP signatures do this by calculating the commit hash AS-IF the signature was not contained, then sign this hash and then add the signature into the commit header (thereby changing the hash). A similar approach could have been taken with the timestamps, but this would have two serious drawbacks:
- Since PGP signatues are inserted natively AFTER the commit is generated, the timestamp token could therefore not timestamp the signature (instead, the signature would sign the timestamp, which is not useful).
- Validation code would need to compute a commit hash AS-IF the timestamp-token was not contained, but also AS-IF any insertions happening AFTER timestamping were not present (at the time of writing, that's only PGP-Signatures. However, since future versions of git may include other additional headers in a similar fashion, this would break current timestamp validation code).
For these reasons, adding timestamps right into the commit that is being timestamped was dismissed, for separate timestamp commits are much more likely to be forward compatible with anything git will add to the commit object in the future.
Additionally to retrieving TSA tokens and timestamping the commits with them, the post-commit hook will also validate these tokens first to ensure that only valid, trusted time-stamp tokens are added. It does so by validating that:
- The received token corresponds to the request (a nonce sent in the request is being used for this).
- The token is valid and trusted.
- All certificates in the trust-chain up to a trusted anchor (stored in .git/hooks/trustanchors) are valid and have not been revoked (checked by downloading and checking CRLs for all certificates).
If a token does not pass these tests, it is not added and the commit is either aborted (if the TSA is not set to optional) or a warning is output (if the TSA is set to optional).
This repository uses the post-commit hook itself, so if you check the commit history of this repository, you will see that each commit is followed by a -----TIMESTAMP COMMIT----- that contains one or more timestamp tokens.
For example, this timestamp commit timestamps this regular commit, which is its direct parent. You can see that the "Message data" of the timestamp token is the commit hash 4f88284a57 of the commit being timestamped.
LTV data:
Additionally to the bare timestamp tokens stored in the commit message as trailers, the timestamp commit also adds revisioned files to the .timestampltv folder. If the timestamps should be evaluated many years in the future, when the TSA does not exist anymore and the entire certificate chains of tokens for example can't be retrieved anymore, this Long Term Validation data will facilitate validating the tokens. For each timestamp commit two files are stored:
- .timestampltv/certs/issuer_hash.cer: This file contains the entire trust chain of the TSA certificate in PEM format (the first certificate being the TSA's signing certificate and the last being the self-signed root). In most cases this file will not change for subsequent timestamp tokens, so no additional data is added to the repository (the file content only changes when the TSA changes its signing certificate).
- .timestampltv/crls/issuer_hash.crl: This file contains CRL responses in PEM format for all certificates in the trust chain at the time of timestamping. In most cases this file will not change for subsequent timestamp tokens, so no additional data is added to the repository (the file content only changes when the CRL lists referenced by certificate in the trust chain change).
The issuer_hash for both files corresponds to the ESSCertID or ESSCertIDv2 hash with which the token identifies its issuer certificate. In general this is the SHA1 hash of the DER encoded issuer certificate for RFC3161 tokens, and some other hash of the DER encoded issuer certificate for RFC5816 tokens (the ESSCertIDv2 of the token specifies the used hashing algorithm).
How to validate timestamps:
Ultimately the responsibility (and criteria) for validating the timestamps lies with the party who wishes to proof/disprove that they are valid and the policy being used.
This repository does come however with an implementation that validates the created timestamps according to the criteria listed below. To use it, simply run .git/hooks/validate.sh
validate.sh will iterate over the entire commit history of the current branch and for each timestamp commit will:
- Check that the digest contained in the token matches the commit hash of the timestamped commit
- Checks that the TSA certificate was valid at the time of timestamping, by using historic CRL data
- Checks whether the TSA certificate or any intermediate certificate in the chain has been revoked and if so, whether the revocationCode matches the acceptable revocation reasons discussed in chapter 4 of the RFC3161 specification (https://tools.ietf.org/html/rfc3161)
- A commit containing multiple timestamps will be considered valid if there is at least one valid timestamp token (a warning will be printed if there are additional timestamps that are considered invalid)
To perform these checks, the same trusted rootCAs from the .git/hooks/trustanchors folder are used.
No other checks are performed. In particular, a timestamp-token is considered valid beyond the expiration date of its signing certificate if it hasn't been revoked due to a reason other than those specified in chapter 4.1 of the RFC3161 specification.
The curent implementation of the validate.sh script also does not consider whether the hashing algorithms used in the timestamp-token or the keylength of the signing certificate are still considered secure.
The script exits with exit code 0 if all tests passed, and with exit code 1 otherwise.
Author
- Matthias Bühlmann