1pub use rsa::{errors::Error as RsaError, RsaPrivateKey, RsaPublicKey};
4
5use rand_core::{CryptoRng, RngCore};
6use rsa::{
7 traits::{PrivateKeyParts, PublicKeyParts},
8 BigUint, Pkcs1v15Sign, Pss,
9};
10use sha2::{Digest, Sha256, Sha384, Sha512};
11
12use core::{fmt, str::FromStr};
13
14use crate::{
15 alg::{SecretBytes, StrongKey, WeakKeyError},
16 alloc::{Box, Cow, String, ToOwned, Vec},
17 jwk::{JsonWebKey, JwkError, KeyType, RsaPrimeFactor, RsaPrivateParts},
18 Algorithm, AlgorithmSignature,
19};
20
21#[derive(Debug)]
23#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
24pub struct RsaSignature(Vec<u8>);
25
26impl AlgorithmSignature for RsaSignature {
27 fn try_from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
28 Ok(RsaSignature(bytes.to_vec()))
29 }
30
31 fn as_bytes(&self) -> Cow<'_, [u8]> {
32 Cow::Borrowed(&self.0)
33 }
34}
35
36#[derive(Debug, Copy, Clone, Eq, PartialEq)]
38enum HashAlg {
39 Sha256,
40 Sha384,
41 Sha512,
42}
43
44impl HashAlg {
45 fn digest(self, message: &[u8]) -> Box<[u8]> {
46 match self {
47 Self::Sha256 => {
48 let digest: [u8; 32] = *(Sha256::digest(message).as_ref());
49 Box::new(digest)
50 }
51 Self::Sha384 => {
52 let mut digest = [0_u8; 48];
53 digest.copy_from_slice(Sha384::digest(message).as_ref());
54 Box::new(digest)
55 }
56 Self::Sha512 => {
57 let mut digest = [0_u8; 64];
58 digest.copy_from_slice(Sha512::digest(message).as_ref());
59 Box::new(digest)
60 }
61 }
62 }
63}
64
65#[derive(Debug, Copy, Clone, Eq, PartialEq)]
67enum Padding {
68 Pkcs1v15,
69 Pss,
70}
71
72#[derive(Debug)]
73enum PaddingScheme {
74 Pkcs1v15(Pkcs1v15Sign),
75 Pss(Pss),
76}
77
78#[derive(Debug, Copy, Clone, Eq, PartialEq)]
80#[non_exhaustive]
81#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
82pub enum ModulusBits {
83 TwoKibibytes,
85 ThreeKibibytes,
87 FourKibibytes,
89}
90
91impl ModulusBits {
92 pub fn bits(self) -> usize {
94 match self {
95 Self::TwoKibibytes => 2_048,
96 Self::ThreeKibibytes => 3_072,
97 Self::FourKibibytes => 4_096,
98 }
99 }
100
101 fn is_valid_bits(bits: usize) -> bool {
102 matches!(bits, 2_048 | 3_072 | 4_096)
103 }
104}
105
106impl TryFrom<usize> for ModulusBits {
107 type Error = ModulusBitsError;
108
109 fn try_from(value: usize) -> Result<Self, Self::Error> {
110 match value {
111 2_048 => Ok(Self::TwoKibibytes),
112 3_072 => Ok(Self::ThreeKibibytes),
113 4_096 => Ok(Self::FourKibibytes),
114 _ => Err(ModulusBitsError(())),
115 }
116 }
117}
118
119#[derive(Debug)]
121#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
122pub struct ModulusBitsError(());
123
124impl fmt::Display for ModulusBitsError {
125 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
126 formatter.write_str(
127 "Unsupported bit length of RSA modulus; only lengths 2048, 3072 and 4096 \
128 are supported.",
129 )
130 }
131}
132
133#[cfg(feature = "std")]
134impl std::error::Error for ModulusBitsError {}
135
136#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
160pub struct Rsa {
161 hash_alg: HashAlg,
162 padding_alg: Padding,
163}
164
165impl Algorithm for Rsa {
166 type SigningKey = RsaPrivateKey;
167 type VerifyingKey = RsaPublicKey;
168 type Signature = RsaSignature;
169
170 fn name(&self) -> Cow<'static, str> {
171 Cow::Borrowed(self.alg_name())
172 }
173
174 fn sign(&self, signing_key: &Self::SigningKey, message: &[u8]) -> Self::Signature {
175 let digest = self.hash_alg.digest(message);
176 let signing_result = match self.padding_scheme() {
177 PaddingScheme::Pkcs1v15(padding) => {
178 signing_key.sign_with_rng(&mut rand_core::OsRng, padding, &digest)
179 }
180 PaddingScheme::Pss(padding) => {
181 signing_key.sign_with_rng(&mut rand_core::OsRng, padding, &digest)
182 }
183 };
184 RsaSignature(signing_result.expect("Unexpected RSA signature failure"))
185 }
186
187 fn verify_signature(
188 &self,
189 signature: &Self::Signature,
190 verifying_key: &Self::VerifyingKey,
191 message: &[u8],
192 ) -> bool {
193 let digest = self.hash_alg.digest(message);
194 let verify_result = match self.padding_scheme() {
195 PaddingScheme::Pkcs1v15(padding) => {
196 verifying_key.verify(padding, &digest, &signature.0)
197 }
198 PaddingScheme::Pss(padding) => verifying_key.verify(padding, &digest, &signature.0),
199 };
200 verify_result.is_ok()
201 }
202}
203
204impl Rsa {
205 const fn new(hash_alg: HashAlg, padding_alg: Padding) -> Self {
206 Rsa {
207 hash_alg,
208 padding_alg,
209 }
210 }
211
212 pub const fn rs256() -> Rsa {
214 Rsa::new(HashAlg::Sha256, Padding::Pkcs1v15)
215 }
216
217 pub const fn rs384() -> Rsa {
219 Rsa::new(HashAlg::Sha384, Padding::Pkcs1v15)
220 }
221
222 pub const fn rs512() -> Rsa {
224 Rsa::new(HashAlg::Sha512, Padding::Pkcs1v15)
225 }
226
227 pub const fn ps256() -> Rsa {
229 Rsa::new(HashAlg::Sha256, Padding::Pss)
230 }
231
232 pub const fn ps384() -> Rsa {
234 Rsa::new(HashAlg::Sha384, Padding::Pss)
235 }
236
237 pub const fn ps512() -> Rsa {
239 Rsa::new(HashAlg::Sha512, Padding::Pss)
240 }
241
242 pub fn with_name(name: &str) -> Self {
249 name.parse().unwrap()
250 }
251
252 fn padding_scheme(self) -> PaddingScheme {
253 match self.padding_alg {
254 Padding::Pkcs1v15 => PaddingScheme::Pkcs1v15(match self.hash_alg {
255 HashAlg::Sha256 => Pkcs1v15Sign::new::<Sha256>(),
256 HashAlg::Sha384 => Pkcs1v15Sign::new::<Sha384>(),
257 HashAlg::Sha512 => Pkcs1v15Sign::new::<Sha512>(),
258 }),
259 Padding::Pss => {
260 PaddingScheme::Pss(match self.hash_alg {
263 HashAlg::Sha256 => Pss::new_with_salt::<Sha256>(Sha256::output_size()),
264 HashAlg::Sha384 => Pss::new_with_salt::<Sha384>(Sha384::output_size()),
265 HashAlg::Sha512 => Pss::new_with_salt::<Sha512>(Sha512::output_size()),
266 })
267 }
268 }
269 }
270
271 fn alg_name(self) -> &'static str {
272 match (self.padding_alg, self.hash_alg) {
273 (Padding::Pkcs1v15, HashAlg::Sha256) => "RS256",
274 (Padding::Pkcs1v15, HashAlg::Sha384) => "RS384",
275 (Padding::Pkcs1v15, HashAlg::Sha512) => "RS512",
276 (Padding::Pss, HashAlg::Sha256) => "PS256",
277 (Padding::Pss, HashAlg::Sha384) => "PS384",
278 (Padding::Pss, HashAlg::Sha512) => "PS512",
279 }
280 }
281
282 pub fn generate<R: CryptoRng + RngCore>(
284 rng: &mut R,
285 modulus_bits: ModulusBits,
286 ) -> rsa::errors::Result<(StrongKey<RsaPrivateKey>, StrongKey<RsaPublicKey>)> {
287 let signing_key = RsaPrivateKey::new(rng, modulus_bits.bits())?;
288 let verifying_key = signing_key.to_public_key();
289 Ok((StrongKey(signing_key), StrongKey(verifying_key)))
290 }
291}
292
293impl FromStr for Rsa {
294 type Err = RsaParseError;
295
296 fn from_str(s: &str) -> Result<Self, Self::Err> {
297 Ok(match s {
298 "RS256" => Self::rs256(),
299 "RS384" => Self::rs384(),
300 "RS512" => Self::rs512(),
301 "PS256" => Self::ps256(),
302 "PS384" => Self::ps384(),
303 "PS512" => Self::ps512(),
304 _ => return Err(RsaParseError(s.to_owned())),
305 })
306 }
307}
308
309#[derive(Debug)]
311#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
312pub struct RsaParseError(String);
313
314impl fmt::Display for RsaParseError {
315 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
316 write!(formatter, "Invalid RSA algorithm name: {}", self.0)
317 }
318}
319
320#[cfg(feature = "std")]
321impl std::error::Error for RsaParseError {}
322
323impl StrongKey<RsaPrivateKey> {
324 pub fn to_public_key(&self) -> StrongKey<RsaPublicKey> {
326 StrongKey(self.0.to_public_key())
327 }
328}
329
330impl TryFrom<RsaPrivateKey> for StrongKey<RsaPrivateKey> {
331 type Error = WeakKeyError<RsaPrivateKey>;
332
333 fn try_from(key: RsaPrivateKey) -> Result<Self, Self::Error> {
334 if ModulusBits::is_valid_bits(key.n().bits()) {
335 Ok(StrongKey(key))
336 } else {
337 Err(WeakKeyError(key))
338 }
339 }
340}
341
342impl TryFrom<RsaPublicKey> for StrongKey<RsaPublicKey> {
343 type Error = WeakKeyError<RsaPublicKey>;
344
345 fn try_from(key: RsaPublicKey) -> Result<Self, Self::Error> {
346 if ModulusBits::is_valid_bits(key.n().bits()) {
347 Ok(StrongKey(key))
348 } else {
349 Err(WeakKeyError(key))
350 }
351 }
352}
353
354impl<'a> From<&'a RsaPublicKey> for JsonWebKey<'a> {
355 fn from(key: &'a RsaPublicKey) -> JsonWebKey<'a> {
356 JsonWebKey::Rsa {
357 modulus: Cow::Owned(key.n().to_bytes_be()),
358 public_exponent: Cow::Owned(key.e().to_bytes_be()),
359 private_parts: None,
360 }
361 }
362}
363
364impl TryFrom<&JsonWebKey<'_>> for RsaPublicKey {
365 type Error = JwkError;
366
367 fn try_from(jwk: &JsonWebKey<'_>) -> Result<Self, Self::Error> {
368 let JsonWebKey::Rsa {
369 modulus,
370 public_exponent,
371 ..
372 } = jwk
373 else {
374 return Err(JwkError::key_type(jwk, KeyType::Rsa));
375 };
376
377 let e = BigUint::from_bytes_be(public_exponent);
378 let n = BigUint::from_bytes_be(modulus);
379 Self::new(n, e).map_err(|err| JwkError::custom(anyhow::anyhow!(err)))
380 }
381}
382
383impl<'a> From<&'a RsaPrivateKey> for JsonWebKey<'a> {
389 fn from(key: &'a RsaPrivateKey) -> JsonWebKey<'a> {
390 const MSG: &str = "RsaPrivateKey must have at least 2 prime factors";
391
392 let p = key.primes().get(0).expect(MSG);
393 let q = key.primes().get(1).expect(MSG);
394
395 let private_parts = RsaPrivateParts {
396 private_exponent: SecretBytes::owned(key.d().to_bytes_be()),
397 prime_factor_p: SecretBytes::owned(p.to_bytes_be()),
398 prime_factor_q: SecretBytes::owned(q.to_bytes_be()),
399 p_crt_exponent: None,
400 q_crt_exponent: None,
401 q_crt_coefficient: None,
402 other_prime_factors: key.primes()[2..]
403 .iter()
404 .map(|factor| RsaPrimeFactor {
405 factor: SecretBytes::owned(factor.to_bytes_be()),
406 crt_exponent: None,
407 crt_coefficient: None,
408 })
409 .collect(),
410 };
411
412 JsonWebKey::Rsa {
413 modulus: Cow::Owned(key.n().to_bytes_be()),
414 public_exponent: Cow::Owned(key.e().to_bytes_be()),
415 private_parts: Some(private_parts),
416 }
417 }
418}
419
420impl TryFrom<&JsonWebKey<'_>> for RsaPrivateKey {
425 type Error = JwkError;
426
427 fn try_from(jwk: &JsonWebKey<'_>) -> Result<Self, Self::Error> {
428 let JsonWebKey::Rsa {
429 modulus,
430 public_exponent,
431 private_parts,
432 } = jwk
433 else {
434 return Err(JwkError::key_type(jwk, KeyType::Rsa));
435 };
436
437 let RsaPrivateParts {
438 private_exponent: d,
439 prime_factor_p,
440 prime_factor_q,
441 other_prime_factors,
442 ..
443 } = private_parts
444 .as_ref()
445 .ok_or_else(|| JwkError::NoField("d".into()))?;
446
447 let e = BigUint::from_bytes_be(public_exponent);
448 let n = BigUint::from_bytes_be(modulus);
449 let d = BigUint::from_bytes_be(d);
450
451 let mut factors = Vec::with_capacity(2 + other_prime_factors.len());
452 factors.push(BigUint::from_bytes_be(prime_factor_p));
453 factors.push(BigUint::from_bytes_be(prime_factor_q));
454 factors.extend(
455 other_prime_factors
456 .iter()
457 .map(|prime| BigUint::from_bytes_be(&prime.factor)),
458 );
459
460 let key = Self::from_components(n, e, d, factors);
461 let key = key.map_err(|err| JwkError::custom(anyhow::anyhow!(err)))?;
462 key.validate()
463 .map_err(|err| JwkError::custom(anyhow::anyhow!(err)))?;
464 Ok(key)
465 }
466}