anza-cryptography-source/curve25519/solana-ed25519/src/ed_sigs/tests/decoding.rs
zz-sol bfc9f01bbb
[ed25519] improve signing key life cycle (#51)
* make sk non-copy

* lint

* simplify zeroization
2026-06-18 09:25:12 -04:00

146 lines
5.1 KiB
Rust

#[cfg(any(feature = "pem", feature = "pkcs8"))]
use crate::ed_sigs::*;
#[cfg(feature = "pkcs8")]
use pkcs8::der::asn1::BitStringRef;
#[cfg(feature = "pkcs8")]
use pkcs8::{DecodePrivateKey, DecodePublicKey};
/// Ed25519 PKCS#8 v1 private key encoded as ASN.1 DER.
#[cfg(feature = "pkcs8")]
const PKCS8_V1_DER: &[u8] = include_bytes!("../../../examples/pkcs8-v1.der");
/// Ed25519 PKCS#8 v1 private key encoded as PEM.
#[cfg(feature = "pem")]
const PKCS8_V1_PEM: &str = include_str!("../../../examples/pkcs8-v1.pem");
/// Ed25519 PKCS#8 v2 private key + public key encoded as ASN.1 DER.
#[cfg(feature = "pkcs8")]
const PKCS8_V2_DER: &[u8] = include_bytes!("../../../examples/pkcs8-v2.der");
/// Ed25519 PKCS#8 v2 private key + public key encoded as PEM.
#[cfg(feature = "pem")]
const PKCS8_V2_PEM: &str = include_str!("../../../examples/pkcs8-v2.pem");
/// Ed25519 PKCS#8 v2 private key + mismatched public key encoded as ASN.1 DER.
#[cfg(feature = "pkcs8")]
const PKCS8_V2_DER_BAD: &[u8] = include_bytes!("../../../examples/pkcs8-v2-bad-ver-key.der");
/// Ed25519 PKCS#8 v2 private key + mismatched public key encoded as PEM.
#[cfg(feature = "pem")]
const PKCS8_V2_PEM_BAD: &str = include_str!("../../../examples/pkcs8-v2-bad-ver-key.pem");
/// Ed25519 SubjectPublicKeyInfo encoded as ASN.1 DER.
#[cfg(feature = "pkcs8")]
const PUBLIC_KEY_DER: &[u8] = include_bytes!("../../../examples/pubkey.der");
/// Ed25519 SubjectPublicKeyInfo encoded as PEM.
#[cfg(feature = "pem")]
const PUBLIC_KEY_PEM: &str = include_str!("../../../examples/pubkey.pem");
#[test]
#[cfg(feature = "pkcs8")]
fn decode_der_to_signing_key() {
// Test against a v1 DER key.
let sk1 = SigningKey::from_pkcs8_der(PKCS8_V1_DER).unwrap();
let sk_bytes_string_1 = "D4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F44755842";
assert_eq!(
hex::decode(sk_bytes_string_1).unwrap(),
sk1.as_secret_key_bytes()
);
// Test against a v2 DER key.
let sk2 = SigningKey::from_pkcs8_der(PKCS8_V2_DER).unwrap();
let sk_bytes_string_2 = "D4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F44755842";
assert_eq!(
hex::decode(sk_bytes_string_2).unwrap(),
sk2.as_secret_key_bytes()
);
// Test against a v2 DER key with a mismatched public key.
assert!(SigningKey::from_pkcs8_der(PKCS8_V2_DER_BAD).is_err());
}
#[test]
#[cfg(feature = "pkcs8")]
fn reject_malformed_private_key_der_without_panicking() {
assert!(SigningKey::from_pkcs8_der(b"not a pkcs8 key").is_err());
}
#[test]
#[cfg(feature = "pem")]
fn decode_doc_to_signing_key() {
// Test against a v1 PEM key.
let sk1 = SigningKey::from_pkcs8_pem(PKCS8_V1_PEM).unwrap();
let sk_bytes_string_1 = "D4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F44755842";
assert_eq!(
hex::decode(sk_bytes_string_1).unwrap(),
sk1.as_secret_key_bytes()
);
// Test against a valid v2 PEM key.
let sk2 = SigningKey::from_pkcs8_pem(PKCS8_V2_PEM).unwrap();
let sk_bytes_string_2 = "D4EE72DBF913584AD5B6D8F1F769F8AD3AFE7C28CBF1D4FBE097A88F44755842";
assert_eq!(
hex::decode(sk_bytes_string_2).unwrap(),
sk2.as_secret_key_bytes()
);
// Test against a v2 DER key with a mismatched public key.
assert!(SigningKey::from_pkcs8_pem(PKCS8_V2_PEM_BAD).is_err());
}
#[test]
#[cfg(feature = "pkcs8")]
fn decode_der_to_verification_key() {
let vk = VerificationKey::from_public_key_der(PUBLIC_KEY_DER).unwrap();
let vk_bytes_string = "19bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1";
assert_eq!(hex::decode(vk_bytes_string).unwrap(), vk.as_ref());
}
#[test]
#[cfg(feature = "pkcs8")]
fn reject_public_key_der_with_wrong_algorithm_oid() {
let vk = VerificationKey::from_public_key_der(PUBLIC_KEY_DER).unwrap();
let oid = pkcs8::ObjectIdentifier::new_unwrap("1.3.101.110"); // X25519
let spki = pkcs8::spki::SubjectPublicKeyInfoRef {
algorithm: pkcs8::spki::AlgorithmIdentifierRef {
oid,
parameters: None,
},
subject_public_key: BitStringRef::from_bytes(vk.as_ref()).unwrap(),
};
let doc = pkcs8::Document::try_from(spki).unwrap();
assert_eq!(
VerificationKey::from_public_key_der(doc.as_bytes()).unwrap_err(),
pkcs8::spki::Error::OidUnknown { oid }
);
}
#[test]
#[cfg(feature = "pkcs8")]
fn reject_public_key_der_with_malformed_key_bytes() {
let oid = pkcs8::ObjectIdentifier::new_unwrap("1.3.101.112"); // Ed25519
let spki = pkcs8::spki::SubjectPublicKeyInfoRef {
algorithm: pkcs8::spki::AlgorithmIdentifierRef {
oid,
parameters: None,
},
subject_public_key: BitStringRef::from_bytes(&[0u8; 31]).unwrap(),
};
let doc = pkcs8::Document::try_from(spki).unwrap();
assert_eq!(
VerificationKey::from_public_key_der(doc.as_bytes()).unwrap_err(),
pkcs8::spki::Error::KeyMalformed
);
}
#[test]
#[cfg(feature = "pem")]
fn decode_doc_to_verification_key() {
let vk = VerificationKey::from_public_key_pem(PUBLIC_KEY_PEM).unwrap();
let vk_bytes_string = "19bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1";
assert_eq!(hex::decode(vk_bytes_string).unwrap(), vk.as_ref());
}