Skip to content

Feat: Added support for JWK decoding Ed25519 keys#506

Merged
arckoor merged 13 commits into
Keats:masterfrom
richy1623:feat/jwk_decode_ed25519
Jun 20, 2026
Merged

Feat: Added support for JWK decoding Ed25519 keys#506
arckoor merged 13 commits into
Keats:masterfrom
richy1623:feat/jwk_decode_ed25519

Conversation

@richy1623

@richy1623 richy1623 commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Summary: Added decoding JWK support for Ed25519 keys

Changes:

  • Implemented the unimplemented Jwk::from_encoding_key when Algorithm::EdDSA
  • Added to the JWK utils to support fetching Ed25519
  • Updated both backends to support extracting the x parameter (https://datatracker.ietf.org/doc/html/rfc8037#section-2)
  • Added a new EllipticCurve type Ed448 for Ed448 curves
  • Updated the decoder to allow decoding PEMs of type Ed448
  • Added tests for all changes

Solves: #244

@richy1623 richy1623 marked this pull request as ready for review April 28, 2026 11:29
Comment thread src/crypto/aws_lc/eddsa.rs Outdated
Comment thread src/crypto/mod.rs Outdated
Comment thread src/jwk.rs
Comment thread tests/eddsa/mod.rs Outdated
Comment thread src/jwk.rs
@richy1623

Copy link
Copy Markdown
Contributor Author

Thanks for the review @arckoor! I have implemented the requested changes if I could please get a re-review.

@richy1623 richy1623 requested a review from arckoor June 14, 2026 11:48

@arckoor arckoor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry this took so long to get back to.
Classifying Ed448 curves properly and later on rejecting them with UnsupportedAlgorithm is a nice idea, however doing it like this is misleading for PEM users:

let privkey_pem = include_bytes!("private_ed448_key.pem");
let encoding_key = EncodingKey::from_ed_pem(privkey_pem).unwrap(); // this succeeds

let claims = Claims {... };
let token = encode(&Header::new(Algorithm::EdDSA), &claims, &encoding_key).unwrap(); // obviously fails because it's not EdDSA, but there is also no Ed448 algorithm here :/

If I can construct a (PEM) key, I'd expect to be able to sign with it.
So I'd prefer if that bit were removed. Should also mean that you don't need classify_ed_curve at all anymore, and can just match based on key length

Comment thread src/crypto/rust_crypto/mod.rs Outdated
pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey},
traits::PublicKeyParts,
};
use ed25519_dalek::SigningKey;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Import as Ed25519SigningKey

Comment thread src/jwk.rs Outdated
Comment on lines +360 to +365
// --- EllipticCurve Constants ---
// Key Lengths
// ED25519: https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5
pub(crate) const ED25519_PUBLIC_KEY_LENGTH: usize = 32;
// ED448: https://datatracker.ietf.org/doc/html/rfc8032#section-5.2.5
pub(crate) const ED448_PUBLIC_KEY_LENGTH: usize = 57;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ok to inline

Comment thread src/crypto/rust_crypto/eddsa.rs Outdated
}

pub struct EdDSAVerifier(VerifyingKey);
pub struct EdDSAVerifier(pub VerifyingKey);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

leftover

@richy1623 richy1623 requested a review from arckoor June 19, 2026 16:56
@richy1623

Copy link
Copy Markdown
Contributor Author

@arckoor I'm made the changes and added a test case for extracting the PEM key which now fails as expected 👍

@arckoor

arckoor commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Sorry, I should have been clearer, I meant to remove the 448 stuff entirely
It doesn't really hurt to have it, but including a code path that can exclusively be reached by using the from_der methods with an unsupported key just seems kind of silly

ed_pub_components_from_public_key is just entirely superfluous I think? If you inline the the length check to from_decoding_key as well

The 448 test is good to keep though

@richy1623

Copy link
Copy Markdown
Contributor Author

@arckoor I have removed all Ed448 references now (keeping the test). Let me know if there is anything else you would like me to change.

@arckoor arckoor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks!

Comment thread src/jwk.rs
Comment on lines +593 to +602
let (curve_type, x) = match &key.kind() {
DecodingKeyKind::SecretOrDer(pub_bytes) => {
match pub_bytes.len() {
// ED25519: https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5
32 => (EllipticCurve::Ed25519, pub_bytes),
_ => return Err(ErrorKind::InvalidEddsaKey.into()),
}
}
_ => return Err(ErrorKind::InvalidKeyFormat.into()),
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In #515 should be able to use try_get_as_bytes (just note to self so I don't forget :p)

@arckoor arckoor merged commit 31a1dc6 into Keats:master Jun 20, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants