1use core::fmt;
7use core::fmt::{Debug, Formatter};
8use std::marker::PhantomData;
9
10#[cfg(feature = "ring-sig-verify")]
11use untrusted::Input;
12
13use crate::aws_lc::{EVP_PKEY, EVP_PKEY_ED25519};
14
15use crate::buffer::Buffer;
16use crate::encoding::{
17 AsBigEndian, AsDer, Curve25519SeedBin, Pkcs8V1Der, Pkcs8V2Der, PublicKeyX509Der,
18};
19use crate::error::{KeyRejected, Unspecified};
20use crate::evp_pkey::No_EVP_PKEY_CTX_consumer;
21use crate::pkcs8::{Document, Version};
22use crate::ptr::LcPtr;
23use crate::rand::SecureRandom;
24use crate::signature::{KeyPair, Signature, VerificationAlgorithm};
25use crate::{constant_time, hex, sealed};
26
27pub const ED25519_PUBLIC_KEY_LEN: usize = crate::aws_lc::ED25519_PUBLIC_KEY_LEN as usize;
29const ED25519_SIGNATURE_LEN: usize = crate::aws_lc::ED25519_SIGNATURE_LEN as usize;
30const ED25519_SEED_LEN: usize = 32;
31
32#[derive(Debug)]
34pub struct EdDSAParameters;
35
36impl sealed::Sealed for EdDSAParameters {}
37
38impl VerificationAlgorithm for EdDSAParameters {
39 #[inline]
40 #[cfg(feature = "ring-sig-verify")]
41 fn verify(
42 &self,
43 public_key: Input<'_>,
44 msg: Input<'_>,
45 signature: Input<'_>,
46 ) -> Result<(), Unspecified> {
47 let evp_pkey = try_ed25519_public_key_from_bytes(public_key.as_slice_less_safe())?;
48 evp_pkey.verify(
49 msg.as_slice_less_safe(),
50 None,
51 No_EVP_PKEY_CTX_consumer,
52 signature.as_slice_less_safe(),
53 )
54 }
55
56 fn verify_sig(
57 &self,
58 public_key: &[u8],
59 msg: &[u8],
60 signature: &[u8],
61 ) -> Result<(), Unspecified> {
62 let evp_pkey = try_ed25519_public_key_from_bytes(public_key)?;
63 evp_pkey.verify(msg, None, No_EVP_PKEY_CTX_consumer, signature)
64 }
65}
66
67fn try_ed25519_public_key_from_bytes(key_bytes: &[u8]) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
68 if key_bytes.len() == ED25519_PUBLIC_KEY_LEN {
70 return LcPtr::<EVP_PKEY>::parse_raw_public_key(key_bytes, EVP_PKEY_ED25519);
71 }
72 LcPtr::<EVP_PKEY>::parse_rfc5280_public_key(key_bytes, EVP_PKEY_ED25519)
74}
75
76#[allow(clippy::module_name_repetitions)]
78pub struct Ed25519KeyPair {
79 evp_pkey: LcPtr<EVP_PKEY>,
80 public_key: PublicKey,
81}
82
83impl Debug for Ed25519KeyPair {
84 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
85 f.write_str(&format!(
86 "Ed25519KeyPair {{ public_key: PublicKey(\"{}\") }}",
87 hex::encode(&self.public_key)
88 ))
89 }
90}
91
92#[derive(Clone)]
93#[allow(clippy::module_name_repetitions)]
94pub struct Seed<'a> {
96 bytes: Box<[u8]>,
97 phantom: PhantomData<&'a [u8]>,
98}
99
100impl AsBigEndian<Curve25519SeedBin<'static>> for Seed<'_> {
101 fn as_be_bytes(&self) -> Result<Curve25519SeedBin<'static>, Unspecified> {
108 Ok(Curve25519SeedBin::new(self.bytes.to_vec()))
109 }
110}
111
112impl Debug for Seed<'_> {
113 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
114 f.write_str("Ed25519Seed()")
115 }
116}
117
118#[derive(Clone)]
119#[allow(clippy::module_name_repetitions)]
120pub struct PublicKey {
122 evp_pkey: LcPtr<EVP_PKEY>,
123 public_key_bytes: [u8; ED25519_PUBLIC_KEY_LEN],
124}
125
126impl AsRef<[u8]> for PublicKey {
127 #[inline]
128 fn as_ref(&self) -> &[u8] {
130 &self.public_key_bytes
131 }
132}
133
134impl Debug for PublicKey {
135 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
136 f.write_str(&format!(
137 "PublicKey(\"{}\")",
138 hex::encode(self.public_key_bytes)
139 ))
140 }
141}
142
143unsafe impl Send for PublicKey {}
144unsafe impl Sync for PublicKey {}
145
146impl AsDer<PublicKeyX509Der<'static>> for PublicKey {
147 fn as_der(&self) -> Result<PublicKeyX509Der<'static>, crate::error::Unspecified> {
151 let der = self.evp_pkey.as_const().marshal_rfc5280_public_key()?;
157 Ok(PublicKeyX509Der::from(Buffer::new(der)))
158 }
159}
160
161impl KeyPair for Ed25519KeyPair {
162 type PublicKey = PublicKey;
163 #[inline]
164 fn public_key(&self) -> &Self::PublicKey {
165 &self.public_key
166 }
167}
168
169unsafe impl Send for Ed25519KeyPair {}
170unsafe impl Sync for Ed25519KeyPair {}
171
172pub(crate) fn generate_key() -> Result<LcPtr<EVP_PKEY>, Unspecified> {
173 LcPtr::<EVP_PKEY>::generate(EVP_PKEY_ED25519, No_EVP_PKEY_CTX_consumer)
174}
175
176impl Ed25519KeyPair {
177 pub fn generate() -> Result<Self, Unspecified> {
182 let evp_pkey = generate_key()?;
183
184 let mut public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
185 let out_len: usize = evp_pkey
186 .as_const()
187 .marshal_raw_public_to_buffer(&mut public_key)?;
188 debug_assert_eq!(public_key.len(), out_len);
189
190 Ok(Self {
191 public_key: PublicKey {
192 public_key_bytes: public_key,
193 evp_pkey: evp_pkey.clone(),
194 },
195 evp_pkey,
196 })
197 }
198
199 pub fn generate_pkcs8(_rng: &dyn SecureRandom) -> Result<Document, Unspecified> {
222 let evp_pkey = generate_key()?;
223 Ok(Document::new(
224 evp_pkey
225 .as_const()
226 .marshal_rfc5208_private_key(Version::V2)?,
227 ))
228 }
229
230 pub fn to_pkcs8(&self) -> Result<Document, Unspecified> {
236 Ok(Document::new(
237 self.evp_pkey
238 .as_const()
239 .marshal_rfc5208_private_key(Version::V2)?,
240 ))
241 }
242
243 pub fn generate_pkcs8v1(_rng: &dyn SecureRandom) -> Result<Document, Unspecified> {
258 let evp_pkey = generate_key()?;
259 Ok(Document::new(
260 evp_pkey
261 .as_const()
262 .marshal_rfc5208_private_key(Version::V1)?,
263 ))
264 }
265
266 pub fn to_pkcs8v1(&self) -> Result<Document, Unspecified> {
272 Ok(Document::new(
273 self.evp_pkey
274 .as_const()
275 .marshal_rfc5208_private_key(Version::V1)?,
276 ))
277 }
278
279 pub fn from_seed_and_public_key(seed: &[u8], public_key: &[u8]) -> Result<Self, KeyRejected> {
293 let this = Self::from_seed_unchecked(seed)?;
294
295 constant_time::verify_slices_are_equal(public_key, &this.public_key.public_key_bytes)
296 .map_err(|_| KeyRejected::inconsistent_components())?;
297 Ok(this)
298 }
299
300 pub fn from_seed_unchecked(seed: &[u8]) -> Result<Self, KeyRejected> {
313 if seed.len() < ED25519_SEED_LEN {
314 return Err(KeyRejected::inconsistent_components());
315 }
316
317 let evp_pkey = LcPtr::<EVP_PKEY>::parse_raw_private_key(seed, EVP_PKEY_ED25519)?;
318
319 let mut derived_public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
320 let out_len: usize = evp_pkey
321 .as_const()
322 .marshal_raw_public_to_buffer(&mut derived_public_key)?;
323 debug_assert_eq!(derived_public_key.len(), out_len);
324
325 Ok(Self {
326 public_key: PublicKey {
327 public_key_bytes: derived_public_key,
328 evp_pkey: evp_pkey.clone(),
329 },
330 evp_pkey,
331 })
332 }
333
334 pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
350 Self::parse_pkcs8(pkcs8)
351 }
352
353 pub fn from_pkcs8_maybe_unchecked(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
369 Self::parse_pkcs8(pkcs8)
370 }
371
372 fn parse_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
373 let evp_pkey = LcPtr::<EVP_PKEY>::parse_rfc5208_private_key(pkcs8, EVP_PKEY_ED25519)?;
374
375 evp_pkey.as_const().validate_as_ed25519()?;
376
377 let mut public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
378 let out_len: usize = evp_pkey
379 .as_const()
380 .marshal_raw_public_to_buffer(&mut public_key)?;
381 debug_assert_eq!(public_key.len(), out_len);
382
383 Ok(Self {
384 public_key: PublicKey {
385 public_key_bytes: public_key,
386 evp_pkey: evp_pkey.clone(),
387 },
388 evp_pkey,
389 })
390 }
391
392 #[inline]
400 #[must_use]
401 pub fn sign(&self, msg: &[u8]) -> Signature {
402 Self::try_sign(self, msg).expect("ED25519 signing failed")
403 }
404
405 #[inline]
413 pub fn try_sign(&self, msg: &[u8]) -> Result<Signature, Unspecified> {
414 let sig_bytes = self.evp_pkey.sign(msg, None, No_EVP_PKEY_CTX_consumer)?;
415
416 Ok(Signature::new(|slice| {
417 slice[0..ED25519_SIGNATURE_LEN].copy_from_slice(&sig_bytes);
418 ED25519_SIGNATURE_LEN
419 }))
420 }
421
422 pub fn seed(&self) -> Result<Seed<'static>, Unspecified> {
429 Ok(Seed {
430 bytes: self
431 .evp_pkey
432 .as_const()
433 .marshal_raw_private_key()?
434 .into_boxed_slice(),
435 phantom: PhantomData,
436 })
437 }
438}
439
440impl AsDer<Pkcs8V1Der<'static>> for Ed25519KeyPair {
441 fn as_der(&self) -> Result<Pkcs8V1Der<'static>, crate::error::Unspecified> {
446 Ok(Pkcs8V1Der::new(
447 self.evp_pkey
448 .as_const()
449 .marshal_rfc5208_private_key(Version::V1)?,
450 ))
451 }
452}
453
454impl AsDer<Pkcs8V2Der<'static>> for Ed25519KeyPair {
455 fn as_der(&self) -> Result<Pkcs8V2Der<'static>, crate::error::Unspecified> {
460 Ok(Pkcs8V2Der::new(
461 self.evp_pkey
462 .as_const()
463 .marshal_rfc5208_private_key(Version::V2)?,
464 ))
465 }
466}
467
468#[cfg(test)]
469mod tests {
470 use crate::ed25519::Ed25519KeyPair;
471 use crate::encoding::{AsBigEndian, AsDer, Pkcs8V1Der, Pkcs8V2Der, PublicKeyX509Der};
472 use crate::rand::SystemRandom;
473 use crate::signature::{KeyPair, UnparsedPublicKey, ED25519};
474 use crate::{hex, test};
475
476 #[test]
477 fn test_generate() {
478 const MESSAGE: &[u8] = b"test message";
479 let key_pair = Ed25519KeyPair::generate().unwrap();
480 let public_key = key_pair.public_key();
481 let signature = key_pair.sign(MESSAGE);
482 let unparsed_public_key = UnparsedPublicKey::new(&ED25519, public_key.as_ref());
483 unparsed_public_key
484 .verify(MESSAGE, signature.as_ref())
485 .unwrap();
486 }
487
488 #[test]
489 fn test_generate_pkcs8() {
490 let rng = SystemRandom::new();
491 let document = Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
492 let kp1: Ed25519KeyPair = Ed25519KeyPair::from_pkcs8(document.as_ref()).unwrap();
493 assert_eq!(
494 document.as_ref(),
495 AsDer::<Pkcs8V2Der>::as_der(&kp1).unwrap().as_ref()
496 );
497 let kp2: Ed25519KeyPair =
498 Ed25519KeyPair::from_pkcs8_maybe_unchecked(document.as_ref()).unwrap();
499 assert_eq!(
500 kp1.seed().unwrap().as_be_bytes().unwrap().as_ref(),
501 kp2.seed().unwrap().as_be_bytes().unwrap().as_ref(),
502 );
503 assert_eq!(kp1.public_key.as_ref(), kp2.public_key.as_ref());
504
505 let document = Ed25519KeyPair::generate_pkcs8v1(&rng).unwrap();
506 let kp1: Ed25519KeyPair = Ed25519KeyPair::from_pkcs8(document.as_ref()).unwrap();
507 assert_eq!(
508 document.as_ref(),
509 AsDer::<Pkcs8V1Der>::as_der(&kp1).unwrap().as_ref()
510 );
511 let kp2: Ed25519KeyPair =
512 Ed25519KeyPair::from_pkcs8_maybe_unchecked(document.as_ref()).unwrap();
513 assert_eq!(
514 kp1.seed().unwrap().as_be_bytes().unwrap().as_ref(),
515 kp2.seed().unwrap().as_be_bytes().unwrap().as_ref(),
516 );
517 assert_eq!(kp1.public_key.as_ref(), kp2.public_key.as_ref());
518 let seed = kp1.seed().unwrap();
519 assert_eq!("Ed25519Seed()", format!("{seed:?}"));
520 }
521
522 #[test]
523 fn test_from_pkcs8() {
524 struct TestCase {
525 key: &'static str,
526 expected_public: &'static str,
527 }
528
529 for case in [
530 TestCase {
531 key: "302e020100300506032b6570042204209d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
532 expected_public: "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a",
533 },
534 TestCase {
535 key: "3051020101300506032b657004220420756434bd5b824753007a138d27abbc14b5cc786adb78fb62435e6419a2b2e72b8121000faccd81e57de15fa6343a7fbb43b2b93f28be6435100ae8bd633c6dfee3d198",
536 expected_public: "0faccd81e57de15fa6343a7fbb43b2b93f28be6435100ae8bd633c6dfee3d198",
537 },
538 TestCase {
539 key: "304f020100300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842a01f301d060a2a864886f70d01090914310f0c0d437572646c6520436861697273",
540 expected_public: "19bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1",
541 },
542 TestCase {
543 key: "3072020101300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842a01f301d060a2a864886f70d01090914310f0c0d437572646c652043686169727381210019bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1",
544 expected_public: "19bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1",
545 }
546 ] {
547 let key_pair = Ed25519KeyPair::from_pkcs8(&test::from_dirty_hex(case.key)).unwrap();
548 assert_eq!(
549 format!(
550 r#"Ed25519KeyPair {{ public_key: PublicKey("{}") }}"#,
551 case.expected_public
552 ),
553 format!("{key_pair:?}")
554 );
555 let key_pair = Ed25519KeyPair::from_pkcs8_maybe_unchecked(&test::from_dirty_hex(case.key)).unwrap();
556 assert_eq!(
557 format!(
558 r#"Ed25519KeyPair {{ public_key: PublicKey("{}") }}"#,
559 case.expected_public
560 ),
561 format!("{key_pair:?}")
562 );
563 }
564 }
565
566 #[test]
567 fn test_public_key_as_der_x509() {
568 let key_pair = Ed25519KeyPair::from_pkcs8(&hex::decode("302e020100300506032b6570042204209d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60").unwrap()).unwrap();
569 let public_key = key_pair.public_key();
570 let x509der = AsDer::<PublicKeyX509Der>::as_der(public_key).unwrap();
571 assert_eq!(
572 x509der.as_ref(),
573 &[
574 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0xd7, 0x5a,
575 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b, 0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a,
576 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07,
577 0x51, 0x1a
578 ]
579 );
580 }
581}