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.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.marshal_raw_public_to_buffer(&mut public_key)?;
186 debug_assert_eq!(public_key.len(), out_len);
187
188 Ok(Self {
189 public_key: PublicKey {
190 public_key_bytes: public_key,
191 evp_pkey: evp_pkey.clone(),
192 },
193 evp_pkey,
194 })
195 }
196
197 pub fn generate_pkcs8(_rng: &dyn SecureRandom) -> Result<Document, Unspecified> {
220 let evp_pkey = generate_key()?;
221 Ok(Document::new(
222 evp_pkey.marshal_rfc5208_private_key(Version::V2)?,
223 ))
224 }
225
226 pub fn to_pkcs8(&self) -> Result<Document, Unspecified> {
232 Ok(Document::new(
233 self.evp_pkey.marshal_rfc5208_private_key(Version::V2)?,
234 ))
235 }
236
237 pub fn generate_pkcs8v1(_rng: &dyn SecureRandom) -> Result<Document, Unspecified> {
252 let evp_pkey = generate_key()?;
253 Ok(Document::new(
254 evp_pkey.marshal_rfc5208_private_key(Version::V1)?,
255 ))
256 }
257
258 pub fn to_pkcs8v1(&self) -> Result<Document, Unspecified> {
264 Ok(Document::new(
265 self.evp_pkey.marshal_rfc5208_private_key(Version::V1)?,
266 ))
267 }
268
269 pub fn from_seed_and_public_key(seed: &[u8], public_key: &[u8]) -> Result<Self, KeyRejected> {
283 let this = Self::from_seed_unchecked(seed)?;
284
285 constant_time::verify_slices_are_equal(public_key, &this.public_key.public_key_bytes)
286 .map_err(|_| KeyRejected::inconsistent_components())?;
287 Ok(this)
288 }
289
290 pub fn from_seed_unchecked(seed: &[u8]) -> Result<Self, KeyRejected> {
303 if seed.len() < ED25519_SEED_LEN {
304 return Err(KeyRejected::inconsistent_components());
305 }
306
307 let evp_pkey = LcPtr::<EVP_PKEY>::parse_raw_private_key(seed, EVP_PKEY_ED25519)?;
308
309 let mut derived_public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
310 let out_len: usize = evp_pkey.marshal_raw_public_to_buffer(&mut derived_public_key)?;
311 debug_assert_eq!(derived_public_key.len(), out_len);
312
313 Ok(Self {
314 public_key: PublicKey {
315 public_key_bytes: derived_public_key,
316 evp_pkey: evp_pkey.clone(),
317 },
318 evp_pkey,
319 })
320 }
321
322 pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
338 Self::parse_pkcs8(pkcs8)
339 }
340
341 pub fn from_pkcs8_maybe_unchecked(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
357 Self::parse_pkcs8(pkcs8)
358 }
359
360 fn parse_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
361 let evp_pkey = LcPtr::<EVP_PKEY>::parse_rfc5208_private_key(pkcs8, EVP_PKEY_ED25519)?;
362
363 evp_pkey.validate_as_ed25519()?;
364
365 let mut public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
366 let out_len: usize = evp_pkey.marshal_raw_public_to_buffer(&mut public_key)?;
367 debug_assert_eq!(public_key.len(), out_len);
368
369 Ok(Self {
370 public_key: PublicKey {
371 public_key_bytes: public_key,
372 evp_pkey: evp_pkey.clone(),
373 },
374 evp_pkey,
375 })
376 }
377
378 #[inline]
386 #[must_use]
387 pub fn sign(&self, msg: &[u8]) -> Signature {
388 Self::try_sign(self, msg).expect("ED25519 signing failed")
389 }
390
391 #[inline]
392 fn try_sign(&self, msg: &[u8]) -> Result<Signature, Unspecified> {
393 let sig_bytes = self.evp_pkey.sign(msg, None, No_EVP_PKEY_CTX_consumer)?;
394
395 Ok(Signature::new(|slice| {
396 slice[0..ED25519_SIGNATURE_LEN].copy_from_slice(&sig_bytes);
397 ED25519_SIGNATURE_LEN
398 }))
399 }
400
401 pub fn seed(&self) -> Result<Seed<'static>, Unspecified> {
408 Ok(Seed {
409 bytes: self.evp_pkey.marshal_raw_private_key()?.into_boxed_slice(),
410 phantom: PhantomData,
411 })
412 }
413}
414
415impl AsDer<Pkcs8V1Der<'static>> for Ed25519KeyPair {
416 fn as_der(&self) -> Result<Pkcs8V1Der<'static>, crate::error::Unspecified> {
421 Ok(Pkcs8V1Der::new(
422 self.evp_pkey.marshal_rfc5208_private_key(Version::V1)?,
423 ))
424 }
425}
426
427impl AsDer<Pkcs8V2Der<'static>> for Ed25519KeyPair {
428 fn as_der(&self) -> Result<Pkcs8V2Der<'static>, crate::error::Unspecified> {
433 Ok(Pkcs8V2Der::new(
434 self.evp_pkey.marshal_rfc5208_private_key(Version::V2)?,
435 ))
436 }
437}
438
439#[cfg(test)]
440mod tests {
441 use crate::ed25519::Ed25519KeyPair;
442 use crate::encoding::{AsBigEndian, AsDer, Pkcs8V1Der, Pkcs8V2Der, PublicKeyX509Der};
443 use crate::rand::SystemRandom;
444 use crate::signature::{KeyPair, UnparsedPublicKey, ED25519};
445 use crate::{hex, test};
446
447 #[test]
448 fn test_generate() {
449 const MESSAGE: &[u8] = b"test message";
450 let key_pair = Ed25519KeyPair::generate().unwrap();
451 let public_key = key_pair.public_key();
452 let signature = key_pair.sign(MESSAGE);
453 let unparsed_public_key = UnparsedPublicKey::new(&ED25519, public_key.as_ref());
454 unparsed_public_key
455 .verify(MESSAGE, signature.as_ref())
456 .unwrap();
457 }
458
459 #[test]
460 fn test_generate_pkcs8() {
461 let rng = SystemRandom::new();
462 let document = Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
463 let kp1: Ed25519KeyPair = Ed25519KeyPair::from_pkcs8(document.as_ref()).unwrap();
464 assert_eq!(
465 document.as_ref(),
466 AsDer::<Pkcs8V2Der>::as_der(&kp1).unwrap().as_ref()
467 );
468 let kp2: Ed25519KeyPair =
469 Ed25519KeyPair::from_pkcs8_maybe_unchecked(document.as_ref()).unwrap();
470 assert_eq!(
471 kp1.seed().unwrap().as_be_bytes().unwrap().as_ref(),
472 kp2.seed().unwrap().as_be_bytes().unwrap().as_ref(),
473 );
474 assert_eq!(kp1.public_key.as_ref(), kp2.public_key.as_ref());
475
476 let document = Ed25519KeyPair::generate_pkcs8v1(&rng).unwrap();
477 let kp1: Ed25519KeyPair = Ed25519KeyPair::from_pkcs8(document.as_ref()).unwrap();
478 assert_eq!(
479 document.as_ref(),
480 AsDer::<Pkcs8V1Der>::as_der(&kp1).unwrap().as_ref()
481 );
482 let kp2: Ed25519KeyPair =
483 Ed25519KeyPair::from_pkcs8_maybe_unchecked(document.as_ref()).unwrap();
484 assert_eq!(
485 kp1.seed().unwrap().as_be_bytes().unwrap().as_ref(),
486 kp2.seed().unwrap().as_be_bytes().unwrap().as_ref(),
487 );
488 assert_eq!(kp1.public_key.as_ref(), kp2.public_key.as_ref());
489 let seed = kp1.seed().unwrap();
490 assert_eq!("Ed25519Seed()", format!("{seed:?}"));
491 }
492
493 #[test]
494 fn test_from_pkcs8() {
495 struct TestCase {
496 key: &'static str,
497 expected_public: &'static str,
498 }
499
500 for case in [
501 TestCase {
502 key: "302e020100300506032b6570042204209d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
503 expected_public: "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a",
504 },
505 TestCase {
506 key: "3051020101300506032b657004220420756434bd5b824753007a138d27abbc14b5cc786adb78fb62435e6419a2b2e72b8121000faccd81e57de15fa6343a7fbb43b2b93f28be6435100ae8bd633c6dfee3d198",
507 expected_public: "0faccd81e57de15fa6343a7fbb43b2b93f28be6435100ae8bd633c6dfee3d198",
508 },
509 TestCase {
510 key: "304f020100300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842a01f301d060a2a864886f70d01090914310f0c0d437572646c6520436861697273",
511 expected_public: "19bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1",
512 },
513 TestCase {
514 key: "3072020101300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842a01f301d060a2a864886f70d01090914310f0c0d437572646c652043686169727381210019bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1",
515 expected_public: "19bf44096984cdfe8541bac167dc3b96c85086aa30b6b6cb0c5c38ad703166e1",
516 }
517 ] {
518 let key_pair = Ed25519KeyPair::from_pkcs8(&test::from_dirty_hex(case.key)).unwrap();
519 assert_eq!(
520 format!(
521 r#"Ed25519KeyPair {{ public_key: PublicKey("{}") }}"#,
522 case.expected_public
523 ),
524 format!("{key_pair:?}")
525 );
526 let key_pair = Ed25519KeyPair::from_pkcs8_maybe_unchecked(&test::from_dirty_hex(case.key)).unwrap();
527 assert_eq!(
528 format!(
529 r#"Ed25519KeyPair {{ public_key: PublicKey("{}") }}"#,
530 case.expected_public
531 ),
532 format!("{key_pair:?}")
533 );
534 }
535 }
536
537 #[test]
538 fn test_public_key_as_der_x509() {
539 let key_pair = Ed25519KeyPair::from_pkcs8(&hex::decode("302e020100300506032b6570042204209d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60").unwrap()).unwrap();
540 let public_key = key_pair.public_key();
541 let x509der = AsDer::<PublicKeyX509Der>::as_der(public_key).unwrap();
542 assert_eq!(
543 x509der.as_ref(),
544 &[
545 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0xd7, 0x5a,
546 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, 0xd5, 0x4b, 0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a,
547 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, 0x23, 0x25, 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07,
548 0x51, 0x1a
549 ]
550 );
551 }
552}