public inbox for git@vger.kernel.org
 help / color / mirror / Atom feed
From: Justin Tobler <jltobler@gmail.com>
To: git@vger.kernel.org
Cc: sandals@crustytoothpaste.net, christian.couder@gmail.com,
	ps@pks.im, gitster@pobox.com, peff@peff.net,
	Justin Tobler <jltobler@gmail.com>
Subject: [PATCH v6 0/3] fast-import: add mode to re-sign invalid commit signatures
Date: Thu, 12 Mar 2026 20:39:35 -0500	[thread overview]
Message-ID: <20260313013938.2742124-1-jltobler@gmail.com> (raw)
In-Reply-To: <20260312192228.481134-1-jltobler@gmail.com>

Greetings,

With c20f112e51 (fast-import: add 'strip-if-invalid' mode to
--signed-commits=<mode>, 2025-11-17), it became possible to remove
invalid signatures from commits via git-fast-import(1) while maintaining
valid commit signatures. Building upon this functionality, a user may
want to re-sign these invalid commit signatures. This series introduces
the `sign-if-invalid` mode to do so accordingly.

The newly added mode in this series currently ignores
`extensions.compatObjectFormat` when generating the new signatures. From
my understanding, to generate the compatibility structure would also
require us to reconstruct the compatibility object for the object being
signed. I think this would be possible to do, but would require getting
the mapped OIDs for the commit parents and tree. I'm not completely sure
of a good way to go about this yet though. I'm also not completely
certain if this is something that should be addressed as part of this
series, or could be done later down the road. So for now I've opted to
delay its implementation. I'm open going down the other route if that is
preferred though.

The first commit is a simple cleanup for something I noticed while
reading though commit signing code. The second commit actually
introduces the new `--signed-commits` mode.

Changes since V5:
- Fixed a test that was incorrectly referencing the openpgp-signing
  branch when it should be using the ssh-signing branch.
- Changed warning message wording.
- Added some parentheses in a conditional statement to clarify operation
  order.

Changes since V4:
- Instead of introducing a separate `sign_buffer_with_key()` helper,
  extend `sign_buffer()` to support a SIGN_BUFFER_USE_DEFAULT_KEY flag.
- Fixed message in die().

Changes since V3:
- Rename the `re-sign-if-invalid` mode to `sign-if-invalid`. The
  "if-invalid" already implies the signatures was previously signed
  making "re-sign" redundant.

Changes since V2:
- Adapted commit message in second patch to improve clarity.
- Fixed typos.
- Renamed SIGN_RESIGN_IF_INVALID to SIGN_RE_SIGN_IF_INVALID.
- Created separate helper function to handle printing invalid signature
  warnings.

Changes since V1:
- Improved commit messages and comments to better explain why
  interoperability mode is not currently supported.
- Clarified documentation for re-sign-if-invalid mode.
- Renamed `handle_invalid_signature()` to `handle_signature_if_invalid()`.
- Added warning messages specific to commit resigning.
- Fixed some small typos.
- Added support for explicitly specifying the signing key ID via
  `--signed-commits=re-sign-if-invalid[=<keyid>]` similar to how it can
  specified in git-commit(1).
- We now die() as unsupported when attempting to re-sign an invalid
  commit signature in interoperability mode.
- We now die() when failing to re-sign a commit.

Thanks,
-Justin

Justin Tobler (3):
  commit: remove unused forward declaration
  gpg-interface: allow sign_buffer() to use default signing key
  fast-import: add mode to sign commits with invalid signatures

 Documentation/git-fast-import.adoc |   4 +
 builtin/fast-export.c              |   8 +-
 builtin/fast-import.c              | 101 +++++++++++++++-----
 builtin/tag.c                      |   4 +-
 commit.c                           |  19 +---
 commit.h                           |   2 -
 gpg-interface.c                    |  36 ++++++--
 gpg-interface.h                    |  19 +++-
 send-pack.c                        |   2 +-
 t/t9305-fast-import-signatures.sh  | 144 ++++++++++++++++++-----------
 10 files changed, 231 insertions(+), 108 deletions(-)

