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