fix(rust): pass raw public key bytes to DecodingKey::from_ed_der
Previous test refactor wrapped both keys in their respective DER envelopes. CI surfaced the asymmetry: jsonwebtoken's two from_ed_der constructors expect different inputs. - EncodingKey::from_ed_der → PKCS#8 v1 wrapped (ring's Ed25519KeyPair::from_pkcs8 path). The 16-byte prefix + 32-byte seed blob is correct. - DecodingKey::from_ed_der → raw 32-byte public key. Internally it becomes ring's UnparsedPublicKey::new(&ED25519, key_bytes), which takes the bare bytes, NOT a SubjectPublicKeyInfo wrapper. The test was building an SPKI DER for the public key, so verification saw a malformed key and failed every signature with InvalidSignature (`accepts_well_formed_base_license` and `activation_token_matches_machine`). Drop the SPKI helper, pass `signing_key.verifying_key().to_bytes()` straight into DecodingKey::from_ed_der. Inline doc-comment captures the asymmetry so the next person doesn't fall in the same hole.
This commit is contained in:
parent
69e136cab0
commit
2e9df1c0b9
1 changed files with 10 additions and 18 deletions
|
|
@ -279,10 +279,16 @@ mod tests {
|
|||
use ed25519_dalek::SigningKey;
|
||||
use jsonwebtoken::{encode, EncodingKey, Header};
|
||||
|
||||
// === Manual DER encoders for Ed25519 keys =================================================
|
||||
// === Manual DER encoder for the Ed25519 private key =======================================
|
||||
// We avoid the `pem` feature on `ed25519-dalek` because the `LineEnding` re-export path
|
||||
// varies across `pkcs8`/`spki`/`der` versions. The Ed25519 PKCS#8 v1 byte layout is fixed
|
||||
// and trivial: prefix + 32-byte raw key.
|
||||
// and trivial: 16-byte prefix + 32-byte raw seed.
|
||||
//
|
||||
// Note the asymmetry in jsonwebtoken's API:
|
||||
// - `EncodingKey::from_ed_der` expects a PKCS#8-wrapped private key (passed to ring's
|
||||
// `Ed25519KeyPair::from_pkcs8`).
|
||||
// - `DecodingKey::from_ed_der` expects the *raw* 32-byte public key (passed to ring's
|
||||
// `UnparsedPublicKey::new` which takes raw bytes, not a SubjectPublicKeyInfo).
|
||||
|
||||
/// Wrap a 32-byte Ed25519 seed in a PKCS#8 v1 PrivateKeyInfo DER blob.
|
||||
fn ed25519_pkcs8_private_der(seed: &[u8; 32]) -> Vec<u8> {
|
||||
|
|
@ -303,28 +309,14 @@ mod tests {
|
|||
der
|
||||
}
|
||||
|
||||
/// Wrap a 32-byte Ed25519 public key in a SubjectPublicKeyInfo DER blob.
|
||||
fn ed25519_spki_public_der(pubkey: &[u8; 32]) -> Vec<u8> {
|
||||
// SEQUENCE(42) {
|
||||
// SEQUENCE(5) { OID(3) 1.3.101.112 }
|
||||
// BIT STRING(33) { 00 <32 bytes> }
|
||||
// }
|
||||
let mut der = vec![
|
||||
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
|
||||
];
|
||||
der.extend_from_slice(pubkey);
|
||||
der
|
||||
}
|
||||
|
||||
/// Build a deterministic test keypair so signed tokens are reproducible across runs.
|
||||
/// Returns (private_der, decoding_key_for_verification).
|
||||
fn test_keys(seed: [u8; 32]) -> (EncodingKey, DecodingKey) {
|
||||
let signing_key = SigningKey::from_bytes(&seed);
|
||||
let pubkey_bytes = signing_key.verifying_key().to_bytes();
|
||||
let priv_der = ed25519_pkcs8_private_der(&seed);
|
||||
let pub_der = ed25519_spki_public_der(&pubkey_bytes);
|
||||
let encoding_key = EncodingKey::from_ed_der(&priv_der);
|
||||
let decoding_key = DecodingKey::from_ed_der(&pub_der);
|
||||
// Raw 32-byte public key (NOT SubjectPublicKeyInfo) — see note above.
|
||||
let decoding_key = DecodingKey::from_ed_der(&pubkey_bytes);
|
||||
(encoding_key, decoding_key)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue