#1137357 gpg-from-sq: provide a way to provide (or default to) deterministic signatures

#1137357#5
Date:
2026-05-22 22:02:20 UTC
From:
To:
I'm trying to get Git's testsuite to work with the Sequoia-PGP
chameleon.  However, even with a faked system time, Sequoia includes a
salt annotation in signatures, which results in non-deterministic
output.  Because Git object IDs are generated from a hash which covers
the signature, this causes objects to differ and therefore tests to
fail.

We'd need Sequoia to provide some way to provide deterministic
signatures for at least v4 signatures, and probably v6 signatures as
well.  I realize that v6 does not intend to allow this, but it is
functionally required for testsuites as well as some cases with
reproducible builds[0].

Could you please add support for some method for signing reproducibly,
ideally either based on `--faked-system-time` or `SOURCE_BUILD_EPOCH`?

[0] While this might not be useful for _Debian_ reproducible builds, it
is useful for _general_ reproducible builds where a trusted authority
signs their builds in a reproducible way or includes a signature inside
an archive which must be bit-for-bit identical.

#1137357#10
Date:
2026-05-26 12:48:32 UTC
From:
To:
Hi,
I’m not sure that’s doable. It might be for RSA signatures (if they use RSASSA-PKCS1-v1_5), but even RSASSA-PSS signatures are non-deterministic already and depend on that non-determinism for their security properties.

The same applies for ECDSA signatures by default (there is a deterministic variant in RFC 6979, but RFC 9580 doesn’t mention that RFC, so I’m guessing OpenPGP doesn’t support that).

ML-DSA signatures are have a random component by nature.

Long-term, it seems like the better solution to not assume that the used signature scheme is deterministic, and change the tests to not expect a fixed hash.


Note: I’m not involved with Debian maintenance of this package, just here to provide context.

#1137357#15
Date:
2026-05-26 21:19:23 UTC
From:
To:
The trend regarding signatures in Reproducible Builds is towards "signatures are
build inputs", meaning:

- you build an unsigned artifact
- sign it with your private key out-of-band
- declare a 2nd build, with your signatures and unsigned artifact as build input
- the 2nd build merges them together, without private key access

This is necessary or the independent verifier would not be able to reproduce
anything, unless you share your private key with them - either by permanently
revealing the secret number, or letting them borrow your hardware signing key.

This two-step-build-sign-out-of-band is how Debian handles secure boot
signatures and the story behind the linux-binary-unsigned-* packages.

You could attempt to do this in one build step, by building once with private
key access, extract the signatures, add them to your declared build inputs, then
build again with an oracle that hands out the corresponding pre-computed
signatures when asked to sign a specific sha256 (without actually being able to
issue any new signatures).

This approach is more fragile though.

Of course the most elegant solution is "avoid signing keys unless absolutely
necessary", for example there's an ongoing effort to complement Linux kernel
module signing with a merkle-tree based alternative that doesn't depend on
secret numbers for security:

https://lwn.net/Articles/1012946/

Sincerely,
kpcyrd

#1137357#20
Date:
2026-05-27 17:40:56 UTC
From:
To:
It's actually worse than that. Several cryptographic signing algorithms require nonces (long random values); to get the same signature result, you'd need the same artifact, same private key, *and* same nonce.

However, in several algorithms, if you *ever* reuse a nonce for a differen artifact and a given private key, you reveal the private key. So if you retain a nonce, generate something but it turns out to be different, and sign, you've exposed the private key. This footgun will happen sooner or later if you try to re-sign with the same private key in a way that reproduces the final signature.

Things also get weird when you have hardware keys where the secret key *cannot* be extracted. When (not if) the key dies, does that mean that you can't reproduce the artifact? The correct answer is obviously no.

Signatures should *not* be considered part of the item you're reproducing. Signatures attest something about an artifact; added signatures of attestation do not change the artifact being attested.
--- David A. Wheeler
#1137357#25
Date:
2026-05-28 02:30:34 UTC
From:
To:
Ed25519 is deterministic and smart ECDSA implementers use deterministic
ECDSA as well.  Requiring randomness in signatures exposes your private
key when you have a bad CSPRNG.

Unfortunately, you're at least a decade too late to hold that position
when it comes to Git objects.  Git includes the signature as part of the
object ID and there is no plan to change that.  In fact, I agree with
that decision since it makes the signature functionally impossible to
modify or remove.

The current Git testsuite requires objects to hold the same object ID
when signed with `gpg --faked-system-time` and if that doesn't happen,
then Sequoia will simply not be supported in Git's testsuite[0].  There are
other changes for Sequoia to work properly and I don't have any plans to
send those upstream until there is a version in Debian unstable that
will pass the testsuite.

Since I use Sequoia as `gpg`, I would like it to be supported since not
having it prevents me from running signing tests, which as a Git
developer (and specifically, as the one doing the SHA-1/SHA-256
interoperability work) I would like to run without hassle.

[0] While we have moved away from fixed object IDs in the testsuite as
much as possible, the code in question tests the SHA-1/SHA-256 object
conversion code where we really want to have bit-for-bit identical
objects so we know that the conversion code for an algorithm produces
the same code as creating a repository natively in that algorithm.
Hence, we use the object IDs to verify that the objects are identical in
both cases.

#1137357#30
Date:
2026-05-29 16:22:19 UTC
From:
To:
I was talking about this in the context of building packages/containers; I was
*not* including the context of signing source code (which is used as an *input*
to a build process for creating packages/containers).

The mere *presence* of executable built artifacts in a source git repo
is often considered a serious security concern. OpenSSF Scorecard's
"Binary-Artifacts" identifies executable built artifacts in a git repo as a high risk:
https://github.com/ossf/scorecard/blob/main/docs/checks.md#binary-artifacts
It lists these "Problems with generated executable (binary) artifacts":
    • Binary artifacts cannot be reviewed, allowing possible obsolete or maliciously subverted executables. Reviews generally review source code, not executables, since it's difficult to audit executables to ensure that they correspond to the source code. Over time the included executables might not correspond to the source code.
    • Generated executables allow the executable generation process to atrophy, which can lead to an inability to create working executables. These problems can be countered with verified reproducible builds, but it's easier to implement verified reproducible builds when executables are not included in the source repository (since the executable generation process is less likely to have atrophied).

If we can't reproduce a commit object in the *source* repo, but we can verify it,
that's not a problem. When reading source, we just want to know "can we verify
that it's signed by a key I find acceptable", not "can I recreate the signature?".
In fact, being able to indpendently reproduce arbitrary signatures in a source repo
would be a serious vulnerability, that's forging with extra steps :-).

I wish my best to all working on the SHA-256 implementation in git!!
--- David A. Wheeler