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::{
7    traits::{PrivateKeyParts, PublicKeyParts},
8    BigUint, RsaPrivateKey, RsaPublicKey,
9};
10use core::convert::{TryFrom, TryInto};
11use pkcs8::{der::Encode, Document, EncodePrivateKey, EncodePublicKey, SecretDocument};
12use zeroize::Zeroizing;
13
14/// Verify that the `AlgorithmIdentifier` for a key is correct.
15fn verify_algorithm_id(algorithm: &pkcs8::AlgorithmIdentifierRef) -> 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 TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for RsaPublicKey {
49    type Error = pkcs8::spki::Error;
50
51    fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result<Self> {
52        verify_algorithm_id(&spki.algorithm)?;
53
54        let pkcs1_key = pkcs1::RsaPublicKey::try_from(
55            spki.subject_public_key
56                .as_bytes()
57                .ok_or(pkcs8::spki::Error::KeyMalformed)?,
58        )?;
59        let n = BigUint::from_bytes_be(pkcs1_key.modulus.as_bytes());
60        let e = BigUint::from_bytes_be(pkcs1_key.public_exponent.as_bytes());
61        RsaPublicKey::new(n, e).map_err(|_| pkcs8::spki::Error::KeyMalformed)
62    }
63}
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_der()?;
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_der()?;
112
113        pkcs8::SubjectPublicKeyInfoRef {
114            algorithm: pkcs1::ALGORITHM_ID,
115            subject_public_key: pkcs8::der::asn1::BitStringRef::new(
116                0,
117                subject_public_key.as_ref(),
118            )?,
119        }
120        .try_into()
121    }
122}