rsa/
encoding.rs

1//! PKCS#1 and PKCS#8 encoding support.
2//!
3//! Note: PKCS#1 support is achieved through a blanket impl of the
4//! `pkcs1` crate's traits for types which impl the `pkcs8` crate's traits.
5
6use crate::{key::PublicKeyParts, BigUint, RsaPrivateKey, RsaPublicKey};
7use core::convert::{TryFrom, TryInto};
8use pkcs1::der::Encode;
9use pkcs8::{
10    DecodePrivateKey, DecodePublicKey, Document, EncodePrivateKey, EncodePublicKey, SecretDocument,
11};
12use zeroize::Zeroizing;
13
14/// Verify that the `AlgorithmIdentifier` for a key is correct.
15fn verify_algorithm_id(algorithm: &pkcs8::AlgorithmIdentifier) -> pkcs8::spki::Result<()> {
16    algorithm.assert_algorithm_oid(pkcs1::ALGORITHM_OID)?;
17
18    if algorithm.parameters_any()? != pkcs8::der::asn1::Null.into() {
19        return Err(pkcs8::spki::Error::KeyMalformed);
20    }
21
22    Ok(())
23}
24
25impl TryFrom<pkcs8::PrivateKeyInfo<'_>> for RsaPrivateKey {
26    type Error = pkcs8::Error;
27
28    fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result<Self> {
29        verify_algorithm_id(&private_key_info.algorithm)?;
30
31        let pkcs1_key = pkcs1::RsaPrivateKey::try_from(private_key_info.private_key)?;
32
33        // Multi-prime RSA keys not currently supported
34        if pkcs1_key.version() != pkcs1::Version::TwoPrime {
35            return Err(pkcs1::Error::Version.into());
36        }
37
38        let n = BigUint::from_bytes_be(pkcs1_key.modulus.as_bytes());
39        let e = BigUint::from_bytes_be(pkcs1_key.public_exponent.as_bytes());
40        let d = BigUint::from_bytes_be(pkcs1_key.private_exponent.as_bytes());
41        let prime1 = BigUint::from_bytes_be(pkcs1_key.prime1.as_bytes());
42        let prime2 = BigUint::from_bytes_be(pkcs1_key.prime2.as_bytes());
43        let primes = vec![prime1, prime2];
44        RsaPrivateKey::from_components(n, e, d, primes).map_err(|_| pkcs8::Error::KeyMalformed)
45    }
46}
47
48impl DecodePrivateKey for RsaPrivateKey {}
49
50impl TryFrom<pkcs8::SubjectPublicKeyInfo<'_>> for RsaPublicKey {
51    type Error = pkcs8::spki::Error;
52
53    fn try_from(spki: pkcs8::SubjectPublicKeyInfo<'_>) -> pkcs8::spki::Result<Self> {
54        verify_algorithm_id(&spki.algorithm)?;
55
56        let pkcs1_key = pkcs1::RsaPublicKey::try_from(spki.subject_public_key)?;
57        let n = BigUint::from_bytes_be(pkcs1_key.modulus.as_bytes());
58        let e = BigUint::from_bytes_be(pkcs1_key.public_exponent.as_bytes());
59        RsaPublicKey::new(n, e).map_err(|_| pkcs8::spki::Error::KeyMalformed)
60    }
61}
62
63impl DecodePublicKey for RsaPublicKey {}
64
65impl EncodePrivateKey for RsaPrivateKey {
66    fn to_pkcs8_der(&self) -> pkcs8::Result<SecretDocument> {
67        // Check if the key is multi prime
68        if self.primes.len() > 2 {
69            return Err(pkcs1::Error::Version.into());
70        }
71
72        let modulus = self.n().to_bytes_be();
73        let public_exponent = self.e().to_bytes_be();
74        let private_exponent = Zeroizing::new(self.d().to_bytes_be());
75        let prime1 = Zeroizing::new(self.primes[0].to_bytes_be());
76        let prime2 = Zeroizing::new(self.primes[1].to_bytes_be());
77        let exponent1 = Zeroizing::new((self.d() % (&self.primes[0] - 1u8)).to_bytes_be());
78        let exponent2 = Zeroizing::new((self.d() % (&self.primes[1] - 1u8)).to_bytes_be());
79        let coefficient = Zeroizing::new(
80            self.crt_coefficient()
81                .ok_or(pkcs1::Error::Crypto)?
82                .to_bytes_be(),
83        );
84
85        let private_key = pkcs1::RsaPrivateKey {
86            modulus: pkcs1::UIntRef::new(&modulus)?,
87            public_exponent: pkcs1::UIntRef::new(&public_exponent)?,
88            private_exponent: pkcs1::UIntRef::new(&private_exponent)?,
89            prime1: pkcs1::UIntRef::new(&prime1)?,
90            prime2: pkcs1::UIntRef::new(&prime2)?,
91            exponent1: pkcs1::UIntRef::new(&exponent1)?,
92            exponent2: pkcs1::UIntRef::new(&exponent2)?,
93            coefficient: pkcs1::UIntRef::new(&coefficient)?,
94            other_prime_infos: None,
95        }
96        .to_vec()?;
97
98        pkcs8::PrivateKeyInfo::new(pkcs1::ALGORITHM_ID, private_key.as_ref()).try_into()
99    }
100}
101
102impl EncodePublicKey for RsaPublicKey {
103    fn to_public_key_der(&self) -> pkcs8::spki::Result<Document> {
104        let modulus = self.n().to_bytes_be();
105        let public_exponent = self.e().to_bytes_be();
106
107        let subject_public_key = pkcs1::RsaPublicKey {
108            modulus: pkcs1::UIntRef::new(&modulus)?,
109            public_exponent: pkcs1::UIntRef::new(&public_exponent)?,
110        }
111        .to_vec()?;
112
113        pkcs8::SubjectPublicKeyInfo {
114            algorithm: pkcs1::ALGORITHM_ID,
115            subject_public_key: subject_public_key.as_ref(),
116        }
117        .try_into()
118    }
119}