- Package:
- gpg-from-sq
- Source:
- gpg-from-sq
- Submitter:
- brian m. carlson
- Date:
- 2026-05-29 16:25:02 UTC
- Severity:
- normal
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.
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.
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
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
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.
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