sign jwt tokens with ed25519, ecdsa p-256 and rsa pkcs#1 - #631
Merged
Conversation
the runtime could verify all three but sign none of them, a shape left over from tls, where certificates are checked constantly and produced never. jwt is the first caller that wants signing outright, so the three signers are now wired through: ring already had them, and rsa pkcs#1 reuses the same helper rsa-pss was using with a different encoding. ecdsa signs with the fixed encoding, so the signature comes out as the raw r-and-s form jws carries and the sign path needs none of the der translation the verify path does. the ed25519 parser is the maybe_unchecked variant because openssl writes pkcs#8 v1, which cannot carry the public key ring's strict parser insists on. jwt gains sign_rs256, sign_es256 and sign_eddsa, and every algorithm in the module now both signs and verifies. rsa pkcs#1 and ed25519 are deterministic, so the tests hold the new signers to byte equality with tokens openssl minted over the same key and claims, rather than settling for a round trip. es256 gets the opposite check: two signatures over the same input must differ, because a repeated ecdsa nonce forfeits the private key.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
summary
the runtime verified ed25519, ecdsa and rsa pkcs#1 signatures but could not produce them — a shape inherited from tls, which checks certificates constantly and signs almost never. jwt is the first caller that wants signing as a first-class operation, so this wires the three signers through. ring already had all of them; rsa pkcs#1 is the existing rsa helper with a different encoding constant, ed25519 is a ten-line kernel, and ecdsa p-256 signs with the fixed encoding so the signature comes out as the raw r-and-s form jws carries — the sign path needs none of the der translation the verify path does.
std.crypto.jwtgainssign_rs256,sign_es256andsign_eddsa, and every algorithm in the module now both signs and verifies.std.crypto.signatureexposes the three kernels for anything else that needs them. all signing keys are pkcs#8, which is whatencoding.pem_decodeyields from aBEGIN PRIVATE KEYfile; the ed25519 parser is ring's maybe_unchecked variant because openssl writes pkcs#8 v1, which cannot carry the embedded public key the strict parser insists on.docs and the crypto index no longer describe the sign/verify asymmetry, and instead say which algorithm to pick when.
what was tested
rsa pkcs#1 v1.5 and ed25519 are deterministic, so for a fixed key and claims there is exactly one valid token — the tests check
sign_rs256andsign_eddsareproduce, byte for byte, the tokens openssl minted over the same key and claims. that pins the signing half to the same external standard the verifying half was already held to, where a round trip would only prove the module agrees with itself. es256 gets the opposite check: two signatures over the same input must differ (a repeated ecdsa nonce forfeits the private key), both must verify, and a wrong key must not. a garbage private key fails loudly.make test,make bootstrap-verify(the bootstrap seed is regenerated — the checker and lowering tables changed),make run-examples, andmake leak-checkall clean.notes
the per-signature ecdsa nonce is generated inside ring from the system rng; it is never chosen or seen by pith code, which is the property that keeps p-256 keys from leaking through nonce reuse. ed25519 needs no nonce at all, which is why it can be the deterministic one.