Git development
 help / color / mirror / Atom feed
* [RFC PATCH 0/4] sign a SHA-256 digest of the tree in commits and tags
@ 2026-10-02  8:18 Scott Chacon
  2026-10-02  8:18 ` [RFC PATCH 1/4] tree-sha256: hash the contents of a tree with SHA-256 Scott Chacon
                   ` (5 more replies)
  0 siblings, 6 replies; 22+ messages in thread
From: Scott Chacon @ 2026-10-02  8:18 UTC (permalink / raw)
  To: git

I'm concerned about the ecosystem impact of moving the `git init` default
hashing function to SHA-256 in 3.0. I have suggested that it may be more 
feasible with similar benefits to add the ability to inject an independently
calculated and verifiable tree content sha into signed objects instead.

This RFC series is meant to demonstrate how this might work.

It adds the ability to directly rehash the full tree contents when signing a
commit or tag with SHA-256 without the repository needing to be in the sha256
object format.

In this series "git tag -s --hash=sha256" and "git commit -S --hash=sha256" 
compute a SHA-256 digest over every file in the tree (and submodules) and put
that additional hash in a header before signing:

  object 78bd45828aa36fbde3161f49da15272dff3d06f5
  type commit
  tag v1.0
  tagger A U Thor <author@example.com> 1790749714 +0200
  tree-sha256 775aff90d07c9a73f19ef83ab89bd8e95d1d835325d53cc57a2232b015783d89

  Release 1.0
  -----BEGIN SSH SIGNATURE-----

For a commit it goes after "committer", before "gpgsig". Setting
gpg.treeHash=sha256 makes it the default for everything you sign.

The digest is SHA-256 over one record per file, sorted by path:

  <hex sha256 of content> SP <path> NUL

The file mode isn't included. Submodules are followed into their own
repositories and contribute "<hex digest of their tree> SP <path>/ NUL",
so the signature covers their contents too; if a submodule isn't
available, we fail rather than sign something we can't vouch for.

Old versions of Git are fine with the new header: fsck ignores extra
headers after "tagger" by default (and always for commits), and "git
tag -v" and "git verify-commit" check the signature as before.

  - Patch 1 adds the digest, with a test-tool helper so it can be
    tested on its own.
  - Patches 2 and 3 add --hash to "git tag" and "git commit".
  - Patch 4 adds gpg.treeHash.

From a speed perspective, it's not fast but it's not slow. The default
build on my M5 is 245ms for a git.git signed tag call, ~5s for the Linux
tree. An accelerated OpenSSL build is 135ms for git.git, 1.8s for Linux.

However, this is single threaded. We could easily do parallel hashing which
should make it many times faster - my previous tests in Rust on 18 threads
on my M5 did git.git in 36ms and Linux tree in 0.5s (verified the same hash).

Not in this series, and what I'd like opinions on:

  - Any interest? Would the list find this approach a viable alternative
    to not switching the default hash function to sha-256 in 3.0? Not that
    it wouldn't be an available object format, but that it wouldn't need to
    be the default one.

  - Verification. "git tag -v" and "git verify-commit" don't recompute
    the digest yet. I'd like to agree on the format before adding that.

  - Excluding submodules. Large projects can have submodules that most
    people never check out, and they can't sign with --hash today. One
    option is an "excluded:<commit>" header that still covers the
    pinned commit but not its contents, with a header listing the
    excluded paths so that verification can report them.

  - Naming. The header is "tree-sha256", the option "--hash", and the
    config "gpg.treeHash". I'm not attached to any of them.

Scott Chacon (4):
  tree-sha256: hash the contents of a tree with SHA-256
  tag: add --hash=sha256 to sign a tree-sha256 header
  commit: add --hash=sha256 to sign a tree-sha256 header
  gpg: add gpg.treeHash to sign a tree-sha256 header by default

 Documentation/config/gpg.adoc |   6 +
 Documentation/git-commit.adoc |  11 +-
 Documentation/git-tag.adoc    |  11 +-
 Makefile                      |   2 +
 builtin/commit.c              |  46 ++++++-
 builtin/tag.c                 |  41 +++++-
 meson.build                   |   1 +
 t/helper/meson.build          |   1 +
 t/helper/test-tool.c          |   1 +
 t/helper/test-tool.h          |   1 +
 t/helper/test-tree-sha256.c   |  31 +++++
 t/meson.build                 |   2 +
 t/t1018-tree-sha256.sh        | 123 +++++++++++++++++
 t/t7032-tree-sha256-signed.sh | 169 +++++++++++++++++++++++
 tree-sha256.c                 | 247 ++++++++++++++++++++++++++++++++++
 tree-sha256.h                 |  36 +++++
 16 files changed, 720 insertions(+), 9 deletions(-)
 create mode 100644 t/helper/test-tree-sha256.c
 create mode 100755 t/t1018-tree-sha256.sh
 create mode 100755 t/t7032-tree-sha256-signed.sh
 create mode 100644 tree-sha256.c
 create mode 100644 tree-sha256.h


base-commit: a018953688f1b10bddf91bff8747068f5f4746a4
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2026-10-07 21:07 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-02  8:18 [RFC PATCH 0/4] sign a SHA-256 digest of the tree in commits and tags Scott Chacon
2026-10-02  8:18 ` [RFC PATCH 1/4] tree-sha256: hash the contents of a tree with SHA-256 Scott Chacon
2026-10-02 15:45   ` Junio C Hamano
2026-10-02  8:18 ` [RFC PATCH 2/4] tag: add --hash=sha256 to sign a tree-sha256 header Scott Chacon
2026-10-02 15:49   ` Junio C Hamano
2026-10-02  8:18 ` [RFC PATCH 3/4] commit: " Scott Chacon
2026-10-02  8:18 ` [RFC PATCH 4/4] gpg: add gpg.treeHash to sign a tree-sha256 header by default Scott Chacon
2026-10-02 15:52 ` [RFC PATCH 0/4] sign a SHA-256 digest of the tree in commits and tags Junio C Hamano
2026-10-02 19:06 ` brian m. carlson
2026-10-05  9:32   ` Scott Chacon
2026-10-05 12:41     ` Patrick Steinhardt
2026-10-05 14:16       ` Scott Chacon
2026-10-05 22:57         ` brian m. carlson
2026-10-06 13:36         ` Johannes Schindelin
2026-10-06 16:16       ` Kristoffer Haugsbakk
2026-10-06 21:55         ` brian m. carlson
2026-10-06 22:38           ` Junio C Hamano
2026-10-06 23:40             ` brian m. carlson
2026-10-06  9:00   ` Christian Couder
2026-10-06 22:26     ` brian m. carlson
2026-10-07 12:26       ` Christian Couder
2026-10-07 21:07         ` brian m. carlson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox