From ec3b92c6a2c5c1c40ef44fb2e043cd942fcd9dee6e29248e968367d6b018c5d9 Mon Sep 17 00:00:00 2001 From: Nicholas Johnson Date: Sun, 16 Jul 2023 00:00:00 +0000 Subject: Make big improvements to the README --- README.md | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 1cfcaf2..882ee1f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## ❌ Default Git Privacy ❌ -With only 3 commands, *anyone* can find out the dates, time zones, and exact clock times a developer makes commits. +[Git is generally good about not preserving any metadata](https://git.wiki.kernel.org/index.php/ContentLimitations), except when it comes to timestamps. With only 3 commands, anyone can find out the time zones and exact clock times a developer makes commits. ```sh git clone @@ -10,53 +10,56 @@ cd git log --format=fuller ``` -This can leak personal information about a developer's life. The time zones reveal the developer's approximate location in the world at that time and exact commit times recorded over a sufficient timespan may be used to deduce a developer's sleep patterns for example. +This can leak personal information about a developer's life. The time zones reveal the developer's approximate location in the world and exact commit times recorded over a sufficient timespan may be used to deduce a developer's sleep patterns for example. ## 📅 Git Timestamps 📅 -[Git commit objects](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/user-manual.html#commit-object) have 2 or 3 timestamps to worry about. The two main ones are: +[Git commit objects](https://git-scm.com/docs/user-manual.html#commit-object) always have at least 2 timestamps. They are controlled by the following environment variables: -* `GIT_AUTHOR_DATE` represents the time and date the *changes* were made, not the *commit*. -* `GIT_COMMITTER_DATE` represents the time and date the changes were *committed*. +* `GIT_AUTHOR_DATE` represents when the changes were made +* `GIT_COMMITTER_DATE` represents when the changes were committed -### Removing Timestamps For Commits +Annotated [Git tag objects](https://git-scm.com/docs/user-manual.html#tag-object) always have at least 1 timestamp. It is also controlled by the `GIT_COMMITTER_DATE` environment variable. -Git doesn't have a way to *remove* timestamps altogether, but both the `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE` can be set to any arbitrary date. For maximum privacy, set the `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE` to any constant date in your shell's environment variables. +There is another timestamp which comes from the optional GnuPG signature on a commit or annotated tag. It is controlled by GnuPG. + +### Removing Timestamps for Commits and Annotated Tags + +Git can't remove timestamps altogether, but the `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE` environment variables can be set to any arbitrary date. Preferably, use dates from before Git was invented to clearly signal the timestamps are forged: ```sh -export GIT_COMMITTER_DATE="2000-01-01 00:00:00+0000" -export GIT_AUTHOR_DATE="2000-01-01 00:00:00+0000" +export GIT_AUTHOR_DATE="2000/01/01T00:00:00+0000" +export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" ``` -To retain only the day on which a commit was made, set both the `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE` like so: +To retain the day on which changes and commits are made, set `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE` to the output of the date command, like so: ```sh -export GIT_COMMITTER_DATE="$(date +%Y-%m-%d) 00:00:00+0000" -export GIT_AUTHOR_DATE="$(date +%Y-%m-%d) 00:00:00+0000" +export GIT_AUTHOR_DATE="$(date -u +%DT00:00:00%z)" +export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" ``` -Environment variables don't change after being set. So the dates update when a new shell is opened, not at midnight. +Environment variables don't change after being set, so the dates update when a new shell is opened, not at midnight. ### 🔑 Removing Timestamps for Digital Signatures 🔑 -GPG signatures contain their own timestamps which can be just as revealing as Git timestamps. Luckily, GPG signature timestamps can also be forged with the option: `--faked-system-time `. For this to be persistent, Git needs to run a version of GPG that *always* forges the system time. Also, the script should exclude GPG version information since that could also leak time information: +GnuPG can't remove its signature timestamps altogether, but they can be forged by configuring Git to run a custom version of GnuPG: ```sh #!/bin/sh -# file: /usr/bin/gpg2-git -gpg2 --faked-system-time ! --no-emit-version --no-comments $@ +gpg --faked-system-time ! $@ ``` -`` can be any time *after* the GPG signing key was generated. An example `iso` value is `20201130T000000` for 30 November 2020 at midnight. +For GnuPG signatures with a fixed forged timestamp to be verifiable, `` must be manually set to a time between the expiry date of the signing key and when it was generated. See gpg(1) for how to format ``. -Make Git use the new script instead of regular GPG by adding the following lines to your Git config: +To retain the day on which GnuPG signatures are made, use the output of the date command: -```plaintext -[gpg] - program = gpg2-git +```sh +#!/bin/sh +gpg --faked-system-time "$(date -u +%Y%m%dT000000)!" $@ ``` -Git will now use a fake system time for every GPG signed commit. [Git preserves almost no metadata](https://git.wiki.kernel.org/index.php/ContentLimitations) by design, so privacy is looking pretty good. +The last step is to set the script as executable with `chmod +x /path/to/custom-gpg.sh` and point Git to it with `git config --global gpg.program /path/to/custom-gpg.sh`. ## 📝 Additional Notes 📝 -- cgit v1.2.3