4 ms·
Doesn't appear to have any domain separation. This means that if a common private key is reused in another application you may be able to use that application a
by nullc 5y ago
Doesn't appear to have any domain separation. This means that if a common private key is reused in another application you may be able to use that application as an oracle to produce signatures it doesn't intend to use. Say you later want to have packagers sign with the same keys for security announcements. Obviously not reusing keys is good but there are reasons people do that (e.g. to share the trust of an existing key). The lack of domain sep means stuff like a subkey itself is a valid payload signed by the master key. The modern advice is to personalize the hash function for each distinct application and use within the application.
Signer is setup to have the whole input in memory at once. The protocol design makes it tricky to do otherwise without using two passes at best. This could be avoided if anyone cared, e.g. using a signing scheme with prehashing (which has its own obscure tradeoffs).
This text says very little about validating trusted keys. A signature where you just take the pubkey from the input and don't validate it is essentially just a really computationally expensive hash and doesn't itself provide security. The text about validating all signatures regardless of trusted or not could be read as saying that you just accept stuff with valid signature regardless if they were being signed by the Evil League of Evil instead of an approved source. :)
It uses ed25519 but doesn't do anything about inconsistent validation criteria ( https://hdevalence.ca/blog/2020-10-04-its-25519am https://hdevalence.ca/blog/2020-10-04-its-25519am ), different implementations consider non-overlapping sets of signatures valid. If you want to have automated klaxons on signature failures, this ought to be addressed for the same reason as "repositories do not fail for a subset of users". (though it's not fatal in this application as it is in consensus systems).
The format will be a little clunky if used with post-quantum signatures, e.g. sphincs+ would have a couple kilobytes of signature data stuffed on a line. I don't have a real recommendation there other than saying you should probably have test vectors that have some couple-kilobyte-long examples.
No obvious affordance for additional signed metadata, which is useful for forensics. So, for example, if a project has multiple parties with access to the keys they may want to tag which user(s) authorized the signature or included a timestamp. If their signing is performed by a HSM (e.g. something like USB armory that allows no user access) the consistency of their metadata could be preserved. This could probably be kludged on by requiring the metadata just be inside the payload somewhere.
I like that there are subkeys with expiration. It's not entirely clear to me that it's supported to hand out multiple subkeys to different parties all with the same serial, and they stay all equally valid until a key is observed with a newer serial (at which point all subkeys need to be updated)? "Subkeys may reuse/share serial numbers provided" is confusing on this point. Good security practices suggest that if there are multiple places that can sign each should get its own subkey (so if there is a compromise you can isolate it), and this might mean that there are multiple subkeys in parallel all valid for a given trusted master.
Personally, I'm a little disappointed to see a proposal for repository signing that doesn't include affordances for something like opentimestamps or a certificate-transparency like facility (e.g. to validate that parties aren't making backdoored alternative versions for private distribution). But I guess these could be overlaid as additional signature types and the idea is just to phase out pgp, not advance the security state of the art forward.
Authors of this proposal should be aware the NSA has made a formal recommendation against the use of ECC with curves smaller than 384-bits. There are plenty of applications where compatibility, performance, or computational constraints make it attractive to stay with 256 bit options. But if I were doing something entirely greenfield where a double size key/signature would be a non-issue, I'd be really tempted to use ed448 instead: If nothing else, at least if there are problems in the future you at least didn't violate existing credible advice. :) (Really I'd want to use sphincs+ for something like this, but it's probably too premature). Considering how close to security theater package signing often is in practice, I'm not sure if it's worth worrying too much that the underlying cryptosystem might be stronger-- it's not the limiting factor.
- technion 5y agoThey do say "there may not be any practical ed448 implementations", however the cryptography.hazmat.primitives.asymmetric library used by the reference implementation has an ed448 function that could very likely slide right in. They would however need to change some hardcoded lengths. I do feel their discussion about not using separators to avoid coding string splitting actually makes it more complicated to code around variable lengths. (I'm finding that to be a great reading on validation)
- julian-klode 5y ago> They do say "there may not be any practical ed448 implementations", however the cryptography.hazmat.primitives.asymmetric library used by the reference implementation has an ed448 function that could very likely slide right in. They would however need to change some hardcoded lengths. But that's not what that sentence means at all. It meant that APT might start just with support for ed25519, as IIRC I was told that ed448 is overkill right now. I successfully have signed and verified signatures using Ed448 using the branch of python-aptsign for it. > I do feel their discussion about not using separators to avoid coding string splitting actually makes it more complicated to code around variable lengths. I don't follow
- julian-klode 5y agoFor reference why I don't follow, the two word approach to determine the algorithm and then be able to parse the base64 directly into a struct are easy. like in C++, I can std::string algo, encoded; in >> algo >> encoded; if (algo == ed25519) base64_decode(encoded, ed25519_pointer); return std::move(ed25519_pointer); else if (algo == ed448) base64_decode(encoded, ed448_pointer); return std::move(ed448_pointer); Where the _pointer are std::unique_ptr of Ed25519Signature and Ed448Signature which are each subclasses of Signature, and the return type hence std::unique_ptr<Signature>.
- technion 5y agoIt's only upon the later clarifications in this thread that I've understood "key option 1" and the second option with subkeys are options for the standard and you won't need to support both. Both of these options have different lengths, and if both were supported you've have to split based on.. magic? It's been 20 years since I looked at C++, so I don't understand how you're splitting the public key from the signature given they are one concatenated blob, but that could just be me.