Skip to content

Automatically create trusted timestamps for your commits

License

Notifications You must be signed in to change notification settings

Ocead/timestamping

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ocead's Automated Timestamping

Automatically create trusted timestamps for your commits

This software allows you to add timestamps to your contributions to a Git repository via trusted third-party timestamping services. As specified in RFC 3161, these timestamps may be used to prove the existence of data at the time the timestamp was issued and that the data wasn't changed since then. This timestamp data may serve to derive proofs of:

  • Integrity of the data to be committed
  • Ownership immediately before the commit
  • Timeliness of the contributed work
  • Authorship through self-disclosed copyright notices

All data used and generated by this software is stored in separate Git branches. You may choose freely to publish the timestamps or keep them private as needed. This software runs entirely client-side.

ℹ Note: Check out this software in action on this repo: sig/b/master

Requirements

Installation

This software can be installed to any local Git repository. Clone this repository or download its source from the Releases page. Then choose one of the following ways to install:

Automatic

Run the config.sh script with the path to the local repository you want to install automated timestamping to:

./config.sh ~/path/to/repo

Manual

  1. Copy the contents of hooks directory into the .git/hooks directory of the target repository.
  2. Set the options described in the options section for at least the target repository.
  3. If you already have the hooks commit-msg, post-commit, pre-push in place, in your hooks:
    1. source this software's renamed respective hook file
    2. Call the ts-commit-msg/ts-post-commit/ts-pre-push function with the arguments the respective hook expects.

ℹ Note: if the script was installed into .git/hooks it is technically not part of the repository and will therefore not be versioned through commits nor sent to remotes through pushes.

⚠ Warning: If the repository you wish to install to already uses any of the hooks above, make sure the scripts of this software are run not parallel to other hooked scripts that read or modify the repository.

Deinstallation

Automatic

Run the config.sh script with the path to the local repository you want to uninstall automated timestamping from:

./config.sh -r ~/path/to/repo

If you don't want to keep the generated timestamps, run

./config.sh -p ~/path/to/repo

instead.

Manual

To remove automated timestamping from a repository (provided automatic installation preceded):

  1. Delete the commit-msg, post-commit, pre-push and timestamping.sh files from the .git/hooks directory in the repository.
  2. Unset the ts.* git-config options.

