---
# System prepended metadata

title: Signed Git Commit Structure

---

# Signed Git Commit Structure

Wolf McNally, Blockchain Commons

## Verifying Commits Using GIt

Git can indeed verify commits. Note the `good signature` line below.

```shell
$ git show --show-signature 3572bae2999f524635ced380cccaa8fe7ca6fbdf
```

```
commit 3572bae2999f524635ced380cccaa8fe7ca6fbdf (HEAD -> master, origin/master)
gpg: Signature made Fri Mar  1 03:36:22 2024 PST
gpg:                using RSA key 943652EE38441760C3DC35364B6C2FCF894780AE
gpg: Good signature from "Wolf McNally <wolf@wolfmcnally.com>" [ultimate]
Author: Wolf McNally <wolf@wolfmcnally.com>
Date:   Fri Mar 1 03:36:22 2024 -0800

    Clarified README.

diff --git a/README.md b/README.md
index a05bcd9..9a0ea79 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@ _For related Threat Modeling, see the [Seed Tool Manual](https://github.com/Bloc
 ### 1.6.1 (79)
 
 * THIS IS A RELEASE CANDIDATE
-* Fixed: Some places in the app were still producing version 2 output descriptors.
+* Fixed: Some places in the app were still producing version 2 output descriptors. Version 2 output descriptors are still supported for reading but only Version 3 descriptors are now produced.
  
 ### 1.6 (78)
```

## Viewing Commits

```shell
$ git cat-file commit 3572bae2999f524635ced380cccaa8fe7ca6fbdf
```

```
tree de2e850dc1fab0387be6a3ae3f22546dff6631bd
parent ed858de10c8bc82a8819d20a5cd0f5748d570bf2
author Wolf McNally <wolf@wolfmcnally.com> 1709292982 -0800
committer Wolf McNally <wolf@wolfmcnally.com> 1709292982 -0800
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEElDZS7jhEF2DD3DU2S2wvz4lHgK4FAmXhvbYACgkQS2wvz4lH
 gK6ZFxAAkkAEthu4Cxqz/KgH4C+OeNH4tauGkFzgus6MkwyeqoVLCGxqQ3bYfDLM
 s6J5LovbMXNiPkloiaTB8XPtVQFI37+Vz2RGXqJnxUAOxa6WasOjJUItRR6G+zjJ
 QKeHz1DP5JXoEGfxkD6wPXFkOzvd6mhWYYrlduNAr44p17Vhq2w7JCLDm7ukBCJD
 DI6DObfFvwwXRV4xalLPluSIF079uatjbWJC3O1FOa0fFYrusuWxakMzXHtwOEtU
 vBurctpwf6qJUicBNymTlMx7HKPYqh5rVBQWOVC5BGJZtrikQN0GmCuDsp7HWdYB
 2xGaQVfWRQqVz3POfLqLqq+D95RpEerqmnmtHd0NJx+gwHGJmcxgMBtDBevFZlFG
 8f0olImncJmwdg76yYgNJxefnNfqYT/XaDlcWD3SSY5TARReGRtvRVL28hihkKL7
 6/66sRzDssQ5/d379pFMxtgrGxEBRs78nIo2Ntxs3Da//+ayjTvoeCOQu+EUvOdu
 rqDE01dsrXOdMP04od4SaWeBO8FZgQAxSjKRgaub/tjc8X0nclzKaConpT0egtgT
 UE1dsQrkNYHZOnvKkNTkV7NnF9s8gOXNkHey5ycy/IYzYD8ym/l/n3hNTNfdXlWm
 MvFMyHTEetg7NgZ1XSyeeRRYGMkTE25FWi3Hj4oY7EjXIgPVQ4g=
 =gSpB
 -----END PGP SIGNATURE-----

Clarified README.
```

## Producing the signature image

The interesting thing about the commit message above is that it is exactly what is needed to sign or verify, with the exception of the signature itself.

In the Git source code, the file `commit.c` contains a function, [`write_commit_tree`](https://github.com/git/git/blob/c3ebe91b40c23a1b70dba36383a23016711d8bc0/commit.c#L1648), which is used to write the above information (without the signature) which is then signed (or verified) by `gpg` or `ssh-keygen` called from within Git.

To verify this, we copy the part of the commit tree to a new file, `signed_data.txt`. This removes the signature from the middle of the file, and leaves the blank line separating the signature from the commit message. This is just a regular text file, including a trailing newline character.

```
tree de2e850dc1fab0387be6a3ae3f22546dff6631bd
parent ed858de10c8bc82a8819d20a5cd0f5748d570bf2
author Wolf McNally <wolf@wolfmcnally.com> 1709292982 -0800
committer Wolf McNally <wolf@wolfmcnally.com> 1709292982 -0800

Clarified README.
```

We also copy the signature itself to `signature.asc`. The blank line after the `BEGIN PGP SIGNATURE` header must be preserved:

```
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEElDZS7jhEF2DD3DU2S2wvz4lHgK4FAmXhvbYACgkQS2wvz4lH
gK6ZFxAAkkAEthu4Cxqz/KgH4C+OeNH4tauGkFzgus6MkwyeqoVLCGxqQ3bYfDLM
s6J5LovbMXNiPkloiaTB8XPtVQFI37+Vz2RGXqJnxUAOxa6WasOjJUItRR6G+zjJ
QKeHz1DP5JXoEGfxkD6wPXFkOzvd6mhWYYrlduNAr44p17Vhq2w7JCLDm7ukBCJD
DI6DObfFvwwXRV4xalLPluSIF079uatjbWJC3O1FOa0fFYrusuWxakMzXHtwOEtU
vBurctpwf6qJUicBNymTlMx7HKPYqh5rVBQWOVC5BGJZtrikQN0GmCuDsp7HWdYB
2xGaQVfWRQqVz3POfLqLqq+D95RpEerqmnmtHd0NJx+gwHGJmcxgMBtDBevFZlFG
8f0olImncJmwdg76yYgNJxefnNfqYT/XaDlcWD3SSY5TARReGRtvRVL28hihkKL7
6/66sRzDssQ5/d379pFMxtgrGxEBRs78nIo2Ntxs3Da//+ayjTvoeCOQu+EUvOdu
rqDE01dsrXOdMP04od4SaWeBO8FZgQAxSjKRgaub/tjc8X0nclzKaConpT0egtgT
UE1dsQrkNYHZOnvKkNTkV7NnF9s8gOXNkHey5ycy/IYzYD8ym/l/n3hNTNfdXlWm
MvFMyHTEetg7NgZ1XSyeeRRYGMkTE25FWi3Hj4oY7EjXIgPVQ4g=
=gSpB
-----END PGP SIGNATURE-----
```

We can then verify the signature:

```shell
$ gpg --verify signature.asc signed_data.txt
```

```
gpg: Signature made Fri Mar  1 03:36:22 2024 PST
gpg:                using RSA key 943652EE38441760C3DC35364B6C2FCF894780AE
gpg: Good signature from "Wolf McNally <wolf@wolfmcnally.com>" [ultimate]
```

Therefore we now understand how Git produces the image used to sign. I haven't tried this with an SSH-signed commit yet, but I think it will work exactly the same way as a GPG-signed commit.