Range-diff against v5:
1:  0d00b72ee0 = 1:  0d00b72ee0 commit: remove unused forward declaration
2:  7a0deed77b ! 2:  5224c1766f gpg-interface: allow sign_buffer() to use default signing key
    @@ gpg-interface.c: const char *gpg_trust_level_to_str(enum signature_trust_level l
      	gpg_interface_lazy_init();
      
     -	return use_format->sign_buffer(buffer, signature, signing_key);
    -+	if (flags & SIGN_BUFFER_USE_DEFAULT_KEY && (!signing_key || !*signing_key))
    ++	if ((flags & SIGN_BUFFER_USE_DEFAULT_KEY) && (!signing_key || !*signing_key))
     +		signing_key = keyid_to_free = get_signing_key();
     +
     +	ret = use_format->sign_buffer(buffer, signature, signing_key);
3:  e659971e84 ! 3:  d9ad73e05b fast-import: add mode to sign commits with invalid signatures
    @@ builtin/fast-import.c: static void handle_strip_if_invalid(struct strbuf *new_da
     +		break;
     +	case SIGN_SIGN_IF_INVALID:
     +		if (subject_len > 100)
    -+			warning(_("signing commit with invalid signature for '%.100s...'\n"
    ++			warning(_("replacing invalid signature for commit '%.100s...'\n"
     +				  "  allegedly by %s"), subject, signer);
     +		else if (subject_len > 0)
    -+			warning(_("signing commit with invalid signature for '%.*s'\n"
    ++			warning(_("replacing invalid signature for commit '%.*s'\n"
     +				  "  allegedly by %s"), subject_len, subject, signer);
     +		else
    -+			warning(_("signing commit with invalid signature\n"
    ++			warning(_("replacing invalid signature for commit\n"
     +				  "  allegedly by %s"), signer);
     +		break;
     +	default:
    @@ t/t9305-fast-import-signatures.sh: test_expect_success GPG 'strip both OpenPGP s
     +			test_grep "stripping invalid signature" log &&
     +			test_grep ! -E "^gpgsig" actual
     +		else
    -+			test_grep "signing commit with invalid signature" log &&
    ++			test_grep "replacing invalid signature" log &&
     +			test_grep -E "^gpgsig(-sha256)? " actual &&
     +			git -C new verify-commit "$IMPORTED"
     +		fi
    @@ t/t9305-fast-import-signatures.sh: test_expect_success GPG 'strip both OpenPGP s
      	rm -rf new &&
      	git init new &&
      
    -@@ t/t9305-fast-import-signatures.sh: test_expect_success GPG 'strip signature invalidated by message change with --si
    - 	# corresponding `data <length>` command would have to be changed too.
    - 	sed "s/OpenPGP signed commit/OpenPGP forged commit/" output >modified &&
    +-	git fast-export --signed-commits=verbatim openpgp-signing >output &&
    ++	git fast-export --signed-commits=verbatim ssh-signing >output &&
      
    + 	# Change the commit message, which invalidates the signature.
    + 	# The commit message length should not change though, otherwise the
    + 	# corresponding `data <length>` command would have to be changed too.
    +-	sed "s/OpenPGP signed commit/OpenPGP forged commit/" output >modified &&
    +-
     -	git -C new fast-import --quiet --signed-commits=strip-if-invalid <modified >log 2>&1 &&
    -+	# Configure the target repository with an invalid default signing key.
    -+	test_config -C new user.signingkey "not-a-real-key-id" &&
    -+	test_config -C new gpg.format ssh &&
    -+	test_config -C new gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
    -+	test_must_fail git -C new fast-import --quiet \
    -+		--signed-commits=sign-if-invalid <modified >/dev/null 2>&1 &&
    -+
    -+	# Import using explicitly provided signing key.
    -+	git -C new fast-import --quiet \
    -+		--signed-commits=sign-if-invalid="${GPGSSH_KEY_PRIMARY}" <modified &&
    - 
    - 	IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
    - 	test $OPENPGP_SIGNING != $IMPORTED &&
    - 	git -C new cat-file commit "$IMPORTED" >actual &&
    +-
    +-	IMPORTED=$(git -C new rev-parse --verify refs/heads/openpgp-signing) &&
    +-	test $OPENPGP_SIGNING != $IMPORTED &&
    +-	git -C new cat-file commit "$IMPORTED" >actual &&
     -	test_grep ! -E "^gpgsig" actual &&
     -	test_grep "stripping invalid signature" log
     -'
    @@ t/t9305-fast-import-signatures.sh: test_expect_success GPG 'strip signature inva
     -	IMPORTED=$(git -C new rev-parse --verify refs/heads/x509-signing) &&
     -	test $X509_SIGNING = $IMPORTED &&
     -	git -C new cat-file commit "$IMPORTED" >actual &&
    - 	test_grep -E "^gpgsig(-sha256)? " actual &&
    +-	test_grep -E "^gpgsig(-sha256)? " actual &&
     -	test_must_be_empty log
     -'
     -
     -test_expect_success GPGSSH 'keep valid SSH signature with --signed-commits=strip-if-invalid' '
     -	rm -rf new &&
     -	git init new &&
    --
    --	test_config -C new gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
    --
    ++	sed "s/SSH signed commit/SSH forged commit/" output >modified &&
    + 
    ++	# Configure the target repository with an invalid default signing key.
    ++	test_config -C new user.signingkey "not-a-real-key-id" &&
    ++	test_config -C new gpg.format ssh &&
    + 	test_config -C new gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" &&
    ++	test_must_fail git -C new fast-import --quiet \
    ++		--signed-commits=sign-if-invalid <modified >/dev/null 2>&1 &&
    ++
    ++	# Import using explicitly provided signing key.
    ++	git -C new fast-import --quiet \
    ++		--signed-commits=sign-if-invalid="${GPGSSH_KEY_PRIMARY}" <modified &&
    + 
     -	git fast-export --signed-commits=verbatim ssh-signing >output &&
     -	git -C new fast-import --quiet --signed-commits=strip-if-invalid <output >log 2>&1 &&
    --	IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
    + 	IMPORTED=$(git -C new rev-parse --verify refs/heads/ssh-signing) &&
     -	test $SSH_SIGNING = $IMPORTED &&
    --	git -C new cat-file commit "$IMPORTED" >actual &&
    --	test_grep -E "^gpgsig(-sha256)? " actual &&
    ++	test $SSH_SIGNING != $IMPORTED &&
    + 	git -C new cat-file commit "$IMPORTED" >actual &&
    + 	test_grep -E "^gpgsig(-sha256)? " actual &&
     -	test_must_be_empty log
     +	git -C new verify-commit "$IMPORTED"
      '

base-commit: 7c02d39fc2ed2702223c7674f73150d9a7e61ba4
-- 
2.53.0.381.g628a66ccf6


  parent reply	other threads:[~2026-03-13  1:39 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-23 19:41 [PATCH 0/2] fast-import: add mode to re-sign invalid commit signatures Justin Tobler
2026-02-23 19:41 ` [PATCH 1/2] commit: remove unused forward declaration Justin Tobler
2026-02-24  9:35   ` Patrick Steinhardt
2026-02-23 19:41 ` [PATCH 2/2] fast-import: add mode to re-sign invalid commit signatures Justin Tobler
2026-02-24  9:33   ` Patrick Steinhardt
2026-02-24 18:33     ` Justin Tobler
2026-02-24 13:40 ` [PATCH 0/2] " Christian Couder
2026-02-24 22:41 ` brian m. carlson
2026-02-24 22:45   ` Junio C Hamano
2026-03-02 22:49   ` Justin Tobler
2026-03-06 20:53 ` [PATCH v2 0/3] " Justin Tobler
2026-03-06 20:53   ` [PATCH v2 1/3] commit: remove unused forward declaration Justin Tobler
2026-03-06 20:53   ` [PATCH v2 2/3] gpg-interface: introduce sign_buffer_with_key() Justin Tobler
2026-03-10  9:01     ` Christian Couder
2026-03-10 18:04       ` Justin Tobler
2026-03-06 20:53   ` [PATCH v2 3/3] fast-import: add mode to re-sign invalid commit signatures Justin Tobler
2026-03-10  9:27     ` Christian Couder
2026-03-10 18:09       ` Justin Tobler
2026-03-10 20:11   ` [PATCH v3 0/3] " Justin Tobler
2026-03-10 20:11     ` [PATCH v3 1/3] commit: remove unused forward declaration Justin Tobler
2026-03-10 22:29       ` Junio C Hamano
2026-03-10 20:11     ` [PATCH v3 2/3] gpg-interface: introduce sign_buffer_with_key() Justin Tobler
2026-03-10 22:33       ` Junio C Hamano
2026-03-10 20:11     ` [PATCH v3 3/3] fast-import: add mode to re-sign invalid commit signatures Justin Tobler
2026-03-10 20:49     ` [PATCH v3 0/3] " Junio C Hamano
2026-03-10 21:06       ` Justin Tobler
2026-03-10 21:20         ` Junio C Hamano
2026-03-10 22:13           ` Justin Tobler
2026-03-10 22:39             ` Junio C Hamano
2026-03-10 23:03               ` Justin Tobler
2026-03-11 17:31     ` [PATCH v4 " Justin Tobler
2026-03-11 17:31       ` [PATCH v4 1/3] commit: remove unused forward declaration Justin Tobler
2026-03-11 17:31       ` [PATCH v4 2/3] gpg-interface: introduce sign_buffer_with_key() Justin Tobler
2026-03-12 10:22         ` Patrick Steinhardt
2026-03-12 13:58           ` Justin Tobler
2026-03-11 17:31       ` [PATCH v4 3/3] fast-import: add mode to sign commits with invalid signatures Justin Tobler
2026-03-12 10:23         ` Patrick Steinhardt
2026-03-12 14:08           ` Justin Tobler
2026-03-12 14:22             ` Patrick Steinhardt
2026-03-12 17:21               ` Justin Tobler
2026-03-12 19:22       ` [PATCH v5 0/3] fast-import: add mode to re-sign invalid commit signatures Justin Tobler
2026-03-12 19:22         ` [PATCH v5 1/3] commit: remove unused forward declaration Justin Tobler
2026-03-12 19:22         ` [PATCH v5 2/3] gpg-interface: allow sign_buffer() to use default signing key Justin Tobler
2026-03-12 20:20           ` Junio C Hamano
2026-03-12 20:24             ` Justin Tobler
2026-03-12 19:22         ` [PATCH v5 3/3] fast-import: add mode to sign commits with invalid signatures Justin Tobler
2026-03-12 20:20           ` Junio C Hamano
2026-03-12 20:29             ` Justin Tobler
2026-03-12 23:58           ` Jeff King
2026-03-13  0:17             ` Justin Tobler
2026-03-12 20:20         ` [PATCH v5 0/3] fast-import: add mode to re-sign invalid commit signatures Junio C Hamano
2026-03-12 20:30           ` Justin Tobler
2026-03-13  1:39         ` Justin Tobler [this message]
2026-03-13  1:39           ` [PATCH v6 1/3] commit: remove unused forward declaration Justin Tobler
2026-03-13  1:39           ` [PATCH v6 2/3] gpg-interface: allow sign_buffer() to use default signing key Justin Tobler
2026-03-13  6:31             ` Patrick Steinhardt
2026-03-13  1:39           ` [PATCH v6 3/3] fast-import: add mode to sign commits with invalid signatures Justin Tobler
2026-03-13  6:31             ` Patrick Steinhardt
2026-03-13  4:29           ` [PATCH v6 0/3] fast-import: add mode to re-sign invalid commit signatures Junio C Hamano
2026-03-13  6:31             ` Patrick Steinhardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260313013938.2742124-1-jltobler@gmail.com \
    --to=jltobler@gmail.com \
    --cc=christian.couder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    --cc=ps@pks.im \
    --cc=sandals@crustytoothpaste.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox