Skip to main content

pkcs1/
private_key.rs

1//! PKCS#1 RSA Private Keys.
2
3#[cfg(feature = "alloc")]
4pub(crate) mod other_prime_info;
5
6use crate::{Error, Result, RsaPublicKey, Version};
7use core::fmt;
8use der::{
9    Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Tag, Writer,
10    asn1::{OctetStringRef, UintRef},
11};
12
13#[cfg(feature = "alloc")]
14use {self::other_prime_info::OtherPrimeInfo, alloc::vec::Vec, der::SecretDocument};
15
16#[cfg(feature = "pem")]
17use der::pem::PemLabel;
18
19/// PKCS#1 RSA Private Keys as defined in [RFC 8017 Appendix 1.2].
20///
21/// ASN.1 structure containing a serialized RSA private key:
22///
23/// ```text
24/// RSAPrivateKey ::= SEQUENCE {
25///     version           Version,
26///     modulus           INTEGER,  -- n
27///     publicExponent    INTEGER,  -- e
28///     privateExponent   INTEGER,  -- d
29///     prime1            INTEGER,  -- p
30///     prime2            INTEGER,  -- q
31///     exponent1         INTEGER,  -- d mod (p-1)
32///     exponent2         INTEGER,  -- d mod (q-1)
33///     coefficient       INTEGER,  -- (inverse of q) mod p
34///     otherPrimeInfos   OtherPrimeInfos OPTIONAL
35/// }
36/// ```
37///
38/// Note: the `version` field is selected automatically based on the absence or
39/// presence of the `other_prime_infos` field.
40///
41/// [RFC 8017 Appendix 1.2]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.2
42#[derive(Clone)]
43pub struct RsaPrivateKey<'a> {
44    /// `n`: RSA modulus.
45    pub modulus: UintRef<'a>,
46
47    /// `e`: RSA public exponent.
48    pub public_exponent: UintRef<'a>,
49
50    /// `d`: RSA private exponent.
51    pub private_exponent: UintRef<'a>,
52
53    /// `p`: first prime factor of `n`.
54    pub prime1: UintRef<'a>,
55
56    /// `q`: Second prime factor of `n`.
57    pub prime2: UintRef<'a>,
58
59    /// First exponent: `d mod (p-1)`.
60    pub exponent1: UintRef<'a>,
61
62    /// Second exponent: `d mod (q-1)`.
63    pub exponent2: UintRef<'a>,
64
65    /// CRT coefficient: `(inverse of q) mod p`.
66    pub coefficient: UintRef<'a>,
67
68    /// Additional primes `r_3`, ..., `r_u`, in order, if this is a multi-prime
69    /// RSA key (i.e. `version` is `multi`).
70    pub other_prime_infos: Option<OtherPrimeInfos<'a>>,
71}
72
73impl<'a> RsaPrivateKey<'a> {
74    /// Get the public key that corresponds to this [`RsaPrivateKey`].
75    pub fn public_key(&self) -> RsaPublicKey<'a> {
76        RsaPublicKey {
77            modulus: self.modulus,
78            public_exponent: self.public_exponent,
79        }
80    }
81
82    /// Get the [`Version`] for this key.
83    ///
84    /// Determined by the presence or absence of the
85    /// [`RsaPrivateKey::other_prime_infos`] field.
86    pub fn version(&self) -> Version {
87        if self.other_prime_infos.is_some() {
88            Version::Multi
89        } else {
90            Version::TwoPrime
91        }
92    }
93}
94
95impl<'a> DecodeValue<'a> for RsaPrivateKey<'a> {
96    type Error = der::Error;
97
98    fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
99        let version = Version::decode(reader)?;
100
101        let result = Self {
102            modulus: reader.decode()?,
103            public_exponent: reader.decode()?,
104            private_exponent: reader.decode()?,
105            prime1: reader.decode()?,
106            prime2: reader.decode()?,
107            exponent1: reader.decode()?,
108            exponent2: reader.decode()?,
109            coefficient: reader.decode()?,
110            other_prime_infos: reader.decode()?,
111        };
112
113        // Ensure version is set correctly for two-prime vs multi-prime key.
114        if version.is_multi() != result.other_prime_infos.is_some() {
115            return Err(reader.error(der::ErrorKind::Value { tag: Tag::Integer }));
116        }
117
118        Ok(result)
119    }
120}
121
122impl EncodeValue for RsaPrivateKey<'_> {
123    fn value_len(&self) -> der::Result<Length> {
124        self.version().encoded_len()?
125            + self.modulus.encoded_len()?
126            + self.public_exponent.encoded_len()?
127            + self.private_exponent.encoded_len()?
128            + self.prime1.encoded_len()?
129            + self.prime2.encoded_len()?
130            + self.exponent1.encoded_len()?
131            + self.exponent2.encoded_len()?
132            + self.coefficient.encoded_len()?
133            + self.other_prime_infos.encoded_len()?
134    }
135
136    fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
137        self.version().encode(writer)?;
138        self.modulus.encode(writer)?;
139        self.public_exponent.encode(writer)?;
140        self.private_exponent.encode(writer)?;
141        self.prime1.encode(writer)?;
142        self.prime2.encode(writer)?;
143        self.exponent1.encode(writer)?;
144        self.exponent2.encode(writer)?;
145        self.coefficient.encode(writer)?;
146        self.other_prime_infos.encode(writer)?;
147        Ok(())
148    }
149}
150
151impl<'a> Sequence<'a> for RsaPrivateKey<'a> {}
152
153impl<'a> From<RsaPrivateKey<'a>> for RsaPublicKey<'a> {
154    fn from(private_key: RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
155        private_key.public_key()
156    }
157}
158
159impl<'a> From<&RsaPrivateKey<'a>> for RsaPublicKey<'a> {
160    fn from(private_key: &RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
161        private_key.public_key()
162    }
163}
164
165impl<'a> TryFrom<&'a [u8]> for RsaPrivateKey<'a> {
166    type Error = Error;
167
168    fn try_from(bytes: &'a [u8]) -> Result<Self> {
169        Ok(Self::from_der(bytes)?)
170    }
171}
172
173impl<'a> TryFrom<&'a OctetStringRef> for RsaPrivateKey<'a> {
174    type Error = Error;
175
176    fn try_from(bytes: &'a OctetStringRef) -> Result<Self> {
177        Ok(Self::from_der(bytes.as_bytes())?)
178    }
179}
180
181impl fmt::Debug for RsaPrivateKey<'_> {
182    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183        f.debug_struct("RsaPrivateKey")
184            .field("version", &self.version())
185            .field("modulus", &self.modulus)
186            .field("public_exponent", &self.public_exponent)
187            .finish_non_exhaustive()
188    }
189}
190
191#[cfg(feature = "alloc")]
192impl TryFrom<RsaPrivateKey<'_>> for SecretDocument {
193    type Error = Error;
194
195    fn try_from(private_key: RsaPrivateKey<'_>) -> Result<SecretDocument> {
196        SecretDocument::try_from(&private_key)
197    }
198}
199
200#[cfg(feature = "alloc")]
201impl TryFrom<&RsaPrivateKey<'_>> for SecretDocument {
202    type Error = Error;
203
204    fn try_from(private_key: &RsaPrivateKey<'_>) -> Result<SecretDocument> {
205        Ok(Self::encode_msg(private_key)?)
206    }
207}
208
209#[cfg(feature = "pem")]
210impl PemLabel for RsaPrivateKey<'_> {
211    const PEM_LABEL: &'static str = "RSA PRIVATE KEY";
212}
213
214/// Placeholder struct for `OtherPrimeInfos` in the no-`alloc` case.
215///
216/// This type is unconstructable by design, but supports the same traits.
217#[cfg(not(feature = "alloc"))]
218#[derive(Clone)]
219#[non_exhaustive]
220pub struct OtherPrimeInfos<'a> {
221    _lifetime: core::marker::PhantomData<&'a ()>,
222}
223
224#[cfg(not(feature = "alloc"))]
225impl<'a> DecodeValue<'a> for OtherPrimeInfos<'a> {
226    type Error = der::Error;
227
228    fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
229        // Placeholder decoder that always returns an error.
230        // Uses `Tag::Integer` to signal an unsupported version.
231        Err(reader.error(der::ErrorKind::Value { tag: Tag::Integer }))
232    }
233}
234
235#[cfg(not(feature = "alloc"))]
236impl EncodeValue for OtherPrimeInfos<'_> {
237    fn value_len(&self) -> der::Result<Length> {
238        // Placeholder decoder that always returns an error.
239        // Uses `Tag::Integer` to signal an unsupported version.
240        Err(der::ErrorKind::Value { tag: Tag::Integer }.into())
241    }
242
243    fn encode_value(&self, _writer: &mut impl Writer) -> der::Result<()> {
244        // Placeholder decoder that always returns an error.
245        // Uses `Tag::Integer` to signal an unsupported version.
246        Err(der::ErrorKind::Value { tag: Tag::Integer }.into())
247    }
248}
249
250#[cfg(not(feature = "alloc"))]
251impl der::FixedTag for OtherPrimeInfos<'_> {
252    const TAG: Tag = Tag::Sequence;
253}
254
255/// Additional RSA prime info in a multi-prime RSA key.
256#[cfg(feature = "alloc")]
257pub type OtherPrimeInfos<'a> = Vec<OtherPrimeInfo<'a>>;