Skip to content

Accept subkey signatures #2905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 20, 2025
Merged

Accept subkey signatures #2905

merged 4 commits into from
Aug 20, 2025

Conversation

mtrmac
Copy link
Collaborator

@mtrmac mtrmac commented Jul 21, 2025

Accept simple signing signatures made using a subkey.

This currently breaks because we insist that signature verification reports using a key which we know we have imported.

For the openpgp mechanism, modify verification to report the primary key’s fingerprint.
For GPGME, the information is not easily available (well, we’d have to collect subkey fingerprints on import, and that would affect public API); instead, if the returned fingerprint does not match, do another GPG operation to find the primary key’s fingerprint.

To do this, centralize the key identity matching a bit more in verifyAndExtractSignature.

See individual commit messages for details.


We need this because Sequoia-PGP generates, by default, keys where the primary key can only certify subkeys, and signing happens using a subkey. So, we must support signatures by subkeys in the other mechanism implementations.

See https://github.com/mtrmac/image/tree/sequoia-interop for a proof that this allows accepting Sequoia-PGP keys (for now, by GPGME at least).

Some users also want to use subkeys for other uses, so this will resolve containers/podman#16406 , but …


WARNING: Adding support for subkeys makes subkey revocation relevant. Revocation is always messy — to support long-term signature validity (which is very relevant for container image signing), smooth handling of revocation might require trusted timestamps (not natively supported in OpenPGP).

In practice, this library (partially out of necessity) lets the underlying OpenPGP implementations impose their own policy, and that handling DIFFERS between various SigningMechanism implementations: it seems that GnuPG and x/openpgp refuse to use a revoked subkey regardless of revocation time, while Sequoia-PGP decides based on the revocation reason whether the revocation applies to all signatures or only to signatures (supposedly!!) made after the revocation happened.

It is STRONGLY recommended to avoid all of this complexity, and to plan for workflows where subkey revocation never happens. Just revoke and reissue the whole key — either way you'll need to distribute an updated key to all
consumers.

@mtrmac mtrmac force-pushed the verify-subkeys branch 4 times, most recently from 16b1b24 to b40f9b8 Compare July 23, 2025 22:21
@mtrmac mtrmac changed the title DO NOT MERGE IRRESPONSIBLE: Accept subkey signatures Accept subkey signatures Jul 23, 2025
@mtrmac
Copy link
Collaborator Author

mtrmac commented Jul 23, 2025

@drGrove I think this PR’s approach seems viable, at least for my purpose of Sequoia interoperability.

Would that suit your purposes as well?

@mtrmac mtrmac marked this pull request as ready for review July 23, 2025 22:33
@mtrmac
Copy link
Collaborator Author

mtrmac commented Jul 23, 2025

(Marked as ready for review.)

}
// With https://github.com/proglottis/gpgme/pull/42, we could just
// return key.Fingerprint(), nil
subkey := key.SubKeys()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subkey returns a *SubKey, I think we'll want to iterate through this subkey.Next() until we hit the end. Currently the test keys only have a single signing subkey, but there is a chance that a subkey could also be an encryption or authentication subkey. Since a Primary key can have multiple signing subkeys AND signatures are only valid if they come from a signing subkey (certify key is only valid for signing another gpg key) we may need to return an slice

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine a similar type of implementation will be needed in sequoia as well

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reading this I'm realizing that we are providing the subkey fingerprint to get back the primary for comparison sake. The validation concern probably isn't a problem on the gpg side as the signature verification logic should already handle that but may be on the sequoia side (it's been a while since I've looked over the rust library but I remember it being pretty low level).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reading this I'm realizing that we are providing the subkey fingerprint to get back the primary for comparison sake.

Yes. The first element of Subkeys is the primary key.

The validation concern probably isn't a problem on the gpg side as the signature verification logic should already handle that

Yes.

but may be on the sequoia side (it's been a while since I've looked over the rust library but I remember it being pretty low level).

That’s handled as well, compare #2569 (comment) . But note the warning in the PR description.

@drGrove
Copy link

drGrove commented Jul 24, 2025

Would that suit your purposes as well?

Yes, this works just fine for me. Subkey pinning was a secondary thought and not something I'm necessarily concerned about currently.

I was also able to vendor this into a build of skopeo and do standalone verification on signatures I've made with my signing subkey using the gpgme impl.

Copy link
Member

@Luap99 Luap99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bit far out of my normal review comfort zone, anyway
LGTM

@TomSweeneyRedHat
Copy link
Member

LGTM
but I'd really like a head nod from @nalind or @giuseppe too

mtrmac added 4 commits August 19, 2025 22:37
Encapsulate the wanted/recorded tuples a bit more, to prepare for
changes to the signatureAcceptanceRules type.

Should not change (test) behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
…ryKeyFingerprints

Move more code into the centralized function, to allow us to change
the implementation in the future.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
Document how the key identities from NewEphemeralGPGSigningMechanism
and SigningMechanism should relate.

For the GPGME implementation where the relationship isn't as desired, introduce
signingMechanismWithVerificationIdentityLookup .

For the openpgp implementation, just fix the returned value to match
new expecations.

Currently, the simple signing verifyAndExtractSignature rejects
subkey signatures for both mechanism implementations, so this does not
change behavior for any previously-accepted signatures (but it might
affect theoretical external direct callers of SigningMechanism).

We will actually use this in the next commit.

WARNING: Adding support for subkeys makes subkey revocation relevant.
Revocation is always messy - to support long-term signature validity
(which is very relevant for container image signing), smooth
handling of revocation might require trusted timestamps (not natively
supported in OpenPGP).

In practice, this library (partially out of necessity) lets the underlying
OpenPGP implementations impose their own policy, and that handling DIFFERS
between various SigningMechanism implementations: it seems that GnuPG
and refuses to use a revoked subkey regardless of revocation time, while
Sequoia-PGP decides based on the revocation reason whether the revocation
applies to all signatures or only to signatures (supposedly!!) made after the
revocation happened.

It is STRONGLY recommended to avoid all of this complexity, and to plan
for workflows where subkey revocation never happens. Just revoke and reissue
the whole key - either way you'll need to distribute an updated key to all
consumers.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This does not change behavior for mechanisms which already always return the
primary key fingerprint (after a recent change, openpgp); for the others,
add support for signingMechanismWithVerificationIdentityLookup .

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
@mtrmac mtrmac merged commit ed9ae38 into containers:main Aug 20, 2025
10 checks passed
@mtrmac mtrmac deleted the verify-subkeys branch August 20, 2025 17:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unable to pull and verify images signed with a GPG *subkey* ("None of the signatures were accepted")
4 participants