1#[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
22pub type RsaPrivateKeyRef<'a> = RsaPrivateKey<UintRef<'a>>;
24
25#[cfg(feature = "alloc")]
27pub type RsaPrivateKeyOwned = RsaPrivateKey<Uint>;
28
29#[derive(Clone)]
55pub struct RsaPrivateKey<U> {
56 pub modulus: U,
58
59 pub public_exponent: U,
61
62 pub private_exponent: U,
64
65 pub prime1: U,
67
68 pub prime2: U,
70
71 pub exponent1: U,
73
74 pub exponent2: U,
76
77 pub coefficient: U,
79
80 pub other_prime_infos: Option<OtherPrimeInfos<U>>,
83}
84
85impl<U> RsaPrivateKey<U>
86where
87 U: AsUintRef,
88{
89 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 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 if version.is_multi() != result.other_prime_infos.is_some() {
135 return Err(reader.error(der::ErrorKind::Value { tag: Tag::Integer }));
136 }
137
138 #[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#[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 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 Err(der::ErrorKind::Value { tag: Tag::Integer }.into())
287 }
288
289 fn encode_value(&self, _writer: &mut impl Writer) -> der::Result<()> {
290 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#[cfg(feature = "alloc")]
303pub type OtherPrimeInfos<U> = Vec<OtherPrimeInfo<U>>;