Documentation updated

This commit is contained in:
Matthias Bühlmann
2021-02-15 19:28:28 +01:00
parent ed02e53802
commit e53681e905

View File

@@ -12,11 +12,14 @@ By using this post-commit hook in a repository and thereby adding secure timesta
0. (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/
1. Copy the three bash scripts in the [hooks](hooks/) folder of this project into the .git/hooks folder of the project you want to timestamp.
2. 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`
2. 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`
3. 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_hash` is what openssl returns for the `--subject_hash` argument for x509 cetificates (https://www.openssl.org/docs/man1.1.1/man1/x509.html).
**For your convenience, there is the [hooks/trust.sh](hooks/trust.sh) script which will do this for you.** To use it, simply run `.git/hooks/trust.sh https://freetsa.org/tsr` from 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).
4. (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).
5. (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`. If `optional` is set to true and a timestamping token cannot be retrieved, you will receive a warning but the commit will be created nevertheless.
5. (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`.
If `optional` is 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.
@@ -45,18 +48,18 @@ Zeitgitter seems to use a custom timestamping protocol and rely on developers cr
# Implementation design
The design goals of this implementation are 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 goal was that 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.
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 *timestamping 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. 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 *timestamping commit*. Chosing this design to add the timestamps has several advantages:
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](https://en.wikipedia.org/wiki/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, 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.
- 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 2020 all commits are timestamped using a TSA that uses "certificateA" to sign its timestamps. Then in 2021 a TSA is used which uses "certificateB" to sign its timestamps. Then in 2022 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 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:
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:
1. 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).
2. 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).
@@ -67,12 +70,14 @@ Additionally to retrieving TSA tokens and timestamping the commits with them, th
- 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](https://github.com/MrMabulous/GitTrustedTimestamps/commit/a3e7a2a4a280fc03abe51ff70a8bd603837af150) *timestamp commit* timestamps [this](https://github.com/MrMabulous/GitTrustedTimestamps/commit/4f88284a578ba8309269a4d1f2474033fe441e82) regular commit, which is its direct parent. You can see that the "Message data" of the timestamp token is the commit hash 4f88284a578ba8309269a4d1f2474033fe441e82 of the timestamped commit.
For example, [this](https://github.com/MrMabulous/GitTrustedTimestamps/commit/a3e7a2a4a280fc03abe51ff70a8bd603837af150) *timestamp commit* timestamps [this](https://github.com/MrMabulous/GitTrustedTimestamps/commit/4f88284a578ba8309269a4d1f2474033fe441e82) regular commit, which is its direct parent. You can see that the "Message data" of the timestamp token is the commit hash 4f88284a578ba8309269a4d1f2474033fe441e82 of the commit being timestamped.
# LTV data:
Additionally to the bare timestamp tokens stored in the commit message as trailers, the *timestamping 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 *timestamping commit* two files are stored:
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:
1. .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).
2. .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).