1#[cfg(feature = "alloc")]
4pub(crate) mod other_prime_info;
5
6use crate::{Error, Result, RsaPublicKey, Version};
7use core::fmt;
8use der::{asn1::UIntRef, Decode, DecodeValue, Encode, Header, Reader, Sequence, Tag};
9
10#[cfg(feature = "alloc")]
11use {self::other_prime_info::OtherPrimeInfo, alloc::vec::Vec, der::SecretDocument};
12
13#[cfg(feature = "pem")]
14use der::pem::PemLabel;
15
16#[derive(Clone)]
40pub struct RsaPrivateKey<'a> {
41 pub modulus: UIntRef<'a>,
43
44 pub public_exponent: UIntRef<'a>,
46
47 pub private_exponent: UIntRef<'a>,
49
50 pub prime1: UIntRef<'a>,
52
53 pub prime2: UIntRef<'a>,
55
56 pub exponent1: UIntRef<'a>,
58
59 pub exponent2: UIntRef<'a>,
61
62 pub coefficient: UIntRef<'a>,
64
65 pub other_prime_infos: Option<OtherPrimeInfos<'a>>,
68}
69
70impl<'a> RsaPrivateKey<'a> {
71 pub fn public_key(&self) -> RsaPublicKey<'a> {
73 RsaPublicKey {
74 modulus: self.modulus,
75 public_exponent: self.public_exponent,
76 }
77 }
78
79 pub fn version(&self) -> Version {
84 if self.other_prime_infos.is_some() {
85 Version::Multi
86 } else {
87 Version::TwoPrime
88 }
89 }
90}
91
92impl<'a> DecodeValue<'a> for RsaPrivateKey<'a> {
93 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
94 reader.read_nested(header.length, |reader| {
95 let version = Version::decode(reader)?;
96
97 let result = Self {
98 modulus: reader.decode()?,
99 public_exponent: reader.decode()?,
100 private_exponent: reader.decode()?,
101 prime1: reader.decode()?,
102 prime2: reader.decode()?,
103 exponent1: reader.decode()?,
104 exponent2: reader.decode()?,
105 coefficient: reader.decode()?,
106 other_prime_infos: reader.decode()?,
107 };
108
109 if version.is_multi() != result.other_prime_infos.is_some() {
111 return Err(reader.error(der::ErrorKind::Value { tag: Tag::Integer }));
112 }
113
114 Ok(result)
115 })
116 }
117}
118
119impl<'a> Sequence<'a> for RsaPrivateKey<'a> {
120 fn fields<F, T>(&self, f: F) -> der::Result<T>
121 where
122 F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
123 {
124 f(&[
125 &self.version(),
126 &self.modulus,
127 &self.public_exponent,
128 &self.private_exponent,
129 &self.prime1,
130 &self.prime2,
131 &self.exponent1,
132 &self.exponent2,
133 &self.coefficient,
134 #[cfg(feature = "alloc")]
135 &self.other_prime_infos,
136 ])
137 }
138}
139
140impl<'a> From<RsaPrivateKey<'a>> for RsaPublicKey<'a> {
141 fn from(private_key: RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
142 private_key.public_key()
143 }
144}
145
146impl<'a> From<&RsaPrivateKey<'a>> for RsaPublicKey<'a> {
147 fn from(private_key: &RsaPrivateKey<'a>) -> RsaPublicKey<'a> {
148 private_key.public_key()
149 }
150}
151
152impl<'a> TryFrom<&'a [u8]> for RsaPrivateKey<'a> {
153 type Error = Error;
154
155 fn try_from(bytes: &'a [u8]) -> Result<Self> {
156 Ok(Self::from_der(bytes)?)
157 }
158}
159
160impl fmt::Debug for RsaPrivateKey<'_> {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 f.debug_struct("RsaPrivateKey")
163 .field("version", &self.version())
164 .field("modulus", &self.modulus)
165 .field("public_exponent", &self.public_exponent)
166 .finish_non_exhaustive()
167 }
168}
169
170#[cfg(feature = "alloc")]
171#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
172impl TryFrom<RsaPrivateKey<'_>> for SecretDocument {
173 type Error = Error;
174
175 fn try_from(private_key: RsaPrivateKey<'_>) -> Result<SecretDocument> {
176 SecretDocument::try_from(&private_key)
177 }
178}
179
180#[cfg(feature = "alloc")]
181#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
182impl TryFrom<&RsaPrivateKey<'_>> for SecretDocument {
183 type Error = Error;
184
185 fn try_from(private_key: &RsaPrivateKey<'_>) -> Result<SecretDocument> {
186 Ok(Self::encode_msg(private_key)?)
187 }
188}
189
190#[cfg(feature = "pem")]
191#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
192impl PemLabel for RsaPrivateKey<'_> {
193 const PEM_LABEL: &'static str = "RSA PRIVATE KEY";
194}
195
196#[cfg(not(feature = "alloc"))]
198#[derive(Clone)]
199#[non_exhaustive]
200pub struct OtherPrimeInfos<'a> {
201 _lifetime: core::marker::PhantomData<&'a ()>,
202}
203
204#[cfg(not(feature = "alloc"))]
205impl<'a> Decode<'a> for OtherPrimeInfos<'a> {
206 fn decode<R: Reader<'a>>(reader: &mut R) -> der::Result<Self> {
207 Err(reader.error(der::ErrorKind::Value { tag: Tag::Integer }))
210 }
211}
212
213#[cfg(not(feature = "alloc"))]
214impl<'a> der::FixedTag for OtherPrimeInfos<'a> {
215 const TAG: Tag = Tag::Sequence;
216}
217
218#[cfg(feature = "alloc")]
220pub type OtherPrimeInfos<'a> = Vec<OtherPrimeInfo<'a>>;