If you also want to delete any generated timestamps:

  1. Force-delete the ${ts.branch.prefix}/root and ${ts.branch.prefix}/b/* (sig/root and sig/b/* by default) branches from the repository.

Functionality

This software uses OpenSSL to generate timestamps according to the "Internet X.509 Public Key Infrastructure Time-Stamp Protocol" specified in RFC 3161.

Creating timestamps

Timestamps of your commits are automatically created on calling git-commit.

On committing, this will happen behind the scenes:

  1. Immediately before committing, a full diff (qualified for use with git-apply) of your staged changes / the staged state of the checked out branched is created.
  2. This diff is placed into a separate signing branch, corresponding 1:1 to your normal non-signing branches.
  3. The diff is then hashed, and a timestamping request for that hash is created in the signing branch for each time stamp authority you have configured.
  4. These timestamping requests are sent to the timestamping servers and the responses are also be stored in the signing branch.
  5. The diff, request and response files are then committed to the timestamping branch.
  6. Afterwards, your staged contributions are committed to the non-signing branch.
  7. This commit is then merged into its timestamping branch to relate the timestamp to it.
  8. Lastly, the branch you committed to is checked out again.

Retrieving timestamps

Timestamps are versioned in special signing branches, that match 1:1 to your regular branches. These branches have a separate root, so you may withhold them when publishing your contributions as a Git repository.

To find the timestamp of the latest you created by committing changes, check out the appropriate signing branch (provided default options) e.g.:

git checkout "sig/b/single"

to check out the timestamps created for commits on branch single.

To find the timestamp of a specific commit, refer to this commit history graph:

 
o  <- Merged timestamp/actual commit
╲│
 o <- Actual commit
 
o  <- Timestamp commit
 
  <- Actual branch
   <- Signing branch

As the timestamps are created before the actual commits, they can not refer to the actual commit. Therefore, the actual commit is merged into the signing branch afterwards, so that both the timestamp and actual commit are previous commits of this new merged commit. However, to keep contributions and timestamps separate, the merged commit still only contains the timestamp files.

You'll find the timestamp files from each configured TSA inside its respective configuration directory (provided default options) e.g.

./
├ .diff <- Full diff of the staged files before committing
└ rfc3161/
  └ zeitstempel.dfn.de/
    ├ cacert.pem
    ├ request.tsq  <- Timestamp request
    ├ response.tsr <- Timestamp
    └ url
...

To verify the files against each other you may use these commands (provided default options):

  • Show a trusted timestamp's contents:

    cd ./rfc3161/zeitstempel.dfn.de
    openssl ts -reply -in response.tsr -text
  • Verify a timestamp against the request:

    cd ./rfc3161/zeitstempel.dfn.de
    openssl ts -verify -in response.tsr -queryfile request.tsq -CAfile cacert.pem
  • Verify a timestamp against the diff:

    cd ./rfc3161/zeitstempel.dfn.de
    openssl ts -verify -in response.tsr -data ../../.diff -CAfile cacert.pem

Configuring Time Stamp Authorities (TSAs)

A time stamp authority is a trusted third party that signs data provided to it using asymmetric keys together with the timestamp of receiving the data. With this, the TSA confirms that it was sent the signed data at the signed timestamp. This software utilises the "Time-Stamp Protocol via HTTP" described in RFC 3161 Section 3.4 for requesting timestamps.

Configuring a new TSA

You can configure an arbitrary number of individual TSAs for each repository. To configure a new timestamping server for a repository where this software is installed to, do the following steps:

  1. Check out the branch specified through ts.branch.prefix (sig/root by default).
    Example:

    git checkout sig/root
  2. In there, navigate to the directory specified in ts.server.directory (rfc3161 by default) and create a new directory. The name of this directory specifies the domain of the timestamp server.

    cd rfc3161
    mkdir zeitstempel.dfn.de

    If the URL of the timestamp server is a resource on a domain, you may name this directory anything and place a file named url (can be changed via ts.server.url) containing the URL inside it instead.

  3. Place the public certificate bundle of the timestamp server inside the directory as cacert.pem (can be changed via ts.server.certificate).

    The repository should look like this afterwards (provided default options):

    ./
    └ rfc3161/
      └ zeitstempel.dfn.de/
        ├ cacert.pem
       (└ url)
    ...
    
  4. Commit this addition to sig/root.

ℹ Note: For a ready-to-use list of timestamping servers, see docs/servers.md.

Customising a TSA configuration

By placing additional files inside a TSA configuration's directory, you can further customize how timestamps from that TSA are generated. Here is a fully customized TSA configuration directory:

./
└ rfc3161/
  └ freeTSA/
    ├ .diff
    ├ cacert.pem
    ├ cacert.shdiff.shrequest.sh
    ├ request.tsq
    ├ response.sh
    ├ response.tsr
    └ url
...

The following customizations are recognized:

  • TSA server URL

    File: url

    Description: If existent, defines the URL the timestamping request is sent to.
    Use this to specify a protocol and resource on the server domain.

    Example: ./rfc3161/freetsa/url

    https://freetsa.org/tsr
    
  • TSA certificate bundle

    File: cacert.sh

    Description: If existent, is called when before verifying the timestamp before the actual commit, and it's output is piped into the certificate bundle file of the TSA.
    Use this to ensure the timestamps are verified against the current certificate.

    Example: ./rfc3161/freetsa/cacert.sh

    curl --silent https://freetsa.org/files/cacert.pem
  • Diffs

    File: diff.sh

    Description: If existent, is called when creating the diff before the actual commit, and it's output is used as a diff to timestamp from that TSA only. The so generated diff file will not be modified further.
    Working directory is the repository's root directory.

    Example: ./rfc3161/freetsa/diff.sh

    git diff --staged --full-index --binary
  • Timestamp requests

    File: request.sh

    Description: If existent, is called for creating the timestamping request.
    The diff file will be supplied via stdin and the contents of the request file are expected on stdout.

    Example: ./rfc3161/freetsa/request.sh

    openssl ts -query -cert -sha512 <&0
  • Timestamp responses

    File: response.sh

    Description: If existent, is called for retrieving the timestamping response.
    The request will be supplied via stdin and the contents of the response file are expected on stdout.

    Example: ./rfc3161/freetsa/request.sh

    curl --silent --header 'Content-Type: application/timestamp-query' --data-binary @- https://freetsa.org/tsr <&0

Updating a TSA configuration

You may want to change the configuration of a TSA if the URL to the server or the certificate bundle of the server change. To do so (provided default options):

  1. Change the associated files/directory on branch sig/root.
  2. Commit the changes to sig/root.

Upon committing to the sig/root branch, the timestamps for the changed TSA configurations will be updated for all branches that already have a timestamp of the previous version of the TSA configuration.

Deleting a TSA configuration

To delete a TSA configuration (provided default options):

  1. Delete the associated directory in rfc3161 on branch sig/root.
  2. Commit deleting the directory to sig/root.

Options

This software is controlled via git-config. These options all occupy the ts. namespace. They can be set via

git config <option> "<value>"
Git config option Description Default value
ts.branch.prefix The prefix used for branches created through and used by the automated timestamping.
Will be appended with /root for root branch and with /b/<branch-name> for each branch committed to.
"sig"
ts.branch.pull How remote and local signing branches should me managed.
May either be:
  • "default": As configured through pull.rebase
  • "merge": Merge remote signing branches into local before timestamping or
  • "rebase": Rebase remote signing branches into local before timestamping or
  • "keep": Don't update local signing branches from remote.
"merge"
ts.branch.withhold Whether the contents of timestamping branches should be withheld from remotes.
If true, git-push will fail for timestamping branches.
"false"
ts.commit.prefix The prefix used for messages for commits containing timestamps.
Will be appended with the commit message of the actual commit.
"Timestamp for: "
ts.commit.options Options to apply to the git commit command for committing timestamps. ""
ts.commit.relate Whether timestamp commits should be related via merge commits.
May be true or false.
"true"
ts.diff.notice Text added to the start of the timestamped diff files. "Written by $(git config --get user.name)"
ts.diff.file Name of the generated diff file. ".diff"
ts.diff.type Type of diff to be created.
May either be:
  • "staged" for diffs to HEAD, or
  • "full" for diffs to the empty tree object.
"staged"
ts.server.directory The directory containing the timestamp server configurations relative to the repository's root directory. "rfc3161"
ts.server.url Name of the file containing the url of the timestamp server. "url"
ts.server.certificate Name of the certificate bundle file for a single timestamp server. "cacert.pem"
ts.server.update Whether timestamps should be updated on TSA configuration changes.
May be true or false.
"true"
ts.request.file Name of the generated timestamp request file. "request.tsq"
ts.request.options Options for creating the timestamp request file through openssl ts -query. "-cert -sha256 -no_nonce"
ts.response.file Name of the received timestamp response file. "response.tsr"
ts.response.options Options for requesting the timestamp from the server through curl. ""
ts.response.verify Whether the received timestamp should be verified against the diff and request file.
May be true or false.
"true"
ts.enabled Whether automated timestamping should be triggered on commits.
May be true or false.
"true"

⚠ Warning: Set the paths and filenames so that they don't interfere with what you plan to commit.

Roadmap

  • Automatically creating RFC3161 timestamps
  • Multiple TSAs
  • Choice between cached and full diffs
  • Custom timestamp response options
  • Referencing actual commits in timestamping branches
  • Automatically redoing timestamps upon configuration changes
  • Withholding timestamping commits from remotes
  • Prevent merging timestamping commits into actual branches
  • Custom diff and timestamp generation per TSA
  • Trusted timestamps after commits

License

This software is released under the MIT License.