1#[cfg(feature = "crypto")]
2use std::fmt;
3
4#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
5use aws_lc_rs::unstable::signature::PqdsaKeyPair;
6#[cfg(feature = "pem")]
7use pem::Pem;
8#[cfg(feature = "crypto")]
9use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer};
10use yasna::{DERWriter, DERWriterSeq};
11
12#[cfg(any(feature = "crypto", feature = "pem"))]
13use crate::error::ExternalError;
14#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
15use crate::ring_like::ecdsa_from_private_key_der;
16#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
17use crate::ring_like::rsa::KeySize;
18#[cfg(feature = "crypto")]
19use crate::ring_like::{
20 error as ring_error,
21 rand::SystemRandom,
22 signature::{
23 self, EcdsaKeyPair, Ed25519KeyPair, KeyPair as RingKeyPair, RsaEncoding, RsaKeyPair,
24 },
25 {ecdsa_from_pkcs8, rsa_key_pair_public_modulus_len},
26};
27use crate::sign_algo::SignatureAlgorithm;
28#[cfg(feature = "crypto")]
29use crate::sign_algo::{algo::*, SignAlgo};
30use crate::Error;
31#[cfg(feature = "pem")]
32use crate::ENCODE_CONFIG;
33
34#[allow(clippy::large_enum_variant)]
36#[cfg(feature = "crypto")]
37pub(crate) enum KeyPairKind {
38 Ec(EcdsaKeyPair),
40 Ed(Ed25519KeyPair),
42 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
44 Pq(PqdsaKeyPair),
45 Rsa(RsaKeyPair, &'static dyn RsaEncoding),
47}
48
49#[cfg(feature = "crypto")]
50impl fmt::Debug for KeyPairKind {
51 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52 match self {
53 Self::Ec(key_pair) => write!(f, "{key_pair:?}"),
54 Self::Ed(key_pair) => write!(f, "{key_pair:?}"),
55 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
56 Self::Pq(key_pair) => write!(f, "{key_pair:?}"),
57 Self::Rsa(key_pair, _) => write!(f, "{key_pair:?}"),
58 }
59 }
60}
61
62#[cfg(feature = "crypto")]
64pub struct KeyPair {
65 pub(crate) kind: KeyPairKind,
66 pub(crate) alg: &'static SignatureAlgorithm,
67 pub(crate) serialized_der: Vec<u8>,
68}
69
70#[cfg(feature = "crypto")]
71impl fmt::Debug for KeyPair {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 f.debug_struct("KeyPair")
74 .field("kind", &self.kind)
75 .field("alg", &self.alg)
76 .field("serialized_der", &"[secret key elided]")
77 .finish()
78 }
79}
80
81#[cfg(feature = "crypto")]
82impl KeyPair {
83 #[cfg(feature = "crypto")]
85 pub fn generate() -> Result<Self, Error> {
86 Self::generate_for(&PKCS_ECDSA_P256_SHA256)
87 }
88
89 #[cfg(feature = "crypto")]
96 pub fn generate_for(alg: &'static SignatureAlgorithm) -> Result<Self, Error> {
97 let rng = &SystemRandom::new();
98
99 match alg.sign_alg {
100 SignAlgo::EcDsa(sign_alg) => {
101 let key_pair_doc = EcdsaKeyPair::generate_pkcs8(sign_alg, rng)._err()?;
102 let key_pair_serialized = key_pair_doc.as_ref().to_vec();
103
104 let key_pair = ecdsa_from_pkcs8(sign_alg, key_pair_doc.as_ref(), rng).unwrap();
105 Ok(KeyPair {
106 kind: KeyPairKind::Ec(key_pair),
107 alg,
108 serialized_der: key_pair_serialized,
109 })
110 },
111 SignAlgo::EdDsa(_sign_alg) => {
112 let key_pair_doc = Ed25519KeyPair::generate_pkcs8(rng)._err()?;
113 let key_pair_serialized = key_pair_doc.as_ref().to_vec();
114
115 let key_pair = Ed25519KeyPair::from_pkcs8(key_pair_doc.as_ref()).unwrap();
116 Ok(KeyPair {
117 kind: KeyPairKind::Ed(key_pair),
118 alg,
119 serialized_der: key_pair_serialized,
120 })
121 },
122 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
123 SignAlgo::PqDsa(sign_alg) => {
124 let key_pair = PqdsaKeyPair::generate(sign_alg)._err()?;
125 let key_pair_serialized = key_pair.to_pkcs8()._err()?.as_ref().to_vec();
126
127 Ok(KeyPair {
128 kind: KeyPairKind::Pq(key_pair),
129 alg,
130 serialized_der: key_pair_serialized,
131 })
132 },
133 #[cfg(feature = "aws_lc_rs")]
134 SignAlgo::Rsa(sign_alg) => Self::generate_rsa_inner(alg, sign_alg, KeySize::Rsa2048),
135 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
139 SignAlgo::Rsa(_sign_alg) => Err(Error::KeyGenerationUnavailable),
140 }
141 }
142
143 #[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
148 pub fn generate_rsa_for(
149 alg: &'static SignatureAlgorithm,
150 key_size: RsaKeySize,
151 ) -> Result<Self, Error> {
152 match alg.sign_alg {
153 SignAlgo::Rsa(sign_alg) => {
154 let key_size = match key_size {
155 RsaKeySize::_2048 => KeySize::Rsa2048,
156 RsaKeySize::_3072 => KeySize::Rsa3072,
157 RsaKeySize::_4096 => KeySize::Rsa4096,
158 };
159 Self::generate_rsa_inner(alg, sign_alg, key_size)
160 },
161 _ => Err(Error::KeyGenerationUnavailable),
162 }
163 }
164
165 #[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
166 fn generate_rsa_inner(
167 alg: &'static SignatureAlgorithm,
168 sign_alg: &'static dyn RsaEncoding,
169 key_size: KeySize,
170 ) -> Result<Self, Error> {
171 use aws_lc_rs::encoding::AsDer;
172 let key_pair = RsaKeyPair::generate(key_size)._err()?;
173 let key_pair_serialized = key_pair.as_der()._err()?.as_ref().to_vec();
174
175 Ok(KeyPair {
176 kind: KeyPairKind::Rsa(key_pair, sign_alg),
177 alg,
178 serialized_der: key_pair_serialized,
179 })
180 }
181
182 pub fn algorithm(&self) -> &'static SignatureAlgorithm {
184 self.alg
185 }
186
187 #[cfg(all(feature = "pem", feature = "crypto"))]
195 pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
196 let private_key = pem::parse(pem_str)._err()?;
197 Self::try_from(private_key.contents())
198 }
199
200 #[cfg(all(feature = "pem", feature = "crypto"))]
208 pub fn from_pkcs8_pem_and_sign_algo(
209 pem_str: &str,
210 alg: &'static SignatureAlgorithm,
211 ) -> Result<Self, Error> {
212 let private_key = pem::parse(pem_str)._err()?;
213 let private_key_der: &[_] = private_key.contents();
214 Self::from_pkcs8_der_and_sign_algo(&PrivatePkcs8KeyDer::from(private_key_der), alg)
215 }
216
217 #[cfg(feature = "crypto")]
232 pub fn from_pkcs8_der_and_sign_algo(
233 pkcs8: &PrivatePkcs8KeyDer<'_>,
234 alg: &'static SignatureAlgorithm,
235 ) -> Result<Self, Error> {
236 let rng = &SystemRandom::new();
237 let serialized_der = pkcs8.secret_pkcs8_der().to_vec();
238
239 let kind = if alg == &PKCS_ED25519 {
240 KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
241 } else if alg == &PKCS_ECDSA_P256_SHA256 {
242 KeyPairKind::Ec(ecdsa_from_pkcs8(
243 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
244 &serialized_der,
245 rng,
246 )?)
247 } else if alg == &PKCS_ECDSA_P384_SHA384 {
248 KeyPairKind::Ec(ecdsa_from_pkcs8(
249 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
250 &serialized_der,
251 rng,
252 )?)
253 } else if alg == &PKCS_RSA_SHA256 {
254 let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
255 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
256 } else if alg == &PKCS_RSA_SHA384 {
257 let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
258 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
259 } else if alg == &PKCS_RSA_SHA512 {
260 let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
261 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
262 } else if alg == &PKCS_RSA_PSS_SHA256 {
263 let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
264 KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
265 } else {
266 #[cfg(feature = "aws_lc_rs")]
267 if alg == &PKCS_ECDSA_P521_SHA256 {
268 KeyPairKind::Ec(ecdsa_from_pkcs8(
269 &signature::ECDSA_P521_SHA256_ASN1_SIGNING,
270 &serialized_der,
271 rng,
272 )?)
273 } else if alg == &PKCS_ECDSA_P521_SHA384 {
274 KeyPairKind::Ec(ecdsa_from_pkcs8(
275 &signature::ECDSA_P521_SHA384_ASN1_SIGNING,
276 &serialized_der,
277 rng,
278 )?)
279 } else if alg == &PKCS_ECDSA_P521_SHA512 {
280 KeyPairKind::Ec(ecdsa_from_pkcs8(
281 &signature::ECDSA_P521_SHA512_ASN1_SIGNING,
282 &serialized_der,
283 rng,
284 )?)
285 } else {
286 panic!("Unknown SignatureAlgorithm specified!");
287 }
288
289 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
290 panic!("Unknown SignatureAlgorithm specified!");
291 };
292
293 Ok(KeyPair {
294 kind,
295 alg,
296 serialized_der,
297 })
298 }
299
300 #[cfg(all(feature = "pem", feature = "crypto"))]
311 pub fn from_pem_and_sign_algo(
312 pem_str: &str,
313 alg: &'static SignatureAlgorithm,
314 ) -> Result<Self, Error> {
315 let private_key = pem::parse(pem_str)._err()?;
316 let private_key: &[_] = private_key.contents();
317 Self::from_der_and_sign_algo(
318 &PrivateKeyDer::try_from(private_key).map_err(|_| Error::CouldNotParseKeyPair)?,
319 alg,
320 )
321 }
322
323 #[cfg(feature = "crypto")]
339 pub fn from_der_and_sign_algo(
340 key: &PrivateKeyDer<'_>,
341 alg: &'static SignatureAlgorithm,
342 ) -> Result<Self, Error> {
343 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
344 {
345 if let PrivateKeyDer::Pkcs8(key) = key {
346 Self::from_pkcs8_der_and_sign_algo(key, alg)
347 } else {
348 Err(Error::CouldNotParseKeyPair)
349 }
350 }
351 #[cfg(feature = "aws_lc_rs")]
352 {
353 let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
354
355 let rsa_key_pair_from = if is_pkcs8 {
356 RsaKeyPair::from_pkcs8
357 } else {
358 RsaKeyPair::from_der
359 };
360
361 let serialized_der = key.secret_der().to_vec();
362
363 let kind = if alg == &PKCS_ED25519 {
364 KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
365 } else if alg == &PKCS_ECDSA_P256_SHA256 {
366 KeyPairKind::Ec(ecdsa_from_private_key_der(
367 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
368 &serialized_der,
369 )?)
370 } else if alg == &PKCS_ECDSA_P384_SHA384 {
371 KeyPairKind::Ec(ecdsa_from_private_key_der(
372 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
373 &serialized_der,
374 )?)
375 } else if alg == &PKCS_ECDSA_P521_SHA512 {
376 KeyPairKind::Ec(ecdsa_from_private_key_der(
377 &signature::ECDSA_P521_SHA512_ASN1_SIGNING,
378 &serialized_der,
379 )?)
380 } else if alg == &PKCS_RSA_SHA256 {
381 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
382 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
383 } else if alg == &PKCS_RSA_SHA384 {
384 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
385 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
386 } else if alg == &PKCS_RSA_SHA512 {
387 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
388 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
389 } else if alg == &PKCS_RSA_PSS_SHA256 {
390 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
391 KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
392 } else {
393 panic!("Unknown SignatureAlgorithm specified!");
394 };
395
396 Ok(KeyPair {
397 kind,
398 alg,
399 serialized_der,
400 })
401 }
402 }
403
404 pub fn public_key_raw(&self) -> &[u8] {
413 self.der_bytes()
414 }
415
416 pub fn is_compatible(&self, signature_algorithm: &SignatureAlgorithm) -> bool {
418 self.alg == signature_algorithm
419 }
420
421 pub fn compatible_algs(&self) -> impl Iterator<Item = &'static SignatureAlgorithm> {
424 std::iter::once(self.alg)
425 }
426
427 #[cfg(feature = "pem")]
431 pub fn public_key_pem(&self) -> String {
432 let contents = self.subject_public_key_info();
433 let p = Pem::new("PUBLIC KEY", contents);
434 pem::encode_config(&p, ENCODE_CONFIG)
435 }
436
437 pub fn serialize_der(&self) -> Vec<u8> {
439 self.serialized_der.clone()
440 }
441
442 pub fn serialized_der(&self) -> &[u8] {
445 &self.serialized_der
446 }
447
448 #[cfg(feature = "pem")]
450 pub fn serialize_pem(&self) -> String {
451 let contents = self.serialize_der();
452 let p = Pem::new("PRIVATE KEY", contents);
453 pem::encode_config(&p, ENCODE_CONFIG)
454 }
455}
456
457#[cfg(feature = "crypto")]
458impl SigningKey for KeyPair {
459 fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error> {
460 Ok(match &self.kind {
461 KeyPairKind::Ec(kp) => {
462 let system_random = SystemRandom::new();
463 let signature = kp.sign(&system_random, msg)._err()?;
464 signature.as_ref().to_owned()
465 },
466 KeyPairKind::Ed(kp) => kp.sign(msg).as_ref().to_owned(),
467 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
468 KeyPairKind::Pq(kp) => {
469 let mut signature = vec![0; kp.algorithm().signature_len()];
470 kp.sign(msg, &mut signature)._err()?;
471 signature
472 },
473 KeyPairKind::Rsa(kp, padding_alg) => {
474 let system_random = SystemRandom::new();
475 let mut signature = vec![0; rsa_key_pair_public_modulus_len(kp)];
476 kp.sign(*padding_alg, &system_random, msg, &mut signature)
477 ._err()?;
478 signature
479 },
480 })
481 }
482}
483
484#[cfg(feature = "crypto")]
485impl PublicKeyData for KeyPair {
486 fn der_bytes(&self) -> &[u8] {
487 match &self.kind {
488 KeyPairKind::Ec(kp) => kp.public_key().as_ref(),
489 KeyPairKind::Ed(kp) => kp.public_key().as_ref(),
490 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
491 KeyPairKind::Pq(kp) => kp.public_key().as_ref(),
492 KeyPairKind::Rsa(kp, _) => kp.public_key().as_ref(),
493 }
494 }
495
496 fn algorithm(&self) -> &'static SignatureAlgorithm {
497 self.alg
498 }
499}
500
501#[cfg(feature = "crypto")]
502impl TryFrom<&[u8]> for KeyPair {
503 type Error = Error;
504
505 fn try_from(key: &[u8]) -> Result<KeyPair, Error> {
506 let key = &PrivateKeyDer::try_from(key).map_err(|_| Error::CouldNotParseKeyPair)?;
507
508 key.try_into()
509 }
510}
511
512#[cfg(feature = "crypto")]
513impl TryFrom<Vec<u8>> for KeyPair {
514 type Error = Error;
515
516 fn try_from(key: Vec<u8>) -> Result<KeyPair, Error> {
517 let key = &PrivateKeyDer::try_from(key).map_err(|_| Error::CouldNotParseKeyPair)?;
518
519 key.try_into()
520 }
521}
522
523#[cfg(feature = "crypto")]
524impl TryFrom<&PrivatePkcs8KeyDer<'_>> for KeyPair {
525 type Error = Error;
526
527 fn try_from(key: &PrivatePkcs8KeyDer) -> Result<KeyPair, Error> {
528 key.secret_pkcs8_der().try_into()
529 }
530}
531
532#[cfg(feature = "crypto")]
533impl TryFrom<&PrivateKeyDer<'_>> for KeyPair {
534 type Error = Error;
535
536 fn try_from(key: &PrivateKeyDer) -> Result<KeyPair, Error> {
537 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
538 let (kind, alg) = {
539 let PrivateKeyDer::Pkcs8(pkcs8) = key else {
540 return Err(Error::CouldNotParseKeyPair);
541 };
542 let pkcs8 = pkcs8.secret_pkcs8_der();
543 let rng = SystemRandom::new();
544 let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8) {
545 (KeyPairKind::Ed(edkp), &PKCS_ED25519)
546 } else if let Ok(eckp) =
547 ecdsa_from_pkcs8(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8, &rng)
548 {
549 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
550 } else if let Ok(eckp) =
551 ecdsa_from_pkcs8(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8, &rng)
552 {
553 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
554 } else if let Ok(rsakp) = RsaKeyPair::from_pkcs8(pkcs8) {
555 (
556 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
557 &PKCS_RSA_SHA256,
558 )
559 } else {
560 return Err(Error::CouldNotParseKeyPair);
561 };
562
563 (kind, alg)
564 };
565 #[cfg(feature = "aws_lc_rs")]
566 let (kind, alg) = {
567 let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
568
569 let key = key.secret_der();
570
571 let rsa_key_pair_from = if is_pkcs8 {
572 RsaKeyPair::from_pkcs8
573 } else {
574 RsaKeyPair::from_der
575 };
576
577 let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(key) {
578 (KeyPairKind::Ed(edkp), &PKCS_ED25519)
579 } else if let Ok(eckp) =
580 ecdsa_from_private_key_der(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, key)
581 {
582 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
583 } else if let Ok(eckp) =
584 ecdsa_from_private_key_der(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, key)
585 {
586 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
587 } else if let Ok(eckp) =
588 ecdsa_from_private_key_der(&signature::ECDSA_P521_SHA512_ASN1_SIGNING, key)
589 {
590 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P521_SHA512)
591 } else if let Ok(rsakp) = rsa_key_pair_from(key) {
592 (
593 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
594 &PKCS_RSA_SHA256,
595 )
596 } else {
597 return Err(Error::CouldNotParseKeyPair);
598 };
599 (kind, alg)
600 };
601
602 Ok(KeyPair {
603 kind,
604 alg,
605 serialized_der: key.secret_der().into(),
606 })
607 }
608}
609
610#[cfg(feature = "crypto")]
611impl From<KeyPair> for PrivatePkcs8KeyDer<'static> {
612 fn from(val: KeyPair) -> Self {
613 val.serialize_der().into()
614 }
615}
616
617#[cfg(feature = "crypto")]
618impl From<KeyPair> for PrivateKeyDer<'static> {
619 fn from(val: KeyPair) -> Self {
620 Self::from(PrivatePkcs8KeyDer::from(val))
621 }
622}
623
624#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
626#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
627#[non_exhaustive]
628pub enum RsaKeySize {
629 _2048,
631 _3072,
633 _4096,
635}
636
637pub(crate) fn sign_der(
638 key: &impl SigningKey,
639 f: impl FnOnce(&mut DERWriterSeq<'_>) -> Result<(), Error>,
640) -> Result<Vec<u8>, Error> {
641 yasna::try_construct_der(|writer| {
642 writer.write_sequence(|writer| {
643 let data = yasna::try_construct_der(|writer| writer.write_sequence(f))?;
644 writer.next().write_der(&data);
645
646 key.algorithm().write_alg_ident(writer.next());
648
649 let sig = key.sign(&data)?;
651 let writer = writer.next();
652 writer.write_bitvec_bytes(&sig, sig.len() * 8);
653
654 Ok(())
655 })
656 })
657}
658
659impl<S: SigningKey + ?Sized> SigningKey for &S {
660 fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error> {
661 (*self).sign(msg)
662 }
663}
664
665pub trait SigningKey: PublicKeyData {
667 fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error>;
669}
670
671#[cfg(feature = "crypto")]
672impl<T> ExternalError<T> for Result<T, ring_error::KeyRejected> {
673 fn _err(self) -> Result<T, Error> {
674 self.map_err(|e| Error::RingKeyRejected(e.to_string()))
675 }
676}
677
678#[cfg(feature = "crypto")]
679impl<T> ExternalError<T> for Result<T, ring_error::Unspecified> {
680 fn _err(self) -> Result<T, Error> {
681 self.map_err(|_| Error::RingUnspecified)
682 }
683}
684
685#[cfg(feature = "pem")]
686impl<T> ExternalError<T> for Result<T, pem::PemError> {
687 fn _err(self) -> Result<T, Error> {
688 self.map_err(|e| Error::PemError(e.to_string()))
689 }
690}
691
692#[derive(Clone, Debug, Eq, PartialEq)]
694pub struct SubjectPublicKeyInfo {
695 pub(crate) alg: &'static SignatureAlgorithm,
696 pub(crate) subject_public_key: Vec<u8>,
697}
698
699impl SubjectPublicKeyInfo {
700 #[cfg(all(feature = "x509-parser", feature = "pem"))]
702 pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
703 Self::from_der(&pem::parse(pem_str)._err()?.into_contents())
704 }
705
706 #[cfg(feature = "x509-parser")]
708 pub fn from_der(spki_der: &[u8]) -> Result<Self, Error> {
709 use x509_parser::prelude::FromDer;
710 use x509_parser::x509::{AlgorithmIdentifier, SubjectPublicKeyInfo};
711
712 let (rem, spki) =
713 SubjectPublicKeyInfo::from_der(spki_der).map_err(|e| Error::X509(e.to_string()))?;
714 if !rem.is_empty() {
715 return Err(Error::X509(
716 "trailing bytes in SubjectPublicKeyInfo".to_string(),
717 ));
718 }
719
720 let alg = SignatureAlgorithm::iter()
721 .find(|alg| {
722 let bytes = yasna::construct_der(|writer| {
723 alg.write_oids_sign_alg(writer);
724 });
725 let Ok((rest, aid)) = AlgorithmIdentifier::from_der(&bytes) else {
726 return false;
727 };
728 if !rest.is_empty() {
729 return false;
730 }
731 aid == spki.algorithm
732 })
733 .ok_or(Error::UnsupportedSignatureAlgorithm)?;
734
735 Ok(Self {
736 alg,
737 subject_public_key: Vec::from(spki.subject_public_key.as_ref()),
738 })
739 }
740}
741
742impl PublicKeyData for SubjectPublicKeyInfo {
743 fn der_bytes(&self) -> &[u8] {
744 &self.subject_public_key
745 }
746
747 fn algorithm(&self) -> &'static SignatureAlgorithm {
748 self.alg
749 }
750}
751
752impl<K: PublicKeyData + ?Sized> PublicKeyData for &K {
753 fn der_bytes(&self) -> &[u8] {
754 (*self).der_bytes()
755 }
756
757 fn algorithm(&self) -> &'static SignatureAlgorithm {
758 (*self).algorithm()
759 }
760}
761
762pub trait PublicKeyData {
764 fn subject_public_key_info(&self) -> Vec<u8> {
769 yasna::construct_der(|writer| serialize_public_key_der(self, writer))
770 }
771
772 fn der_bytes(&self) -> &[u8];
774
775 fn algorithm(&self) -> &'static SignatureAlgorithm;
777}
778
779pub(crate) fn serialize_public_key_der(key: &(impl PublicKeyData + ?Sized), writer: DERWriter) {
780 writer.write_sequence(|writer| {
781 key.algorithm().write_oids_sign_alg(writer.next());
782 let pk = key.der_bytes();
783 writer.next().write_bitvec_bytes(pk, pk.len() * 8);
784 })
785}
786
787#[cfg(all(test, feature = "crypto"))]
788mod test {
789 use super::*;
790 use crate::ring_like::rand::SystemRandom;
791 use crate::ring_like::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING};
792
793 #[cfg(all(feature = "x509-parser", feature = "pem"))]
794 #[test]
795 fn test_subject_public_key_parsing() {
796 for alg in [
797 &PKCS_ED25519,
798 &PKCS_ECDSA_P256_SHA256,
799 &PKCS_ECDSA_P384_SHA384,
800 #[cfg(feature = "aws_lc_rs")]
801 &PKCS_ECDSA_P521_SHA512,
802 #[cfg(feature = "aws_lc_rs")]
803 &PKCS_RSA_SHA256,
804 ] {
805 let kp = KeyPair::generate_for(alg).expect("keygen");
806 let pem = kp.public_key_pem();
807 let der = kp.subject_public_key_info();
808
809 let pkd_pem = SubjectPublicKeyInfo::from_pem(&pem).expect("from pem");
810 assert_eq!(kp.der_bytes(), pkd_pem.der_bytes());
811
812 let pkd_der = SubjectPublicKeyInfo::from_der(&der).expect("from der");
813 assert_eq!(kp.der_bytes(), pkd_der.der_bytes());
814 }
815 }
816
817 #[test]
818 fn test_algorithm() {
819 let rng = SystemRandom::new();
820 let pkcs8 = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &rng).unwrap();
821 let der = pkcs8.as_ref().to_vec();
822
823 let key_pair = KeyPair::try_from(der).unwrap();
824 assert_eq!(key_pair.algorithm(), &PKCS_ECDSA_P256_SHA256);
825 }
826}