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_SHA512 {
268 KeyPairKind::Ec(ecdsa_from_pkcs8(
269 &signature::ECDSA_P521_SHA512_ASN1_SIGNING,
270 &serialized_der,
271 rng,
272 )?)
273 } else {
274 panic!("Unknown SignatureAlgorithm specified!");
275 }
276
277 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
278 panic!("Unknown SignatureAlgorithm specified!");
279 };
280
281 Ok(KeyPair {
282 kind,
283 alg,
284 serialized_der,
285 })
286 }
287
288 #[cfg(all(feature = "pem", feature = "crypto"))]
299 pub fn from_pem_and_sign_algo(
300 pem_str: &str,
301 alg: &'static SignatureAlgorithm,
302 ) -> Result<Self, Error> {
303 let private_key = pem::parse(pem_str)._err()?;
304 let private_key: &[_] = private_key.contents();
305 Self::from_der_and_sign_algo(
306 &PrivateKeyDer::try_from(private_key).map_err(|_| Error::CouldNotParseKeyPair)?,
307 alg,
308 )
309 }
310
311 #[cfg(feature = "crypto")]
327 pub fn from_der_and_sign_algo(
328 key: &PrivateKeyDer<'_>,
329 alg: &'static SignatureAlgorithm,
330 ) -> Result<Self, Error> {
331 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
332 {
333 if let PrivateKeyDer::Pkcs8(key) = key {
334 Self::from_pkcs8_der_and_sign_algo(key, alg)
335 } else {
336 Err(Error::CouldNotParseKeyPair)
337 }
338 }
339 #[cfg(feature = "aws_lc_rs")]
340 {
341 let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
342
343 let rsa_key_pair_from = if is_pkcs8 {
344 RsaKeyPair::from_pkcs8
345 } else {
346 RsaKeyPair::from_der
347 };
348
349 let serialized_der = key.secret_der().to_vec();
350
351 let kind = if alg == &PKCS_ED25519 {
352 KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
353 } else if alg == &PKCS_ECDSA_P256_SHA256 {
354 KeyPairKind::Ec(ecdsa_from_private_key_der(
355 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
356 &serialized_der,
357 )?)
358 } else if alg == &PKCS_ECDSA_P384_SHA384 {
359 KeyPairKind::Ec(ecdsa_from_private_key_der(
360 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
361 &serialized_der,
362 )?)
363 } else if alg == &PKCS_ECDSA_P521_SHA512 {
364 KeyPairKind::Ec(ecdsa_from_private_key_der(
365 &signature::ECDSA_P521_SHA512_ASN1_SIGNING,
366 &serialized_der,
367 )?)
368 } else if alg == &PKCS_RSA_SHA256 {
369 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
370 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
371 } else if alg == &PKCS_RSA_SHA384 {
372 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
373 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
374 } else if alg == &PKCS_RSA_SHA512 {
375 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
376 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
377 } else if alg == &PKCS_RSA_PSS_SHA256 {
378 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
379 KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
380 } else {
381 panic!("Unknown SignatureAlgorithm specified!");
382 };
383
384 Ok(KeyPair {
385 kind,
386 alg,
387 serialized_der,
388 })
389 }
390 }
391
392 pub fn public_key_raw(&self) -> &[u8] {
401 self.der_bytes()
402 }
403
404 pub fn is_compatible(&self, signature_algorithm: &SignatureAlgorithm) -> bool {
406 self.alg == signature_algorithm
407 }
408
409 pub fn compatible_algs(&self) -> impl Iterator<Item = &'static SignatureAlgorithm> {
412 std::iter::once(self.alg)
413 }
414
415 #[cfg(feature = "pem")]
419 pub fn public_key_pem(&self) -> String {
420 let contents = self.subject_public_key_info();
421 let p = Pem::new("PUBLIC KEY", contents);
422 pem::encode_config(&p, ENCODE_CONFIG)
423 }
424
425 pub fn serialize_der(&self) -> Vec<u8> {
427 self.serialized_der.clone()
428 }
429
430 pub fn serialized_der(&self) -> &[u8] {
433 &self.serialized_der
434 }
435
436 #[cfg(feature = "pem")]
438 pub fn serialize_pem(&self) -> String {
439 let contents = self.serialize_der();
440 let p = Pem::new("PRIVATE KEY", contents);
441 pem::encode_config(&p, ENCODE_CONFIG)
442 }
443}
444
445#[cfg(feature = "crypto")]
446impl SigningKey for KeyPair {
447 fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error> {
448 Ok(match &self.kind {
449 KeyPairKind::Ec(kp) => {
450 let system_random = SystemRandom::new();
451 let signature = kp.sign(&system_random, msg)._err()?;
452 signature.as_ref().to_owned()
453 },
454 KeyPairKind::Ed(kp) => kp.sign(msg).as_ref().to_owned(),
455 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
456 KeyPairKind::Pq(kp) => {
457 let mut signature = vec![0; kp.algorithm().signature_len()];
458 kp.sign(msg, &mut signature)._err()?;
459 signature
460 },
461 KeyPairKind::Rsa(kp, padding_alg) => {
462 let system_random = SystemRandom::new();
463 let mut signature = vec![0; rsa_key_pair_public_modulus_len(kp)];
464 kp.sign(*padding_alg, &system_random, msg, &mut signature)
465 ._err()?;
466 signature
467 },
468 })
469 }
470}
471
472#[cfg(feature = "crypto")]
473impl PublicKeyData for KeyPair {
474 fn der_bytes(&self) -> &[u8] {
475 match &self.kind {
476 KeyPairKind::Ec(kp) => kp.public_key().as_ref(),
477 KeyPairKind::Ed(kp) => kp.public_key().as_ref(),
478 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
479 KeyPairKind::Pq(kp) => kp.public_key().as_ref(),
480 KeyPairKind::Rsa(kp, _) => kp.public_key().as_ref(),
481 }
482 }
483
484 fn algorithm(&self) -> &'static SignatureAlgorithm {
485 self.alg
486 }
487}
488
489#[cfg(feature = "crypto")]
490impl TryFrom<&[u8]> for KeyPair {
491 type Error = Error;
492
493 fn try_from(key: &[u8]) -> Result<KeyPair, Error> {
494 let key = &PrivateKeyDer::try_from(key).map_err(|_| Error::CouldNotParseKeyPair)?;
495
496 key.try_into()
497 }
498}
499
500#[cfg(feature = "crypto")]
501impl TryFrom<Vec<u8>> for KeyPair {
502 type Error = Error;
503
504 fn try_from(key: Vec<u8>) -> Result<KeyPair, Error> {
505 let key = &PrivateKeyDer::try_from(key).map_err(|_| Error::CouldNotParseKeyPair)?;
506
507 key.try_into()
508 }
509}
510
511#[cfg(feature = "crypto")]
512impl TryFrom<&PrivatePkcs8KeyDer<'_>> for KeyPair {
513 type Error = Error;
514
515 fn try_from(key: &PrivatePkcs8KeyDer) -> Result<KeyPair, Error> {
516 key.secret_pkcs8_der().try_into()
517 }
518}
519
520#[cfg(feature = "crypto")]
521impl TryFrom<&PrivateKeyDer<'_>> for KeyPair {
522 type Error = Error;
523
524 fn try_from(key: &PrivateKeyDer) -> Result<KeyPair, Error> {
525 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
526 let (kind, alg) = {
527 let PrivateKeyDer::Pkcs8(pkcs8) = key else {
528 return Err(Error::CouldNotParseKeyPair);
529 };
530 let pkcs8 = pkcs8.secret_pkcs8_der();
531 let rng = SystemRandom::new();
532 let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8) {
533 (KeyPairKind::Ed(edkp), &PKCS_ED25519)
534 } else if let Ok(eckp) =
535 ecdsa_from_pkcs8(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8, &rng)
536 {
537 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
538 } else if let Ok(eckp) =
539 ecdsa_from_pkcs8(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8, &rng)
540 {
541 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
542 } else if let Ok(rsakp) = RsaKeyPair::from_pkcs8(pkcs8) {
543 (
544 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
545 &PKCS_RSA_SHA256,
546 )
547 } else {
548 return Err(Error::CouldNotParseKeyPair);
549 };
550
551 (kind, alg)
552 };
553 #[cfg(feature = "aws_lc_rs")]
554 let (kind, alg) = {
555 let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
556
557 let key = key.secret_der();
558
559 let rsa_key_pair_from = if is_pkcs8 {
560 RsaKeyPair::from_pkcs8
561 } else {
562 RsaKeyPair::from_der
563 };
564
565 let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(key) {
566 (KeyPairKind::Ed(edkp), &PKCS_ED25519)
567 } else if let Ok(eckp) =
568 ecdsa_from_private_key_der(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, key)
569 {
570 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
571 } else if let Ok(eckp) =
572 ecdsa_from_private_key_der(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, key)
573 {
574 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
575 } else if let Ok(eckp) =
576 ecdsa_from_private_key_der(&signature::ECDSA_P521_SHA512_ASN1_SIGNING, key)
577 {
578 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P521_SHA512)
579 } else if let Ok(rsakp) = rsa_key_pair_from(key) {
580 (
581 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
582 &PKCS_RSA_SHA256,
583 )
584 } else {
585 return Err(Error::CouldNotParseKeyPair);
586 };
587 (kind, alg)
588 };
589
590 Ok(KeyPair {
591 kind,
592 alg,
593 serialized_der: key.secret_der().into(),
594 })
595 }
596}
597
598#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
600#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
601#[non_exhaustive]
602pub enum RsaKeySize {
603 _2048,
605 _3072,
607 _4096,
609}
610
611pub(crate) fn sign_der(
612 key: &impl SigningKey,
613 f: impl FnOnce(&mut DERWriterSeq<'_>) -> Result<(), Error>,
614) -> Result<Vec<u8>, Error> {
615 yasna::try_construct_der(|writer| {
616 writer.write_sequence(|writer| {
617 let data = yasna::try_construct_der(|writer| writer.write_sequence(f))?;
618 writer.next().write_der(&data);
619
620 key.algorithm().write_alg_ident(writer.next());
622
623 let sig = key.sign(&data)?;
625 let writer = writer.next();
626 writer.write_bitvec_bytes(&sig, sig.len() * 8);
627
628 Ok(())
629 })
630 })
631}
632
633impl<S: SigningKey + ?Sized> SigningKey for &S {
634 fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error> {
635 (*self).sign(msg)
636 }
637}
638
639pub trait SigningKey: PublicKeyData {
641 fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error>;
643}
644
645#[cfg(feature = "crypto")]
646impl<T> ExternalError<T> for Result<T, ring_error::KeyRejected> {
647 fn _err(self) -> Result<T, Error> {
648 self.map_err(|e| Error::RingKeyRejected(e.to_string()))
649 }
650}
651
652#[cfg(feature = "crypto")]
653impl<T> ExternalError<T> for Result<T, ring_error::Unspecified> {
654 fn _err(self) -> Result<T, Error> {
655 self.map_err(|_| Error::RingUnspecified)
656 }
657}
658
659#[cfg(feature = "pem")]
660impl<T> ExternalError<T> for Result<T, pem::PemError> {
661 fn _err(self) -> Result<T, Error> {
662 self.map_err(|e| Error::PemError(e.to_string()))
663 }
664}
665
666#[derive(Clone, Debug, Eq, PartialEq)]
668pub struct SubjectPublicKeyInfo {
669 pub(crate) alg: &'static SignatureAlgorithm,
670 pub(crate) subject_public_key: Vec<u8>,
671}
672
673impl SubjectPublicKeyInfo {
674 #[cfg(all(feature = "x509-parser", feature = "pem"))]
676 pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
677 Self::from_der(&pem::parse(pem_str)._err()?.into_contents())
678 }
679
680 #[cfg(feature = "x509-parser")]
682 pub fn from_der(spki_der: &[u8]) -> Result<Self, Error> {
683 use x509_parser::prelude::FromDer;
684 use x509_parser::x509::{AlgorithmIdentifier, SubjectPublicKeyInfo};
685
686 let (rem, spki) =
687 SubjectPublicKeyInfo::from_der(spki_der).map_err(|e| Error::X509(e.to_string()))?;
688 if !rem.is_empty() {
689 return Err(Error::X509(
690 "trailing bytes in SubjectPublicKeyInfo".to_string(),
691 ));
692 }
693
694 let alg = SignatureAlgorithm::iter()
695 .find(|alg| {
696 let bytes = yasna::construct_der(|writer| {
697 alg.write_oids_sign_alg(writer);
698 });
699 let Ok((rest, aid)) = AlgorithmIdentifier::from_der(&bytes) else {
700 return false;
701 };
702 if !rest.is_empty() {
703 return false;
704 }
705 aid == spki.algorithm
706 })
707 .ok_or(Error::UnsupportedSignatureAlgorithm)?;
708
709 Ok(Self {
710 alg,
711 subject_public_key: Vec::from(spki.subject_public_key.as_ref()),
712 })
713 }
714}
715
716impl PublicKeyData for SubjectPublicKeyInfo {
717 fn der_bytes(&self) -> &[u8] {
718 &self.subject_public_key
719 }
720
721 fn algorithm(&self) -> &'static SignatureAlgorithm {
722 self.alg
723 }
724}
725
726impl<K: PublicKeyData + ?Sized> PublicKeyData for &K {
727 fn der_bytes(&self) -> &[u8] {
728 (*self).der_bytes()
729 }
730
731 fn algorithm(&self) -> &'static SignatureAlgorithm {
732 (*self).algorithm()
733 }
734}
735
736pub trait PublicKeyData {
738 fn subject_public_key_info(&self) -> Vec<u8> {
743 yasna::construct_der(|writer| serialize_public_key_der(self, writer))
744 }
745
746 fn der_bytes(&self) -> &[u8];
748
749 fn algorithm(&self) -> &'static SignatureAlgorithm;
751}
752
753pub(crate) fn serialize_public_key_der(key: &(impl PublicKeyData + ?Sized), writer: DERWriter) {
754 writer.write_sequence(|writer| {
755 key.algorithm().write_oids_sign_alg(writer.next());
756 let pk = key.der_bytes();
757 writer.next().write_bitvec_bytes(pk, pk.len() * 8);
758 })
759}
760
761#[cfg(all(test, feature = "crypto"))]
762mod test {
763 use super::*;
764 use crate::ring_like::rand::SystemRandom;
765 use crate::ring_like::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING};
766
767 #[cfg(all(feature = "x509-parser", feature = "pem"))]
768 #[test]
769 fn test_subject_public_key_parsing() {
770 for alg in [
771 &PKCS_ED25519,
772 &PKCS_ECDSA_P256_SHA256,
773 &PKCS_ECDSA_P384_SHA384,
774 #[cfg(feature = "aws_lc_rs")]
775 &PKCS_ECDSA_P521_SHA512,
776 #[cfg(feature = "aws_lc_rs")]
777 &PKCS_RSA_SHA256,
778 ] {
779 let kp = KeyPair::generate_for(alg).expect("keygen");
780 let pem = kp.public_key_pem();
781 let der = kp.subject_public_key_info();
782
783 let pkd_pem = SubjectPublicKeyInfo::from_pem(&pem).expect("from pem");
784 assert_eq!(kp.der_bytes(), pkd_pem.der_bytes());
785
786 let pkd_der = SubjectPublicKeyInfo::from_der(&der).expect("from der");
787 assert_eq!(kp.der_bytes(), pkd_der.der_bytes());
788 }
789 }
790
791 #[test]
792 fn test_algorithm() {
793 let rng = SystemRandom::new();
794 let pkcs8 = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &rng).unwrap();
795 let der = pkcs8.as_ref().to_vec();
796
797 let key_pair = KeyPair::try_from(der).unwrap();
798 assert_eq!(key_pair.algorithm(), &PKCS_ECDSA_P256_SHA256);
799 }
800}