Skip to content

Commit 44fa00d

Browse files
Implement from_seed_unchecked for Ed25519KeyPair (#663)
* Implement `from_seed_unchecked` for `Ed25519KeyPair` * Minor doc/test changes --------- Co-authored-by: Justin Smith <[email protected]>
1 parent 9124243 commit 44fa00d

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

aws-lc-rs/src/ed25519.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,26 @@ impl Ed25519KeyPair {
351351
/// # Errors
352352
/// `error::KeyRejected` if parse error, or if key is otherwise unacceptable.
353353
pub fn from_seed_and_public_key(seed: &[u8], public_key: &[u8]) -> Result<Self, KeyRejected> {
354+
let this = Self::from_seed_unchecked(seed)?;
355+
356+
constant_time::verify_slices_are_equal(public_key, &this.public_key.public_key_bytes)
357+
.map_err(|_| KeyRejected::inconsistent_components())?;
358+
Ok(this)
359+
}
360+
361+
/// Constructs an Ed25519 key pair from the private key seed `seed`.
362+
///
363+
/// It is recommended to use `Ed25519KeyPair::from_pkcs8()` instead. If the public key is
364+
/// available, prefer to use `Ed25519KeyPair::from_seed_and_public_key()` as it will verify
365+
/// the validity of the key pair.
366+
///
367+
/// CAUTION: Both an Ed25519 seed and its public key are 32-bytes. If the bytes of a public key
368+
/// are provided this function will create an (effectively) invalid `Ed25519KeyPair`. This
369+
/// problem is undetectable by the API.
370+
///
371+
/// # Errors
372+
/// `error::KeyRejected` if parse error, or if key is otherwise unacceptable.
373+
pub fn from_seed_unchecked(seed: &[u8]) -> Result<Self, KeyRejected> {
354374
if seed.len() < ED25519_SEED_LEN {
355375
return Err(KeyRejected::inconsistent_components());
356376
}
@@ -372,9 +392,6 @@ impl Ed25519KeyPair {
372392
}
373393
debug_assert_eq!(derived_public_key.len(), out_len);
374394

375-
constant_time::verify_slices_are_equal(public_key, &derived_public_key)
376-
.map_err(|_| KeyRejected::inconsistent_components())?;
377-
378395
Ok(Self {
379396
public_key: PublicKey {
380397
public_key_bytes: derived_public_key,

aws-lc-rs/tests/ed25519_tests.rs

+15
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ fn test_signature_ed25519() {
3434

3535
let expected_sig = test_case.consume_bytes("SIG");
3636

37+
let key_pair = Ed25519KeyPair::from_seed_unchecked(&seed).unwrap();
38+
let actual_sig = key_pair.sign(&msg);
39+
assert_eq!(&expected_sig[..], actual_sig.as_ref());
40+
3741
let key_pair = Ed25519KeyPair::from_seed_and_public_key(&seed, &public_key).unwrap();
3842
let actual_sig = key_pair.sign(&msg);
3943
assert_eq!(&expected_sig[..], actual_sig.as_ref());
@@ -99,6 +103,12 @@ fn test_ed25519_from_seed_and_public_key_misuse() {
99103

100104
// Swapped public and private key.
101105
assert!(Ed25519KeyPair::from_seed_and_public_key(PUBLIC_KEY, PRIVATE_KEY).is_err());
106+
107+
// From a private seed
108+
assert!(Ed25519KeyPair::from_seed_unchecked(PRIVATE_KEY).is_ok());
109+
110+
// From a truncated private seed
111+
assert!(Ed25519KeyPair::from_seed_unchecked(PRIVATE_KEY).is_ok());
102112
}
103113

104114
#[test]
@@ -232,4 +242,9 @@ fn test_seed() {
232242
let key_pair_copy_doc = key_pair_copy.to_pkcs8().unwrap();
233243

234244
assert_eq!(key_pair_doc.as_ref(), key_pair_copy_doc.as_ref());
245+
246+
let key_pair_seed_copy = Ed25519KeyPair::from_seed_unchecked(seed_buffer.as_ref()).unwrap();
247+
let key_pair_seed_copy_doc = key_pair_seed_copy.to_pkcs8().unwrap();
248+
249+
assert_eq!(key_pair_doc.as_ref(), key_pair_seed_copy_doc.as_ref());
235250
}

0 commit comments

Comments
 (0)