1use std::fmt;
2
3#[cfg(feature = "pem")]
4use pem::Pem;
5#[cfg(feature = "crypto")]
6use pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer};
7use yasna::{DERWriter, DERWriterSeq};
8
9#[cfg(any(feature = "crypto", feature = "pem"))]
10use crate::error::ExternalError;
11#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
12use crate::ring_like::ecdsa_from_private_key_der;
13#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
14use crate::ring_like::rsa::KeySize;
15#[cfg(feature = "crypto")]
16use crate::ring_like::{
17 error as ring_error,
18 rand::SystemRandom,
19 signature::{
20 self, EcdsaKeyPair, Ed25519KeyPair, KeyPair as RingKeyPair, RsaEncoding, RsaKeyPair,
21 },
22 {ecdsa_from_pkcs8, rsa_key_pair_public_modulus_len},
23};
24#[cfg(feature = "crypto")]
25use crate::sign_algo::{algo::*, SignAlgo};
26#[cfg(feature = "pem")]
27use crate::ENCODE_CONFIG;
28use crate::{sign_algo::SignatureAlgorithm, Error};
29
30#[allow(clippy::large_enum_variant)]
32pub(crate) enum KeyPairKind {
33 #[cfg(feature = "crypto")]
35 Ec(EcdsaKeyPair),
36 #[cfg(feature = "crypto")]
38 Ed(Ed25519KeyPair),
39 #[cfg(feature = "crypto")]
41 Rsa(RsaKeyPair, &'static dyn RsaEncoding),
42 Remote(Box<dyn RemoteKeyPair + Send + Sync>),
44}
45
46impl fmt::Debug for KeyPairKind {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 match self {
49 #[cfg(feature = "crypto")]
50 Self::Ec(key_pair) => write!(f, "{:?}", key_pair),
51 #[cfg(feature = "crypto")]
52 Self::Ed(key_pair) => write!(f, "{:?}", key_pair),
53 #[cfg(feature = "crypto")]
54 Self::Rsa(key_pair, _) => write!(f, "{:?}", key_pair),
55 Self::Remote(_) => write!(f, "Box<dyn RemotePrivateKey>"),
56 }
57 }
58}
59
60#[derive(Debug)]
68pub struct KeyPair {
69 pub(crate) kind: KeyPairKind,
70 pub(crate) alg: &'static SignatureAlgorithm,
71 pub(crate) serialized_der: Vec<u8>,
72}
73
74impl KeyPair {
75 #[cfg(feature = "crypto")]
77 pub fn generate() -> Result<Self, Error> {
78 Self::generate_for(&PKCS_ECDSA_P256_SHA256)
79 }
80
81 #[cfg(feature = "crypto")]
88 pub fn generate_for(alg: &'static SignatureAlgorithm) -> Result<Self, Error> {
89 let rng = &SystemRandom::new();
90
91 match alg.sign_alg {
92 SignAlgo::EcDsa(sign_alg) => {
93 let key_pair_doc = EcdsaKeyPair::generate_pkcs8(sign_alg, rng)._err()?;
94 let key_pair_serialized = key_pair_doc.as_ref().to_vec();
95
96 let key_pair = ecdsa_from_pkcs8(sign_alg, key_pair_doc.as_ref(), rng).unwrap();
97 Ok(KeyPair {
98 kind: KeyPairKind::Ec(key_pair),
99 alg,
100 serialized_der: key_pair_serialized,
101 })
102 },
103 SignAlgo::EdDsa(_sign_alg) => {
104 let key_pair_doc = Ed25519KeyPair::generate_pkcs8(rng)._err()?;
105 let key_pair_serialized = key_pair_doc.as_ref().to_vec();
106
107 let key_pair = Ed25519KeyPair::from_pkcs8(key_pair_doc.as_ref()).unwrap();
108 Ok(KeyPair {
109 kind: KeyPairKind::Ed(key_pair),
110 alg,
111 serialized_der: key_pair_serialized,
112 })
113 },
114 #[cfg(feature = "aws_lc_rs")]
115 SignAlgo::Rsa(sign_alg) => Self::generate_rsa_inner(alg, sign_alg, KeySize::Rsa2048),
116 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
120 SignAlgo::Rsa(_sign_alg) => Err(Error::KeyGenerationUnavailable),
121 }
122 }
123
124 #[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
129 pub fn generate_rsa_for(
130 alg: &'static SignatureAlgorithm,
131 key_size: RsaKeySize,
132 ) -> Result<Self, Error> {
133 match alg.sign_alg {
134 SignAlgo::Rsa(sign_alg) => {
135 let key_size = match key_size {
136 RsaKeySize::_2048 => KeySize::Rsa2048,
137 RsaKeySize::_3072 => KeySize::Rsa3072,
138 RsaKeySize::_4096 => KeySize::Rsa4096,
139 };
140 Self::generate_rsa_inner(alg, sign_alg, key_size)
141 },
142 _ => Err(Error::KeyGenerationUnavailable),
143 }
144 }
145
146 #[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
147 fn generate_rsa_inner(
148 alg: &'static SignatureAlgorithm,
149 sign_alg: &'static dyn RsaEncoding,
150 key_size: KeySize,
151 ) -> Result<Self, Error> {
152 use aws_lc_rs::encoding::AsDer;
153 let key_pair = RsaKeyPair::generate(key_size)._err()?;
154 let key_pair_serialized = key_pair.as_der()._err()?.as_ref().to_vec();
155
156 Ok(KeyPair {
157 kind: KeyPairKind::Rsa(key_pair, sign_alg),
158 alg,
159 serialized_der: key_pair_serialized,
160 })
161 }
162
163 pub fn algorithm(&self) -> &'static SignatureAlgorithm {
165 self.alg
166 }
167
168 #[cfg(all(feature = "pem", feature = "crypto"))]
176 pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
177 let private_key = pem::parse(pem_str)._err()?;
178 Self::try_from(private_key.contents())
179 }
180
181 pub fn from_remote(key_pair: Box<dyn RemoteKeyPair + Send + Sync>) -> Result<Self, Error> {
183 Ok(Self {
184 alg: key_pair.algorithm(),
185 kind: KeyPairKind::Remote(key_pair),
186 serialized_der: Vec::new(),
187 })
188 }
189
190 #[cfg(all(feature = "pem", feature = "crypto"))]
198 pub fn from_pkcs8_pem_and_sign_algo(
199 pem_str: &str,
200 alg: &'static SignatureAlgorithm,
201 ) -> Result<Self, Error> {
202 let private_key = pem::parse(pem_str)._err()?;
203 let private_key_der: &[_] = private_key.contents();
204 Self::from_pkcs8_der_and_sign_algo(&PrivatePkcs8KeyDer::from(private_key_der), alg)
205 }
206
207 #[cfg(feature = "crypto")]
222 pub fn from_pkcs8_der_and_sign_algo(
223 pkcs8: &PrivatePkcs8KeyDer<'_>,
224 alg: &'static SignatureAlgorithm,
225 ) -> Result<Self, Error> {
226 let rng = &SystemRandom::new();
227 let serialized_der = pkcs8.secret_pkcs8_der().to_vec();
228
229 let kind = if alg == &PKCS_ED25519 {
230 KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
231 } else if alg == &PKCS_ECDSA_P256_SHA256 {
232 KeyPairKind::Ec(ecdsa_from_pkcs8(
233 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
234 &serialized_der,
235 rng,
236 )?)
237 } else if alg == &PKCS_ECDSA_P384_SHA384 {
238 KeyPairKind::Ec(ecdsa_from_pkcs8(
239 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
240 &serialized_der,
241 rng,
242 )?)
243 } else if alg == &PKCS_RSA_SHA256 {
244 let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
245 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
246 } else if alg == &PKCS_RSA_SHA384 {
247 let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
248 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
249 } else if alg == &PKCS_RSA_SHA512 {
250 let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
251 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
252 } else if alg == &PKCS_RSA_PSS_SHA256 {
253 let rsakp = RsaKeyPair::from_pkcs8(&serialized_der)._err()?;
254 KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
255 } else {
256 #[cfg(feature = "aws_lc_rs")]
257 if alg == &PKCS_ECDSA_P521_SHA512 {
258 KeyPairKind::Ec(ecdsa_from_pkcs8(
259 &signature::ECDSA_P521_SHA512_ASN1_SIGNING,
260 &serialized_der,
261 rng,
262 )?)
263 } else {
264 panic!("Unknown SignatureAlgorithm specified!");
265 }
266
267 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
268 panic!("Unknown SignatureAlgorithm specified!");
269 };
270
271 Ok(KeyPair {
272 kind,
273 alg,
274 serialized_der,
275 })
276 }
277
278 #[cfg(all(feature = "pem", feature = "crypto"))]
289 pub fn from_pem_and_sign_algo(
290 pem_str: &str,
291 alg: &'static SignatureAlgorithm,
292 ) -> Result<Self, Error> {
293 let private_key = pem::parse(pem_str)._err()?;
294 let private_key: &[_] = private_key.contents();
295 Self::from_der_and_sign_algo(
296 &PrivateKeyDer::try_from(private_key).map_err(|_| Error::CouldNotParseKeyPair)?,
297 alg,
298 )
299 }
300
301 #[cfg(feature = "crypto")]
317 pub fn from_der_and_sign_algo(
318 key: &PrivateKeyDer<'_>,
319 alg: &'static SignatureAlgorithm,
320 ) -> Result<Self, Error> {
321 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
322 {
323 if let PrivateKeyDer::Pkcs8(key) = key {
324 Self::from_pkcs8_der_and_sign_algo(key, alg)
325 } else {
326 Err(Error::CouldNotParseKeyPair)
327 }
328 }
329 #[cfg(feature = "aws_lc_rs")]
330 {
331 let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
332
333 let rsa_key_pair_from = if is_pkcs8 {
334 RsaKeyPair::from_pkcs8
335 } else {
336 RsaKeyPair::from_der
337 };
338
339 let serialized_der = key.secret_der().to_vec();
340
341 let kind = if alg == &PKCS_ED25519 {
342 KeyPairKind::Ed(Ed25519KeyPair::from_pkcs8_maybe_unchecked(&serialized_der)._err()?)
343 } else if alg == &PKCS_ECDSA_P256_SHA256 {
344 KeyPairKind::Ec(ecdsa_from_private_key_der(
345 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
346 &serialized_der,
347 )?)
348 } else if alg == &PKCS_ECDSA_P384_SHA384 {
349 KeyPairKind::Ec(ecdsa_from_private_key_der(
350 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
351 &serialized_der,
352 )?)
353 } else if alg == &PKCS_ECDSA_P521_SHA512 {
354 KeyPairKind::Ec(ecdsa_from_private_key_der(
355 &signature::ECDSA_P521_SHA512_ASN1_SIGNING,
356 &serialized_der,
357 )?)
358 } else if alg == &PKCS_RSA_SHA256 {
359 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
360 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256)
361 } else if alg == &PKCS_RSA_SHA384 {
362 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
363 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA384)
364 } else if alg == &PKCS_RSA_SHA512 {
365 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
366 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA512)
367 } else if alg == &PKCS_RSA_PSS_SHA256 {
368 let rsakp = rsa_key_pair_from(&serialized_der)._err()?;
369 KeyPairKind::Rsa(rsakp, &signature::RSA_PSS_SHA256)
370 } else {
371 panic!("Unknown SignatureAlgorithm specified!");
372 };
373
374 Ok(KeyPair {
375 kind,
376 alg,
377 serialized_der,
378 })
379 }
380 }
381
382 pub fn public_key_raw(&self) -> &[u8] {
388 self.der_bytes()
389 }
390
391 pub fn is_compatible(&self, signature_algorithm: &SignatureAlgorithm) -> bool {
393 self.alg == signature_algorithm
394 }
395
396 pub fn compatible_algs(&self) -> impl Iterator<Item = &'static SignatureAlgorithm> {
399 std::iter::once(self.alg)
400 }
401
402 pub(crate) fn sign_der(
403 &self,
404 f: impl FnOnce(&mut DERWriterSeq<'_>) -> Result<(), Error>,
405 ) -> Result<Vec<u8>, Error> {
406 yasna::try_construct_der(|writer| {
407 writer.write_sequence(|writer| {
408 let data = yasna::try_construct_der(|writer| writer.write_sequence(f))?;
409 writer.next().write_der(&data);
410
411 self.alg.write_alg_ident(writer.next());
413
414 self.sign(&data, writer.next())?;
416
417 Ok(())
418 })
419 })
420 }
421
422 pub(crate) fn sign(&self, msg: &[u8], writer: DERWriter) -> Result<(), Error> {
423 match &self.kind {
424 #[cfg(feature = "crypto")]
425 KeyPairKind::Ec(kp) => {
426 let system_random = SystemRandom::new();
427 let signature = kp.sign(&system_random, msg)._err()?;
428 let sig = &signature.as_ref();
429 writer.write_bitvec_bytes(sig, &sig.len() * 8);
430 },
431 #[cfg(feature = "crypto")]
432 KeyPairKind::Ed(kp) => {
433 let signature = kp.sign(msg);
434 let sig = &signature.as_ref();
435 writer.write_bitvec_bytes(sig, &sig.len() * 8);
436 },
437 #[cfg(feature = "crypto")]
438 KeyPairKind::Rsa(kp, padding_alg) => {
439 let system_random = SystemRandom::new();
440 let mut signature = vec![0; rsa_key_pair_public_modulus_len(kp)];
441 kp.sign(*padding_alg, &system_random, msg, &mut signature)
442 ._err()?;
443 let sig = &signature.as_ref();
444 writer.write_bitvec_bytes(sig, &sig.len() * 8);
445 },
446 KeyPairKind::Remote(kp) => {
447 let signature = kp.sign(msg)?;
448 writer.write_bitvec_bytes(&signature, &signature.len() * 8);
449 },
450 }
451 Ok(())
452 }
453
454 pub fn public_key_der(&self) -> Vec<u8> {
460 yasna::construct_der(|writer| serialize_public_key_der(self, writer))
461 }
462
463 #[cfg(feature = "pem")]
467 pub fn public_key_pem(&self) -> String {
468 let contents = self.public_key_der();
469 let p = Pem::new("PUBLIC KEY", contents);
470 pem::encode_config(&p, ENCODE_CONFIG)
471 }
472
473 pub fn serialize_der(&self) -> Vec<u8> {
477 #[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))]
478 if let KeyPairKind::Remote(_) = self.kind {
479 panic!("Serializing a remote key pair is not supported")
480 }
481
482 self.serialized_der.clone()
483 }
484
485 pub fn serialized_der(&self) -> &[u8] {
490 #[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))]
491 if let KeyPairKind::Remote(_) = self.kind {
492 panic!("Serializing a remote key pair is not supported")
493 }
494
495 &self.serialized_der
496 }
497
498 pub fn as_remote(&self) -> Option<&(dyn RemoteKeyPair + Send + Sync)> {
500 #[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))]
501 if let KeyPairKind::Remote(remote) = &self.kind {
502 Some(remote.as_ref())
503 } else {
504 None
505 }
506 }
507
508 #[cfg(feature = "pem")]
510 pub fn serialize_pem(&self) -> String {
511 let contents = self.serialize_der();
512 let p = Pem::new("PRIVATE KEY", contents);
513 pem::encode_config(&p, ENCODE_CONFIG)
514 }
515}
516
517#[cfg(feature = "crypto")]
518impl TryFrom<&[u8]> for KeyPair {
519 type Error = Error;
520
521 fn try_from(key: &[u8]) -> Result<KeyPair, Error> {
522 let key = &PrivateKeyDer::try_from(key).map_err(|_| Error::CouldNotParseKeyPair)?;
523
524 key.try_into()
525 }
526}
527
528#[cfg(feature = "crypto")]
529impl TryFrom<Vec<u8>> for KeyPair {
530 type Error = Error;
531
532 fn try_from(key: Vec<u8>) -> Result<KeyPair, Error> {
533 let key = &PrivateKeyDer::try_from(key).map_err(|_| Error::CouldNotParseKeyPair)?;
534
535 key.try_into()
536 }
537}
538
539#[cfg(feature = "crypto")]
540impl TryFrom<&PrivatePkcs8KeyDer<'_>> for KeyPair {
541 type Error = Error;
542
543 fn try_from(key: &PrivatePkcs8KeyDer) -> Result<KeyPair, Error> {
544 key.secret_pkcs8_der().try_into()
545 }
546}
547
548#[cfg(feature = "crypto")]
549impl TryFrom<&PrivateKeyDer<'_>> for KeyPair {
550 type Error = Error;
551
552 fn try_from(key: &PrivateKeyDer) -> Result<KeyPair, Error> {
553 #[cfg(all(feature = "ring", not(feature = "aws_lc_rs")))]
554 let (kind, alg) = {
555 let PrivateKeyDer::Pkcs8(pkcs8) = key else {
556 return Err(Error::CouldNotParseKeyPair);
557 };
558 let pkcs8 = pkcs8.secret_pkcs8_der();
559 let rng = SystemRandom::new();
560 let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8) {
561 (KeyPairKind::Ed(edkp), &PKCS_ED25519)
562 } else if let Ok(eckp) =
563 ecdsa_from_pkcs8(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8, &rng)
564 {
565 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
566 } else if let Ok(eckp) =
567 ecdsa_from_pkcs8(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8, &rng)
568 {
569 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
570 } else if let Ok(rsakp) = RsaKeyPair::from_pkcs8(pkcs8) {
571 (
572 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
573 &PKCS_RSA_SHA256,
574 )
575 } else {
576 return Err(Error::CouldNotParseKeyPair);
577 };
578
579 (kind, alg)
580 };
581 #[cfg(feature = "aws_lc_rs")]
582 let (kind, alg) = {
583 let is_pkcs8 = matches!(key, PrivateKeyDer::Pkcs8(_));
584
585 let key = key.secret_der();
586
587 let rsa_key_pair_from = if is_pkcs8 {
588 RsaKeyPair::from_pkcs8
589 } else {
590 RsaKeyPair::from_der
591 };
592
593 let (kind, alg) = if let Ok(edkp) = Ed25519KeyPair::from_pkcs8_maybe_unchecked(key) {
594 (KeyPairKind::Ed(edkp), &PKCS_ED25519)
595 } else if let Ok(eckp) =
596 ecdsa_from_private_key_der(&signature::ECDSA_P256_SHA256_ASN1_SIGNING, key)
597 {
598 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P256_SHA256)
599 } else if let Ok(eckp) =
600 ecdsa_from_private_key_der(&signature::ECDSA_P384_SHA384_ASN1_SIGNING, key)
601 {
602 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P384_SHA384)
603 } else if let Ok(eckp) =
604 ecdsa_from_private_key_der(&signature::ECDSA_P521_SHA512_ASN1_SIGNING, key)
605 {
606 (KeyPairKind::Ec(eckp), &PKCS_ECDSA_P521_SHA512)
607 } else if let Ok(rsakp) = rsa_key_pair_from(key) {
608 (
609 KeyPairKind::Rsa(rsakp, &signature::RSA_PKCS1_SHA256),
610 &PKCS_RSA_SHA256,
611 )
612 } else {
613 return Err(Error::CouldNotParseKeyPair);
614 };
615 (kind, alg)
616 };
617
618 Ok(KeyPair {
619 kind,
620 alg,
621 serialized_der: key.secret_der().into(),
622 })
623 }
624}
625
626#[cfg(all(feature = "crypto", feature = "aws_lc_rs"))]
628#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
629#[non_exhaustive]
630pub enum RsaKeySize {
631 _2048,
633 _3072,
635 _4096,
637}
638
639impl PublicKeyData for KeyPair {
640 fn der_bytes(&self) -> &[u8] {
641 match &self.kind {
642 #[cfg(feature = "crypto")]
643 KeyPairKind::Ec(kp) => kp.public_key().as_ref(),
644 #[cfg(feature = "crypto")]
645 KeyPairKind::Ed(kp) => kp.public_key().as_ref(),
646 #[cfg(feature = "crypto")]
647 KeyPairKind::Rsa(kp, _) => kp.public_key().as_ref(),
648 KeyPairKind::Remote(kp) => kp.public_key(),
649 }
650 }
651
652 fn algorithm(&self) -> &SignatureAlgorithm {
653 self.alg
654 }
655}
656
657pub trait RemoteKeyPair {
662 fn public_key(&self) -> &[u8];
664
665 fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, Error>;
667
668 fn algorithm(&self) -> &'static SignatureAlgorithm;
670}
671
672#[cfg(feature = "crypto")]
673impl<T> ExternalError<T> for Result<T, ring_error::KeyRejected> {
674 fn _err(self) -> Result<T, Error> {
675 self.map_err(|e| Error::RingKeyRejected(e.to_string()))
676 }
677}
678
679#[cfg(feature = "crypto")]
680impl<T> ExternalError<T> for Result<T, ring_error::Unspecified> {
681 fn _err(self) -> Result<T, Error> {
682 self.map_err(|_| Error::RingUnspecified)
683 }
684}
685
686#[cfg(feature = "pem")]
687impl<T> ExternalError<T> for Result<T, pem::PemError> {
688 fn _err(self) -> Result<T, Error> {
689 self.map_err(|e| Error::PemError(e.to_string()))
690 }
691}
692
693#[derive(Clone, Debug, Eq, PartialEq)]
695pub struct SubjectPublicKeyInfo {
696 pub(crate) alg: &'static SignatureAlgorithm,
697 pub(crate) subject_public_key: Vec<u8>,
698}
699
700impl SubjectPublicKeyInfo {
701 #[cfg(all(feature = "x509-parser", feature = "pem"))]
703 pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
704 Self::from_der(&pem::parse(pem_str)._err()?.into_contents())
705 }
706
707 #[cfg(feature = "x509-parser")]
709 pub fn from_der(spki_der: &[u8]) -> Result<Self, Error> {
710 use x509_parser::{
711 prelude::FromDer,
712 x509::{AlgorithmIdentifier, SubjectPublicKeyInfo},
713 };
714
715 let (rem, spki) =
716 SubjectPublicKeyInfo::from_der(spki_der).map_err(|e| Error::X509(e.to_string()))?;
717 if !rem.is_empty() {
718 return Err(Error::X509(
719 "trailing bytes in SubjectPublicKeyInfo".to_string(),
720 ));
721 }
722
723 let alg = SignatureAlgorithm::iter()
724 .find(|alg| {
725 let bytes = yasna::construct_der(|writer| {
726 alg.write_oids_sign_alg(writer);
727 });
728 let Ok((rest, aid)) = AlgorithmIdentifier::from_der(&bytes) else {
729 return false;
730 };
731 if !rest.is_empty() {
732 return false;
733 }
734 aid == spki.algorithm
735 })
736 .ok_or(Error::UnsupportedSignatureAlgorithm)?;
737
738 Ok(Self {
739 alg,
740 subject_public_key: Vec::from(spki.subject_public_key.as_ref()),
741 })
742 }
743}
744
745impl PublicKeyData for SubjectPublicKeyInfo {
746 fn der_bytes(&self) -> &[u8] {
747 &self.subject_public_key
748 }
749
750 fn algorithm(&self) -> &SignatureAlgorithm {
751 self.alg
752 }
753}
754
755pub trait PublicKeyData {
757 fn der_bytes(&self) -> &[u8];
759
760 fn algorithm(&self) -> &SignatureAlgorithm;
762}
763
764pub(crate) fn serialize_public_key_der(key: &impl PublicKeyData, writer: DERWriter) {
765 writer.write_sequence(|writer| {
766 key.algorithm().write_oids_sign_alg(writer.next());
767 let pk = key.der_bytes();
768 writer.next().write_bitvec_bytes(pk, pk.len() * 8);
769 })
770}
771
772#[cfg(all(test, feature = "crypto"))]
773mod test {
774 use super::*;
775
776 use crate::ring_like::{
777 rand::SystemRandom,
778 signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING},
779 };
780
781 #[cfg(all(feature = "x509-parser", feature = "pem"))]
782 #[test]
783 fn test_subject_public_key_parsing() {
784 for alg in [
785 &PKCS_ED25519,
786 &PKCS_ECDSA_P256_SHA256,
787 &PKCS_ECDSA_P384_SHA384,
788 #[cfg(feature = "aws_lc_rs")]
789 &PKCS_ECDSA_P521_SHA512,
790 #[cfg(feature = "aws_lc_rs")]
791 &PKCS_RSA_SHA256,
792 ] {
793 let kp = KeyPair::generate_for(alg).expect("keygen");
794 let pem = kp.public_key_pem();
795 let der = kp.public_key_der();
796
797 let pkd_pem = SubjectPublicKeyInfo::from_pem(&pem).expect("from pem");
798 assert_eq!(kp.der_bytes(), pkd_pem.der_bytes());
799
800 let pkd_der = SubjectPublicKeyInfo::from_der(&der).expect("from der");
801 assert_eq!(kp.der_bytes(), pkd_der.der_bytes());
802 }
803 }
804
805 #[test]
806 fn test_algorithm() {
807 let rng = SystemRandom::new();
808 let pkcs8 = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &rng).unwrap();
809 let der = pkcs8.as_ref().to_vec();
810
811 let key_pair = KeyPair::try_from(der).unwrap();
812 assert_eq!(key_pair.algorithm(), &PKCS_ECDSA_P256_SHA256);
813 }
814}