1use std::{ops::Deref, sync::Arc};
10
11use der::{Decode, Encode, EncodePem, zeroize::Zeroizing};
12use elliptic_curve::{pkcs8::EncodePrivateKey, sec1::ToEncodedPoint};
13use mas_iana::jose::{JsonWebKeyType, JsonWebSignatureAlg};
14pub use mas_jose::jwk::{JsonWebKey, JsonWebKeySet};
15use mas_jose::{
16 jwa::{AsymmetricSigningKey, AsymmetricVerifyingKey},
17 jwk::{JsonWebKeyPublicParameters, ParametersInfo, PublicJsonWebKeySet},
18};
19use pem_rfc7468::PemLabel;
20use pkcs1::EncodeRsaPrivateKey;
21use pkcs8::{AssociatedOid, PrivateKeyInfo};
22use rand::{CryptoRng, RngCore};
23use rsa::BigUint;
24use thiserror::Error;
25
26mod encrypter;
27
28pub use aead;
29
30pub use self::encrypter::{DecryptError, Encrypter};
31
32#[derive(Debug, Error)]
34pub enum LoadError {
35 #[error("Failed to read PEM document")]
36 Pem {
37 #[from]
38 inner: pem_rfc7468::Error,
39 },
40
41 #[error("Invalid RSA private key")]
42 Rsa {
43 #[from]
44 inner: rsa::errors::Error,
45 },
46
47 #[error("Failed to decode PKCS1-encoded RSA key")]
48 Pkcs1 {
49 #[from]
50 inner: pkcs1::Error,
51 },
52
53 #[error("Failed to decode PKCS8-encoded key")]
54 Pkcs8 {
55 #[from]
56 inner: pkcs8::Error,
57 },
58
59 #[error(transparent)]
60 Der {
61 #[from]
62 inner: der::Error,
63 },
64
65 #[error(transparent)]
66 Spki {
67 #[from]
68 inner: spki::Error,
69 },
70
71 #[error("Unknown Elliptic Curve OID {oid}")]
72 UnknownEllipticCurveOid { oid: const_oid::ObjectIdentifier },
73
74 #[error("Unknown algorithm OID {oid}")]
75 UnknownAlgorithmOid { oid: const_oid::ObjectIdentifier },
76
77 #[error("Unsupported PEM label {label:?}")]
78 UnsupportedPemLabel { label: String },
79
80 #[error("Missing parameters in SEC1 key")]
81 MissingSec1Parameters,
82
83 #[error("Missing curve name in SEC1 parameters")]
84 MissingSec1CurveName,
85
86 #[error("Key is encrypted and no password was provided")]
87 Encrypted,
88
89 #[error("Key is not encrypted but a password was provided")]
90 Unencrypted,
91
92 #[error("Unsupported format")]
93 UnsupportedFormat,
94
95 #[error("Could not decode encrypted payload")]
96 InEncrypted {
97 #[source]
98 inner: Box<LoadError>,
99 },
100}
101
102impl LoadError {
103 #[must_use]
107 pub fn is_encrypted(&self) -> bool {
108 matches!(self, Self::Encrypted)
109 }
110
111 #[must_use]
115 pub fn is_unencrypted(&self) -> bool {
116 matches!(self, Self::Unencrypted)
117 }
118}
119
120#[non_exhaustive]
122#[derive(Debug)]
123pub enum PrivateKey {
124 Rsa(Box<rsa::RsaPrivateKey>),
125 EcP256(Box<elliptic_curve::SecretKey<p256::NistP256>>),
126 EcP384(Box<elliptic_curve::SecretKey<p384::NistP384>>),
127 EcK256(Box<elliptic_curve::SecretKey<k256::Secp256k1>>),
128}
129
130#[derive(Debug, Error)]
132#[error("Wrong algorithm for key")]
133pub struct WrongAlgorithmError;
134
135impl PrivateKey {
136 fn from_pkcs1_private_key(pkcs1_key: &pkcs1::RsaPrivateKey) -> Result<Self, LoadError> {
137 if pkcs1_key.version() != pkcs1::Version::TwoPrime {
141 return Err(pkcs1::Error::Version.into());
142 }
143
144 let n = BigUint::from_bytes_be(pkcs1_key.modulus.as_bytes());
145 let e = BigUint::from_bytes_be(pkcs1_key.public_exponent.as_bytes());
146 let d = BigUint::from_bytes_be(pkcs1_key.private_exponent.as_bytes());
147 let first_prime = BigUint::from_bytes_be(pkcs1_key.prime1.as_bytes());
148 let second_prime = BigUint::from_bytes_be(pkcs1_key.prime2.as_bytes());
149 let primes = vec![first_prime, second_prime];
150 let key = rsa::RsaPrivateKey::from_components(n, e, d, primes)?;
151 Ok(Self::Rsa(Box::new(key)))
152 }
153
154 fn from_private_key_info(info: PrivateKeyInfo) -> Result<Self, LoadError> {
155 match info.algorithm.oid {
156 pkcs1::ALGORITHM_OID => Ok(Self::Rsa(Box::new(info.try_into()?))),
157 elliptic_curve::ALGORITHM_OID => match info.algorithm.parameters_oid()? {
158 p256::NistP256::OID => Ok(Self::EcP256(Box::new(info.try_into()?))),
159 p384::NistP384::OID => Ok(Self::EcP384(Box::new(info.try_into()?))),
160 k256::Secp256k1::OID => Ok(Self::EcK256(Box::new(info.try_into()?))),
161 oid => Err(LoadError::UnknownEllipticCurveOid { oid }),
162 },
163 oid => Err(LoadError::UnknownAlgorithmOid { oid }),
164 }
165 }
166
167 fn from_ec_private_key(key: sec1::EcPrivateKey) -> Result<Self, LoadError> {
168 let curve = key
169 .parameters
170 .ok_or(LoadError::MissingSec1Parameters)?
171 .named_curve()
172 .ok_or(LoadError::MissingSec1CurveName)?;
173
174 match curve {
175 p256::NistP256::OID => Ok(Self::EcP256(Box::new(key.try_into()?))),
176 p384::NistP384::OID => Ok(Self::EcP384(Box::new(key.try_into()?))),
177 k256::Secp256k1::OID => Ok(Self::EcK256(Box::new(key.try_into()?))),
178 oid => Err(LoadError::UnknownEllipticCurveOid { oid }),
179 }
180 }
181
182 pub fn to_der(&self) -> Result<Zeroizing<Vec<u8>>, pkcs1::Error> {
191 let der = match self {
192 PrivateKey::Rsa(key) => key.to_pkcs1_der()?.to_bytes(),
193 PrivateKey::EcP256(key) => to_sec1_der(key)?,
194 PrivateKey::EcP384(key) => to_sec1_der(key)?,
195 PrivateKey::EcK256(key) => to_sec1_der(key)?,
196 };
197
198 Ok(der)
199 }
200
201 pub fn to_pkcs8_der(&self) -> Result<Zeroizing<Vec<u8>>, pkcs8::Error> {
207 let der = match self {
208 PrivateKey::Rsa(key) => key.to_pkcs8_der()?,
209 PrivateKey::EcP256(key) => key.to_pkcs8_der()?,
210 PrivateKey::EcP384(key) => key.to_pkcs8_der()?,
211 PrivateKey::EcK256(key) => key.to_pkcs8_der()?,
212 };
213
214 Ok(der.to_bytes())
215 }
216
217 pub fn to_pem(
226 &self,
227 line_ending: pem_rfc7468::LineEnding,
228 ) -> Result<Zeroizing<String>, pkcs1::Error> {
229 let pem = match self {
230 PrivateKey::Rsa(key) => key.to_pkcs1_pem(line_ending)?,
231 PrivateKey::EcP256(key) => to_sec1_pem(key, line_ending)?,
232 PrivateKey::EcP384(key) => to_sec1_pem(key, line_ending)?,
233 PrivateKey::EcK256(key) => to_sec1_pem(key, line_ending)?,
234 };
235
236 Ok(pem)
237 }
238
239 pub fn load(bytes: &[u8]) -> Result<Self, LoadError> {
246 if let Ok(pem) = std::str::from_utf8(bytes) {
247 match Self::load_pem(pem) {
248 Ok(s) => return Ok(s),
249 Err(LoadError::Pem { .. }) => {}
252 Err(e) => return Err(e),
253 }
254 }
255
256 Self::load_der(bytes)
257 }
258
259 pub fn load_encrypted(bytes: &[u8], password: impl AsRef<[u8]>) -> Result<Self, LoadError> {
267 if let Ok(pem) = std::str::from_utf8(bytes) {
268 match Self::load_encrypted_pem(pem, password.as_ref()) {
269 Ok(s) => return Ok(s),
270 Err(LoadError::Pem { .. }) => {}
273 Err(e) => return Err(e),
274 }
275 }
276
277 Self::load_encrypted_der(bytes, password)
278 }
279
280 pub fn load_encrypted_der(der: &[u8], password: impl AsRef<[u8]>) -> Result<Self, LoadError> {
290 if let Ok(info) = pkcs8::EncryptedPrivateKeyInfo::from_der(der) {
291 let decrypted = info.decrypt(password)?;
292 return Self::load_der(decrypted.as_bytes()).map_err(|inner| LoadError::InEncrypted {
293 inner: Box::new(inner),
294 });
295 }
296
297 if pkcs8::PrivateKeyInfo::from_der(der).is_ok()
298 || sec1::EcPrivateKey::from_der(der).is_ok()
299 || pkcs1::RsaPrivateKey::from_der(der).is_ok()
300 {
301 return Err(LoadError::Unencrypted);
302 }
303
304 Err(LoadError::UnsupportedFormat)
305 }
306
307 pub fn load_der(der: &[u8]) -> Result<Self, LoadError> {
319 if pkcs8::EncryptedPrivateKeyInfo::from_der(der).is_ok() {
321 return Err(LoadError::Encrypted);
322 }
323
324 if let Ok(info) = pkcs8::PrivateKeyInfo::from_der(der) {
325 return Self::from_private_key_info(info);
326 }
327
328 if let Ok(info) = sec1::EcPrivateKey::from_der(der) {
329 return Self::from_ec_private_key(info);
330 }
331
332 if let Ok(pkcs1_key) = pkcs1::RsaPrivateKey::from_der(der) {
333 return Self::from_pkcs1_private_key(&pkcs1_key);
334 }
335
336 Err(LoadError::UnsupportedFormat)
337 }
338
339 pub fn load_encrypted_pem(pem: &str, password: impl AsRef<[u8]>) -> Result<Self, LoadError> {
351 let (label, doc) = pem_rfc7468::decode_vec(pem.as_bytes())?;
352
353 match label {
354 pkcs8::EncryptedPrivateKeyInfo::PEM_LABEL => {
355 let info = pkcs8::EncryptedPrivateKeyInfo::from_der(&doc)?;
356 let decrypted = info.decrypt(password)?;
357 Self::load_der(decrypted.as_bytes()).map_err(|inner| LoadError::InEncrypted {
358 inner: Box::new(inner),
359 })
360 }
361
362 pkcs1::RsaPrivateKey::PEM_LABEL
363 | pkcs8::PrivateKeyInfo::PEM_LABEL
364 | sec1::EcPrivateKey::PEM_LABEL => Err(LoadError::Unencrypted),
365
366 label => Err(LoadError::UnsupportedPemLabel {
367 label: label.to_owned(),
368 }),
369 }
370 }
371
372 pub fn load_pem(pem: &str) -> Result<Self, LoadError> {
383 let (label, doc) = pem_rfc7468::decode_vec(pem.as_bytes())?;
384
385 match label {
386 pkcs1::RsaPrivateKey::PEM_LABEL => {
387 let pkcs1_key = pkcs1::RsaPrivateKey::from_der(&doc)?;
388 Self::from_pkcs1_private_key(&pkcs1_key)
389 }
390
391 pkcs8::PrivateKeyInfo::PEM_LABEL => {
392 let info = pkcs8::PrivateKeyInfo::from_der(&doc)?;
393 Self::from_private_key_info(info)
394 }
395
396 sec1::EcPrivateKey::PEM_LABEL => {
397 let key = sec1::EcPrivateKey::from_der(&doc)?;
398 Self::from_ec_private_key(key)
399 }
400
401 pkcs8::EncryptedPrivateKeyInfo::PEM_LABEL => Err(LoadError::Encrypted),
402
403 label => Err(LoadError::UnsupportedPemLabel {
404 label: label.to_owned(),
405 }),
406 }
407 }
408
409 pub fn verifying_key_for_alg(
416 &self,
417 alg: &JsonWebSignatureAlg,
418 ) -> Result<AsymmetricVerifyingKey, WrongAlgorithmError> {
419 let key = match (self, alg) {
420 (Self::Rsa(key), _) => {
421 let key: rsa::RsaPublicKey = key.to_public_key();
422 match alg {
423 JsonWebSignatureAlg::Rs256 => AsymmetricVerifyingKey::rs256(key),
424 JsonWebSignatureAlg::Rs384 => AsymmetricVerifyingKey::rs384(key),
425 JsonWebSignatureAlg::Rs512 => AsymmetricVerifyingKey::rs512(key),
426 JsonWebSignatureAlg::Ps256 => AsymmetricVerifyingKey::ps256(key),
427 JsonWebSignatureAlg::Ps384 => AsymmetricVerifyingKey::ps384(key),
428 JsonWebSignatureAlg::Ps512 => AsymmetricVerifyingKey::ps512(key),
429 _ => return Err(WrongAlgorithmError),
430 }
431 }
432
433 (Self::EcP256(key), JsonWebSignatureAlg::Es256) => {
434 AsymmetricVerifyingKey::es256(key.public_key())
435 }
436
437 (Self::EcP384(key), JsonWebSignatureAlg::Es384) => {
438 AsymmetricVerifyingKey::es384(key.public_key())
439 }
440
441 (Self::EcK256(key), JsonWebSignatureAlg::Es256K) => {
442 AsymmetricVerifyingKey::es256k(key.public_key())
443 }
444
445 _ => return Err(WrongAlgorithmError),
446 };
447
448 Ok(key)
449 }
450
451 pub fn signing_key_for_alg(
458 &self,
459 alg: &JsonWebSignatureAlg,
460 ) -> Result<AsymmetricSigningKey, WrongAlgorithmError> {
461 let key = match (self, alg) {
462 (Self::Rsa(key), _) => {
463 let key: rsa::RsaPrivateKey = *key.clone();
464 match alg {
465 JsonWebSignatureAlg::Rs256 => AsymmetricSigningKey::rs256(key),
466 JsonWebSignatureAlg::Rs384 => AsymmetricSigningKey::rs384(key),
467 JsonWebSignatureAlg::Rs512 => AsymmetricSigningKey::rs512(key),
468 JsonWebSignatureAlg::Ps256 => AsymmetricSigningKey::ps256(key),
469 JsonWebSignatureAlg::Ps384 => AsymmetricSigningKey::ps384(key),
470 JsonWebSignatureAlg::Ps512 => AsymmetricSigningKey::ps512(key),
471 _ => return Err(WrongAlgorithmError),
472 }
473 }
474
475 (Self::EcP256(key), JsonWebSignatureAlg::Es256) => {
476 AsymmetricSigningKey::es256(*key.clone())
477 }
478
479 (Self::EcP384(key), JsonWebSignatureAlg::Es384) => {
480 AsymmetricSigningKey::es384(*key.clone())
481 }
482
483 (Self::EcK256(key), JsonWebSignatureAlg::Es256K) => {
484 AsymmetricSigningKey::es256k(*key.clone())
485 }
486
487 _ => return Err(WrongAlgorithmError),
488 };
489
490 Ok(key)
491 }
492
493 pub fn generate_rsa<R: RngCore + CryptoRng>(mut rng: R) -> Result<Self, rsa::errors::Error> {
499 let key = rsa::RsaPrivateKey::new(&mut rng, 2048)?;
500 Ok(Self::Rsa(Box::new(key)))
501 }
502
503 pub fn generate_ec_p256<R: RngCore + CryptoRng>(mut rng: R) -> Self {
505 let key = elliptic_curve::SecretKey::random(&mut rng);
506 Self::EcP256(Box::new(key))
507 }
508
509 pub fn generate_ec_p384<R: RngCore + CryptoRng>(mut rng: R) -> Self {
511 let key = elliptic_curve::SecretKey::random(&mut rng);
512 Self::EcP384(Box::new(key))
513 }
514
515 pub fn generate_ec_k256<R: RngCore + CryptoRng>(mut rng: R) -> Self {
517 let key = elliptic_curve::SecretKey::random(&mut rng);
518 Self::EcK256(Box::new(key))
519 }
520}
521
522fn to_sec1_der<C>(key: &elliptic_curve::SecretKey<C>) -> Result<Zeroizing<Vec<u8>>, der::Error>
526where
527 C: elliptic_curve::Curve + elliptic_curve::CurveArithmetic + AssociatedOid,
528 elliptic_curve::PublicKey<C>: elliptic_curve::sec1::ToEncodedPoint<C>,
529 C::FieldBytesSize: elliptic_curve::sec1::ModulusSize,
530{
531 let private_key_bytes = Zeroizing::new(key.to_bytes());
532 let public_key_bytes = key.public_key().to_encoded_point(false);
533 Ok(Zeroizing::new(
534 sec1::EcPrivateKey {
535 private_key: &private_key_bytes,
536 parameters: Some(sec1::EcParameters::NamedCurve(C::OID)),
537 public_key: Some(public_key_bytes.as_bytes()),
538 }
539 .to_der()?,
540 ))
541}
542
543fn to_sec1_pem<C>(
544 key: &elliptic_curve::SecretKey<C>,
545 line_ending: pem_rfc7468::LineEnding,
546) -> Result<Zeroizing<String>, der::Error>
547where
548 C: elliptic_curve::Curve + elliptic_curve::CurveArithmetic + AssociatedOid,
549 elliptic_curve::PublicKey<C>: elliptic_curve::sec1::ToEncodedPoint<C>,
550 C::FieldBytesSize: elliptic_curve::sec1::ModulusSize,
551{
552 let private_key_bytes = Zeroizing::new(key.to_bytes());
553 let public_key_bytes = key.public_key().to_encoded_point(false);
554 Ok(Zeroizing::new(
555 sec1::EcPrivateKey {
556 private_key: &private_key_bytes,
557 parameters: Some(sec1::EcParameters::NamedCurve(C::OID)),
558 public_key: Some(public_key_bytes.as_bytes()),
559 }
560 .to_pem(line_ending)?,
561 ))
562}
563
564impl From<&PrivateKey> for JsonWebKeyPublicParameters {
565 fn from(val: &PrivateKey) -> Self {
566 match val {
567 PrivateKey::Rsa(key) => key.to_public_key().into(),
568 PrivateKey::EcP256(key) => key.public_key().into(),
569 PrivateKey::EcP384(key) => key.public_key().into(),
570 PrivateKey::EcK256(key) => key.public_key().into(),
571 }
572 }
573}
574
575impl ParametersInfo for PrivateKey {
576 fn kty(&self) -> JsonWebKeyType {
577 match self {
578 PrivateKey::Rsa(_) => JsonWebKeyType::Rsa,
579 PrivateKey::EcP256(_) | PrivateKey::EcP384(_) | PrivateKey::EcK256(_) => {
580 JsonWebKeyType::Ec
581 }
582 }
583 }
584
585 fn possible_algs(&self) -> &'static [JsonWebSignatureAlg] {
586 match self {
587 PrivateKey::Rsa(_) => &[
588 JsonWebSignatureAlg::Rs256,
589 JsonWebSignatureAlg::Rs384,
590 JsonWebSignatureAlg::Rs512,
591 JsonWebSignatureAlg::Ps256,
592 JsonWebSignatureAlg::Ps384,
593 JsonWebSignatureAlg::Ps512,
594 ],
595 PrivateKey::EcP256(_) => &[JsonWebSignatureAlg::Es256],
596 PrivateKey::EcP384(_) => &[JsonWebSignatureAlg::Es384],
597 PrivateKey::EcK256(_) => &[JsonWebSignatureAlg::Es256K],
598 }
599 }
600}
601
602#[derive(Clone, Default)]
606pub struct Keystore {
607 keys: Arc<JsonWebKeySet<PrivateKey>>,
608}
609
610impl Keystore {
611 #[must_use]
613 pub fn new(keys: JsonWebKeySet<PrivateKey>) -> Self {
614 let keys = Arc::new(keys);
615 Self { keys }
616 }
617
618 #[must_use]
620 pub fn public_jwks(&self) -> PublicJsonWebKeySet {
621 self.keys
622 .iter()
623 .map(|key| {
624 key.cloned_map(|params: &PrivateKey| JsonWebKeyPublicParameters::from(params))
625 })
626 .collect()
627 }
628}
629
630impl Deref for Keystore {
631 type Target = JsonWebKeySet<PrivateKey>;
632
633 fn deref(&self) -> &Self::Target {
634 &self.keys
635 }
636}