-
Notifications
You must be signed in to change notification settings - Fork 372
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
RFE: add support for multiple OpenPGP signatures per package #3385
Comments
@simo5 @nwalfield @mlschroe @ffesti thoughts - did I miss some finer details, are there elephants in the room etc? |
One potential open question is --resign: right now it's just an alias for --addsign because there's no practical difference between the two. With this, it could mean something else, probably delete any existing signatures and then sign. Of course this just a minor non-critical detail and can be dealt with later as well. |
Sounds reasonable that --resign will drop all signatures and add new ones. The reason to do that is if you have a package with multiple signatures and you want to replace only one that had a signing key compromised while the others did not. The use case is packages re-distributed by a 3rd party that wants to retain the original signatures and can't recreate them because they have no access to those keys. I wonder if --resign could be enhanced to be able to specify a signature to replace, in which case it would only replace the specific signature and not drop them all ? This is really a corner case and if it is complicated it can definitely be deferred or even not made available. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Yeah --delete and --resign deleting everything is basically just the simplest possible semantics to move forward. I certainly see use-cases for deleting or replacing a specific signature instead, and since that doesn't require any format changes it can be done later once the more critical stuff is out of the way. So I think if we move ahead with this plan, I'd just file another ticket for deleting/replacing a specific signature in some point in the future. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
I recommend against using base64. Just use length-prefixed binary blobs. If base64 is used, the decoder should be very strict and only accept data that round-trips correctly (so no whitespace, etc). |
We don't want to add a "proprietary" format for such a thing because standard header APIs are then no longer usable for accessing and modifying it, and then you only have more code to worry about. We could also just use hex strings, size is not a concern here. But, if we can't be trusted to decode base64 then how are we expected to read the rest of the rpm? That's like being too afraid to leave the house because something bad might happen. I'll note that this is something that could be easily outsourced to rpm-sequoia. Binary arrays could be sort of handled with existinging code u,sing an embedded header (it's just another binary blob afterall), using tag number as the index. But this gets weird and wacky and it's not like the header itself is a trivial structure to parse. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Folks wanting to discuss pros and cons of detached signatures are welcome to do so in the relevant topic but is off-topic here, and has now been flagged such. This ticket is about a new form of embedded signatures in rpm 6.0. Thank you. |
One thing the description doesn't currently cover is the verbose level verification messages, in particular the enforcing mode where it spews out everything it looked at. For example with an unsigned package in enforcing mode, you'd get something like (the last two non-prefixed items stand for legacy Header+payload signatures):
I think we need to lump all the OpenPGP signatures under one label per range to make any sense out of this, ie:
I'm tempted to add "Legacy" in front of the last item because that's what it is, and multiple signatures wont be supported for those. It's a dying breed already in v4, and I'm tempted to drop support for creating them at all in 6.0. We'll need to verify them to properly support v4 but we probably shouldn't even look for them in v6 packages. rpmsign will not create those entries for v6 packages anyhow, but it seems these days rpmsign is the last tool anybody uses for signing... A possible sample output from a package with multiple signatures:
|
This clarifies what these things are - not raw DSA/RSA signatures but OpenPGP signatures. It also opens the door for other types of signatures somewhere in the future, even though no such things are in the plans just now. Most importantly though, this will be needed to make sense of these messages with the multiple OpenPGP signature support where we no longer know such algorithm details. Related: rpm-software-management#3385
Header+payload signatures and digests are rpm v3 era stuff, we still process them but let people know what they are. What a joyous exercise in sed... Related: rpm-software-management#3385
This clarifies what these things are - not raw DSA/RSA signatures but OpenPGP signatures. It also opens the door for other types of signatures somewhere in the future, even though no such things are in the plans just now. Most importantly though, this will be needed to make sense of these messages with the multiple OpenPGP signature support where we no longer know such algorithm details. Related: rpm-software-management#3385
Header+payload signatures and digests are rpm v3 era stuff, we still process them but let people know what they are. What a joyous exercise in sed... Related: rpm-software-management#3385
Multiple signatures aren't necessarily for users installing to process, so it would make sense to ignore them in that case. For example, the signatures may be used to indicate something passed through certain stages. You may have a policy to validate them all, but it may not actually be a required policy. Some signatures may only be for some systems to validate but not others. I can think of a variety of reasons for it. But regardless, I think it does make sense to have some way to indicate a primary/key signature to validate. |
One important point of my suggestion is that the list of keys that are associated with a repo is signed and verifiable with the same list, but is distinct from the keys that are trusted to sign repos. Trusted keys are a superset of keys used in a repo. This makes verifying parts of a repo more deterministic. If your config verified the repo, the uncompromised rpms will always verify. You do not suddenly get one rpm that has only a new signature that you always skipped on the other rpms because they had also an old one. |
Hmm, I thought it was in the description as it's been discussed elsewhere but apparently not - will fix. The initial implementation will indeed simply require all signatures to pass. I expect us to have various extra controls later. Rpm currently has disablers like RPMVSF_NORSAHEADER that operate on the tag level because that's how the signatures are spread out per algorithm, I think we'd extend this to simply operate on algorithm level instead, which means you can explicitly disable eg an algorithm considered compromised and if that's the only thing there was, you fail to get a positive verification. As for unknown signatures, I hadn't really gotten there yet. But there is indeed only one possible default: to ignore anything unknown, because that's the only way to deal with forward compatibility - like @simo5 said. If in doubt, think about this: we add this new RPMTAG_OPENPGP signature tag into rpm now. Older rpm versions simply do not know about this tag, so they will not look there, much less try to verify anything in there. And that's exactly what allows forward compatibility to exist: older rpm versions can still verify the packages to the best of their abilities, we cannot expect them to do anything more. And that's exactly what we must do with the new signatures too - just ignore if not known. If there are no known signatures at all then you fail to get a positive verification, and that's again how it should be. Note all the talk about positive verification: as a reminder, rpm 6.0 will ship with enforcing signature checking on by default (#1573). So you need to make that assumption when talking about this stuff now, otherwise none of it makes any sense. Just like rpm 4.x default signature behavior makes no sense whatsoever. |
Also note that dnf (or otherwise) repositories are way out of scope and topic here, this is strictly an rpm level matter. How multiple signatures are dealt with on repo level is a repo tooling headache to be discussed elsewhere. |
If base64 is bad, what is good then? Plain hex better? @simo5 - thoughts on the encoding? I'm not particularly in love with base64, it's just a format we already have to deal with, and one that isn't as dumb as plain hex space-wise. For traditional signatures, space isn't critical because we're not expecting a single package to have hundreds of thousands of signatures. Are PQ signatures significantly bigger? (I've never seen one, I've no idea) |
This clarifies what these things are - not raw DSA/RSA signatures but OpenPGP signatures. It also opens the door for other types of signatures somewhere in the future, even though no such things are in the plans just now. Most importantly though, this will be needed to make sense of these messages with the multiple OpenPGP signature support where we no longer know such algorithm details. Related: rpm-software-management#3385
Header+payload signatures and digests are rpm v3 era stuff, we still process them but let people know what they are. What a joyous exercise in sed... Related: rpm-software-management#3385
This clarifies what these things are - not raw DSA/RSA signatures but OpenPGP signatures. It also opens the door for other types of signatures somewhere in the future, even though no such things are in the plans just now. Most importantly though, this will be needed to make sense of these messages with the multiple OpenPGP signature support where we no longer know such algorithm details. Related: #3385
Header+payload signatures and digests are rpm v3 era stuff, we still process them but let people know what they are. What a joyous exercise in sed... Related: #3385
The encoding does not affect the feature for me so I have no opinion. The scheme that has the biggest signatures for now is SLH-DSA (formerly known as SPHINCS+) and the stronger variant has a signature size of 50KiB. ML-DSA's (aka Dilithium) biggest signature is ~ 4600 bytes. |
Add support for multiple OpenPGP header signatures per package, base64 encoded in a string array, also known as rpm v6 signatures. --addsign no longer deletes any signatures, it only creates and adds a new signature if possible. --delete and --resign behave as before: they delete ALL signatures on the package, and the latter then creates and adds a new one. For v6 packages this is the default signature type, but if requested, one v4 compat signature can be created for compatible algorithms. v6 signatures on v4 packages are also supported, but have to be explicitly requested. In that case, v3/v4 signatures are only added if none already exist and a v4 compatible algorithm is used. v3 signatures on v6 packages are not supported (out of principle, not a technical limitation) On verification, if RPMTAG_OPENPGP exists then other signature tags are ignored because they're expected to only contain compat copies of the same content. As of now, all existing signatures must validate for signature checking of a package to pass, further policies are to be added later. Besides the concrete RPMTAG_OPENPGP signature tag, add an extension by the same name to handle compatibility with v3/v4 signatures: a user will only need to query the RPMTAG_OPENPGP extension to get all the signatures at once. Extend :pgpsig tag format to handle the new variant. Update --info/-i query to output all existing signatures, one per line. The no-signature case of "Signature : (none)" is preserved as-is to help backwards compatibility with scripts parsing the output. Fixes: rpm-software-management#3385
Add support for multiple OpenPGP header signatures per package, base64 encoded in a string array, also known as rpm v6 signatures. --addsign no longer deletes any signatures, it only creates and adds a new signature if possible. --delete and --resign behave as before: they delete ALL signatures on the package, and the latter then creates and adds a new one. For v6 packages this is the default signature type, but if requested, one v4 compat signature can be created for compatible algorithms. v6 signatures on v4 packages are also supported, but have to be explicitly requested. In that case, v3/v4 signatures are only added if none already exist and a v4 compatible algorithm is used. v3 signatures on v6 packages are not supported (out of principle, not a technical limitation) On verification, if RPMTAG_OPENPGP exists then other signature tags are ignored because they're expected to only contain compat copies of the same content. As of now, all existing signatures must validate for signature checking of a package to pass, further policies are to be added later. Besides the concrete RPMTAG_OPENPGP signature tag, add an extension by the same name to handle compatibility with v3/v4 signatures: a user will only need to query the RPMTAG_OPENPGP extension to get all the signatures at once. Extend :pgpsig tag format to handle the new variant. Update --info/-i query to output all existing signatures, one per line. The no-signature case of "Signature : (none)" is preserved as-is to help backwards compatibility with scripts parsing the output. Fixes: rpm-software-management#3385
Add support for multiple OpenPGP header signatures per package, base64 encoded in a string array, also known as rpm v6 signatures. --addsign no longer deletes any signatures, it only creates and adds a new signature if possible. --delete and --resign behave as before: they delete ALL signatures on the package, and the latter then creates and adds a new one. For v6 packages this is the default signature type, but if requested, one v4 compat signature can be created for compatible algorithms. v6 signatures on v4 packages are also supported, but have to be explicitly requested. In that case, v3/v4 signatures are only added if none already exist and a v4 compatible algorithm is used. v3 signatures on v6 packages are not supported (out of principle, not a technical limitation) On verification, if RPMTAG_OPENPGP exists then other signature tags are ignored because they're expected to only contain compat copies of the same content. As of now, all existing signatures must validate for signature checking of a package to pass, further policies are to be added later. Fixes: rpm-software-management#3385
Add a tag extension for RPMTAG_OPENPGP (on top of the concrete tag) to handle compatibility with v3/v4 signatures: the extension collects all legacy signatures under the same umbrella so users don't need to query multiple different tags, you just query for RPMTAG_OPENPGP to get all them at once. Extend :pgpsig tag format to handle the new string array/base64 variant. Update --info/-i query to use the extension and output all existing signatures, one per line. The no-signature case of "Signature : (none)" is preserved as-is to help backwards compatibility with scripts parsing the output. Related: rpm-software-management#3385
Add a tag extension for RPMTAG_OPENPGP (on top of the concrete tag) to handle compatibility with v3/v4 signatures: the extension collects all legacy signatures under the same umbrella so users don't need to query multiple different tags, you just query for RPMTAG_OPENPGP to get all them at once. Extend :pgpsig tag format to handle the new string array/base64 variant. Update --info/-i query to use the extension and output all existing signatures, one per line. The no-signature case of "Signature : (none)" is preserved as-is to help backwards compatibility with scripts parsing the output. Related: #3385
Add support for multiple OpenPGP header signatures per package, base64 encoded in a string array, also known as rpm v6 signatures. --addsign no longer deletes any signatures, it only creates and adds a new signature if possible. --delete and --resign behave as before: they delete ALL signatures on the package, and the latter then creates and adds a new one. For v6 packages this is the default signature type, but if requested, one v4 compat signature can be created for compatible algorithms. v6 signatures on v4 packages are also supported, but have to be explicitly requested. In that case, v3/v4 signatures are only added if none already exist and a v4 compatible algorithm is used. v3 signatures on v6 packages are not supported (out of principle, not a technical limitation) On verification, if RPMTAG_OPENPGP exists then other signature tags are ignored because they're expected to only contain compat copies of the same content. As of now, all existing signatures must validate for signature checking of a package to pass, further policies are to be added later. Fixes: rpm-software-management#3385
Add a tag extension for RPMTAG_OPENPGP (on top of the concrete tag) to handle compatibility with v3/v4 signatures: the extension collects all legacy signatures under the same umbrella so users don't need to query multiple different tags, you just query for RPMTAG_OPENPGP to get all them at once. Extend :pgpsig tag format to handle the new string array/base64 variant. Update --info/-i query to use the extension and output all existing signatures, one per line. The no-signature case of "Signature : (none)" is preserved as-is to help backwards compatibility with scripts parsing the output. Related: rpm-software-management#3385
Hmm. Just realized that we're accidentally using ASCII-armored signatures when signing with Sequoia, whereas GPG always used binary signatures. And when we then base64 encode that, it gets silly. But that also made me realize that we could use ASCII armored signatures as-is in the RPMTAG_OPENPGP tag, somehow this option never even crossed my mind, I was so fixated on the gpg-era default of "signatures are binary". We could still change this of course - thoughts? |
I'm mostly ambivalent. I think that forensics (i.e., manually extracting the signature and examining it) are a tiny bit easier when using ASCII armor than using a "custom" encoding. |
That's pretty much my view on it too: if it's an OpenPGP signature in a string array, it might as well just say so without having to run it through various extra formatting/processing 😅 |
I strongly oppose ASCII armor, as it injects a lot of additional malliability. |
What does that even mean? Given the current code wants ASCII I would definitely just use the ASCII Armored signature directly and avoid the silly step. I see no need to force a binary representation. |
Malliability means the ability to modify the signature in a way that still produces a valid signature. Base64 with suitable constraints is 1-to-1. ASCII armor is not. |
I know what malleability means, what makes no sense to me is your claim, out of the blue, that the official way to release PGP signatures in printable form is somehow vulnerable to confounding attacks, and how they would be relevant here. If the signature validates it is a valid signature and there is no fudging with the ASCII text that will make it more or less so. I am aware of no relevant issues with armored files, do you have any published analysis that support your stance and would show it being relevant to the RPM situation ? |
There is no relevant security issue in this application, since RPM doesn’t rely on non-malleability and the actual parsing is done by Sequoia. |
Initially requested in #189 and one possible implementation drafted in #1050, but lacking direction and motivation at the time. The topic rose again as in the context of Post Quantum signatures in #3363 - something rpm would rather not know anything about. #1050 added labels to each signature but this is apparently a goofy idea (I think I stole it from Debian at the time), and back then rpm v3 header+payload signatures complicated the backwards compatibility store quite a bit, which is where I ran out of steam in the face of lack of general interest. The discussion in #3363 provided us with a nice clear path ahead now, with multiple benefits, so much so that it'd be stupid not to do this now:
What the implementation will do:
Allowing to replace or delete a specific signature would be out of the initial scope but can be done later. Additional controls for verification policies can/will be added later.
Edit: add default verification policy
The text was updated successfully, but these errors were encountered: