1use rand::thread_rng;
2use rand_core::{CryptoRng, RngCore};
3use rsa::{hash::Hash, BigUint, PaddingScheme, PublicKey, RSAPrivateKey, RSAPublicKey};
4use sha2::{Digest, Sha256, Sha384, Sha512};
5use thiserror::Error;
6
7use std::borrow::Cow;
8
9use crate::{Algorithm, AlgorithmSignature};
10
11#[derive(Debug, Error)]
13pub enum RsaError {
14 #[error("Unsupported signature length")]
15 UnsupportedSignatureLength,
16 #[error("Unsupported modulus size")]
17 UnsupportedModulusSize,
18 #[error("Invalid key: {0}")]
19 InvalidKey(rsa::errors::Error),
20 #[error("Key generation error: {0}")]
21 KeygenError(rsa::errors::Error),
22}
23
24#[derive(Debug)]
25pub struct Signature(Vec<u8>);
26
27impl AlgorithmSignature for Signature {
28 fn try_from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
29 match bytes.len() {
30 256 | 384 | 512 => Ok(Signature(bytes.to_vec())),
31 _ => Err(RsaError::UnsupportedSignatureLength.into()),
32 }
33 }
34
35 fn as_bytes(&self) -> Cow<[u8]> {
36 Cow::Owned(self.0.clone())
37 }
38}
39
40#[derive(Debug, Copy, Clone, Eq, PartialEq)]
42pub enum Padding {
43 Pkcs1v15,
45 Pss,
47}
48
49#[derive(Debug, Clone, Eq, PartialEq)]
51pub struct RsaVerifyingKey(RSAPublicKey);
52
53impl AsRef<RSAPublicKey> for RsaVerifyingKey {
54 fn as_ref(&self) -> &RSAPublicKey {
55 &self.0
56 }
57}
58
59impl RsaVerifyingKey {
60 pub fn from_der(der: &[u8]) -> anyhow::Result<RsaVerifyingKey> {
62 match RSAPublicKey::from_pkcs8(&der) {
63 Err(e) => Err(RsaError::InvalidKey(e).into()),
64 Ok(key) => Ok(RsaVerifyingKey(key)),
65 }
66 }
67
68 pub fn from_components(n: &[u8], e: &[u8]) -> anyhow::Result<RsaVerifyingKey> {
70 let n = BigUint::from_bytes_be(n);
71 let e = BigUint::from_bytes_be(e);
72 match RSAPublicKey::new(n, e) {
73 Err(e) => Err(RsaError::InvalidKey(e).into()),
74 Ok(key) => Ok(RsaVerifyingKey(key)),
75 }
76 }
77}
78
79#[derive(Debug)]
81pub struct RsaSigningKey(RSAPrivateKey);
82
83impl AsRef<RSAPrivateKey> for RsaSigningKey {
84 fn as_ref(&self) -> &RSAPrivateKey {
85 &self.0
86 }
87}
88
89impl RsaSigningKey {
90 pub fn from_der(der: &[u8]) -> anyhow::Result<RsaSigningKey> {
92 match RSAPrivateKey::from_pkcs8(&der) {
93 Err(e) => Err(RsaError::InvalidKey(e).into()),
94 Ok(key) => {
95 key.validate().map_err(RsaError::InvalidKey)?;
96 Ok(RsaSigningKey(key))
97 }
98 }
99 }
100
101 pub fn to_verifying_key(&self) -> RsaVerifyingKey {
103 RsaVerifyingKey(RSAPublicKey::from(&self.0))
104 }
105}
106
107#[derive(Debug)]
115pub struct Rsa {
116 hash_alg: Hash,
117 padding_alg: Padding,
118}
119
120impl Rsa {
121 pub fn new(hash_alg: Hash, padding_alg: Padding) -> Self {
123 Rsa {
124 hash_alg,
125 padding_alg,
126 }
127 }
128}
129
130pub trait RsaVariant {
131 fn rsa() -> Rsa;
132}
133
134impl<T: RsaVariant> Algorithm for T {
135 type SigningKey = RsaSigningKey;
136 type VerifyingKey = RsaVerifyingKey;
137 type Signature = Signature;
138
139 fn name(&self) -> Cow<'static, str> {
140 Self::rsa().name()
141 }
142
143 fn sign(&self, signing_key: &Self::SigningKey, message: &[u8]) -> Self::Signature {
144 Self::rsa().sign(signing_key, message)
145 }
146
147 fn verify_signature(
148 &self,
149 signature: &Self::Signature,
150 verifying_key: &Self::VerifyingKey,
151 message: &[u8],
152 ) -> bool {
153 Self::rsa().verify_signature(signature, verifying_key, message)
154 }
155}
156
157impl Rsa {
158 fn hash(&self, message: &[u8]) -> Vec<u8> {
159 match self.hash_alg {
160 Hash::SHA2_256 => Sha256::digest(message).to_vec(),
161 Hash::SHA2_384 => Sha384::digest(message).to_vec(),
162 Hash::SHA2_512 => Sha512::digest(message).to_vec(),
163 _ => unreachable!(),
164 }
165 }
166
167 fn padding_scheme(&self) -> PaddingScheme {
168 match self.padding_alg {
169 Padding::Pkcs1v15 => PaddingScheme::new_pkcs1v15_sign(Some(self.hash_alg)),
170 Padding::Pss => {
171 let rng = rand_core::OsRng {};
172 match self.hash_alg {
173 Hash::SHA2_256 => PaddingScheme::new_pss::<Sha256, _>(rng),
174 Hash::SHA2_384 => PaddingScheme::new_pss::<Sha384, _>(rng),
175 Hash::SHA2_512 => PaddingScheme::new_pss::<Sha512, _>(rng),
176 _ => unreachable!(),
177 }
178 }
179 }
180 }
181
182 fn name(&self) -> Cow<'static, str> {
183 let name = match self.hash_alg {
184 Hash::SHA2_256 => "RS256",
185 Hash::SHA2_384 => "RS384",
186 Hash::SHA2_512 => "RS512",
187 _ => unreachable!(),
188 };
189 Cow::Borrowed(name)
190 }
191
192 fn sign(&self, signing_key: &RsaSigningKey, message: &[u8]) -> Signature {
193 let digest = self.hash(message);
194 let mut rng = thread_rng();
195 Signature(
196 signing_key
197 .as_ref()
198 .sign_blinded(&mut rng, self.padding_scheme(), &digest)
199 .expect("Unexpected RSA signature failure"),
200 )
201 }
202
203 fn verify_signature(
204 &self,
205 signature: &Signature,
206 verifying_key: &RsaVerifyingKey,
207 message: &[u8],
208 ) -> bool {
209 let digest = self.hash(message);
210 verifying_key
211 .as_ref()
212 .verify(self.padding_scheme(), &digest, &signature.0)
213 .is_ok()
214 }
215
216 pub fn generate<R: CryptoRng + RngCore>(
218 rng: &mut R,
219 modulus_bits: usize,
220 ) -> anyhow::Result<(RsaSigningKey, RsaVerifyingKey)> {
221 match modulus_bits {
222 2048 | 3072 | 4096 => {}
223 _ => return Err(RsaError::UnsupportedModulusSize.into()),
224 }
225 let signing_key = match RSAPrivateKey::new(rng, modulus_bits) {
226 Err(e) => return Err(RsaError::KeygenError(e).into()),
227 Ok(key) => RsaSigningKey(key),
228 };
229 let verifying_key = signing_key.to_verifying_key();
230 Ok((signing_key, verifying_key))
231 }
232}
233
234#[derive(Debug)]
236pub struct Rs256;
237
238impl RsaVariant for Rs256 {
239 fn rsa() -> Rsa {
240 Rsa::new(Hash::SHA2_256, Padding::Pkcs1v15)
241 }
242}
243
244#[derive(Debug)]
246pub struct Rs384;
247
248impl RsaVariant for Rs384 {
249 fn rsa() -> Rsa {
250 Rsa::new(Hash::SHA2_384, Padding::Pkcs1v15)
251 }
252}
253
254#[derive(Debug)]
256pub struct Rs512;
257
258impl RsaVariant for Rs512 {
259 fn rsa() -> Rsa {
260 Rsa::new(Hash::SHA2_512, Padding::Pkcs1v15)
261 }
262}
263
264#[derive(Debug)]
266pub struct Ps256;
267
268impl RsaVariant for Ps256 {
269 fn rsa() -> Rsa {
270 Rsa::new(Hash::SHA2_256, Padding::Pss)
271 }
272}
273
274#[derive(Debug)]
276pub struct Ps384;
277
278impl RsaVariant for Ps384 {
279 fn rsa() -> Rsa {
280 Rsa::new(Hash::SHA2_384, Padding::Pss)
281 }
282}
283
284#[derive(Debug)]
286pub struct Ps512;
287
288impl RsaVariant for Ps512 {
289 fn rsa() -> Rsa {
290 Rsa::new(Hash::SHA2_512, Padding::Pss)
291 }
292}