ts_crypto/
rsa.rs

1//! RSA keys
2
3use digest::{Digest, DynDigest, FixedOutput};
4use pkcs8::AssociatedOid;
5use rsa::{
6    BoxedUint, Pkcs1v15Sign, Pss, RsaPrivateKey, RsaPublicKey,
7    traits::{PublicKeyParts, SignatureScheme},
8};
9use sha2::{Sha256, Sha384, Sha512};
10use spki::DecodePublicKey;
11
12pub use rsa::{RsaPrivateKey as RsaSigningKey, RsaPublicKey as RsaVerifyingKey};
13
14/// Extension trait to [`SignatureScheme`] to make creating a new instance generic.
15pub trait SignatureSchemeExt: SignatureScheme {
16    /// Create a new instance of the signature scheme.
17    fn new<D: 'static + Digest + DynDigest + FixedOutput + AssociatedOid + Send + Sync>() -> Self;
18}
19
20/// A verifying key using RSA.
21pub trait VerifyingKey {
22    /// Get the key's modulus.
23    fn modulus(&self) -> Vec<u8>;
24    /// Get the key's exponent.
25    fn exponent(&self) -> Vec<u8>;
26
27    /// Create a new key from its parameters.
28    fn from_parameters(modulus: &[u8], exponent: &[u8]) -> Option<Self>
29    where
30        Self: Sized;
31
32    /// Create a new key from a PKCS1 der.
33    fn from_pkcs1_der(der: &[u8]) -> Option<Self>
34    where
35        Self: Sized;
36
37    /// Create a new key from a subject public key info der.
38    fn from_spki_der(der: &[u8]) -> Option<Self>
39    where
40        Self: Sized;
41
42    /// Returns if this key verifies the signature to match the message using the `RS256` parameters.
43    fn verifies_rs256(&self, signature: &[u8], message: &[u8]) -> bool;
44    /// Returns if this key verifies the signature to match the message using the `PS256` parameters.
45    fn verifies_ps256(&self, signature: &[u8], message: &[u8]) -> bool;
46    /// Returns if this key verifies the signature to match the message using the `RS384` parameters.
47    fn verifies_rs384(&self, signature: &[u8], message: &[u8]) -> bool;
48    /// Returns if this key verifies the signature to match the message using the `PS384` parameters.
49    fn verifies_ps384(&self, signature: &[u8], message: &[u8]) -> bool;
50    /// Returns if this key verifies the signature to match the message using the `RS512` parameters.
51    fn verifies_rs512(&self, signature: &[u8], message: &[u8]) -> bool;
52    /// Returns if this key verifies the signature to match the message using the `PS512` parameters.
53    fn verifies_ps512(&self, signature: &[u8], message: &[u8]) -> bool;
54}
55
56/// A signing key using RSA.
57pub trait SigningKey {
58    /// Sign the message using the `RS256` parameters.
59    fn sign_rs256(&self, message: &[u8]) -> Vec<u8>;
60    /// Sign the message using the `PS256` parameters.
61    fn sign_ps256(&self, message: &[u8]) -> Vec<u8>;
62    /// Sign the message using the `RS384` parameters.
63    fn sign_rs384(&self, message: &[u8]) -> Vec<u8>;
64    /// Sign the message using the `PS384` parameters.
65    fn sign_ps384(&self, message: &[u8]) -> Vec<u8>;
66    /// Sign the message using the `RS512` parameters.
67    fn sign_rs512(&self, message: &[u8]) -> Vec<u8>;
68    /// Sign the message using the `PS512` parameters.
69    fn sign_ps512(&self, message: &[u8]) -> Vec<u8>;
70
71    /// Create a new key from a PKCS1 DER.
72    fn from_pkcs1_der(der: &[u8]) -> Option<Self>
73    where
74        Self: Sized;
75
76    /// Create a new key from a PKCS8 DER.
77    fn from_pkcs8_der(der: &[u8]) -> Option<Self>
78    where
79        Self: Sized;
80
81    /// Create a verifying key from this key.
82    fn verifying_key(&self) -> Box<dyn VerifyingKey>;
83}
84
85impl VerifyingKey for RsaPublicKey {
86    fn modulus(&self) -> Vec<u8> {
87        self.n_bytes().to_vec()
88    }
89
90    fn exponent(&self) -> Vec<u8> {
91        self.e_bytes().to_vec()
92    }
93
94    fn from_parameters(modulus: &[u8], exponent: &[u8]) -> Option<Self>
95    where
96        Self: Sized,
97    {
98        let modulus = BoxedUint::from_be_slice_vartime(modulus);
99        let exponent = BoxedUint::from_be_slice_vartime(exponent);
100        Self::new(modulus, exponent).ok()
101    }
102
103    fn verifies_rs256(&self, signature: &[u8], message: &[u8]) -> bool {
104        let scheme = Pkcs1v15Sign::new::<Sha256>();
105        let hash = Sha256::digest(message);
106        self.verify(scheme, &hash, signature).is_ok()
107    }
108
109    fn verifies_ps256(&self, signature: &[u8], message: &[u8]) -> bool {
110        let scheme = Pss::new::<Sha256>();
111        let hash = Sha256::digest(message);
112        self.verify(scheme, &hash, signature).is_ok()
113    }
114
115    fn verifies_rs384(&self, signature: &[u8], message: &[u8]) -> bool {
116        let scheme = Pkcs1v15Sign::new::<Sha384>();
117        let hash = Sha384::digest(message);
118        self.verify(scheme, &hash, signature).is_ok()
119    }
120
121    fn verifies_ps384(&self, signature: &[u8], message: &[u8]) -> bool {
122        let scheme = Pss::new::<Sha384>();
123        let hash = Sha384::digest(message);
124        self.verify(scheme, &hash, signature).is_ok()
125    }
126
127    fn verifies_rs512(&self, signature: &[u8], message: &[u8]) -> bool {
128        let scheme = Pkcs1v15Sign::new::<Sha512>();
129        let hash = Sha512::digest(message);
130        self.verify(scheme, &hash, signature).is_ok()
131    }
132
133    fn verifies_ps512(&self, signature: &[u8], message: &[u8]) -> bool {
134        let scheme = Pss::new::<Sha512>();
135        let hash = Sha512::digest(message);
136        self.verify(scheme, &hash, signature).is_ok()
137    }
138
139    fn from_pkcs1_der(der: &[u8]) -> Option<Self>
140    where
141        Self: Sized,
142    {
143        <Self as rsa::pkcs1::DecodeRsaPublicKey>::from_pkcs1_der(der).ok()
144    }
145
146    fn from_spki_der(der: &[u8]) -> Option<Self>
147    where
148        Self: Sized,
149    {
150        Self::from_public_key_der(der).ok()
151    }
152}
153
154impl SigningKey for RsaPrivateKey {
155    fn sign_rs256(&self, message: &[u8]) -> Vec<u8> {
156        let scheme = Pkcs1v15Sign::new::<Sha256>();
157        let hash = Sha256::digest(message);
158        self.sign_with_rng(&mut rand::rng(), scheme, &hash)
159            .expect("RSA signing should not fail")
160    }
161
162    fn sign_ps256(&self, message: &[u8]) -> Vec<u8> {
163        let scheme = Pss::new::<Sha256>();
164        let hash = Sha256::digest(message);
165        self.sign_with_rng(&mut rand::rng(), scheme, &hash)
166            .expect("RSA signing should not fail")
167    }
168
169    fn sign_rs384(&self, message: &[u8]) -> Vec<u8> {
170        let scheme = Pkcs1v15Sign::new::<Sha384>();
171        let hash = Sha384::digest(message);
172        self.sign_with_rng(&mut rand::rng(), scheme, &hash)
173            .expect("RSA signing should not fail")
174    }
175
176    fn sign_ps384(&self, message: &[u8]) -> Vec<u8> {
177        let scheme = Pss::new::<Sha384>();
178        let hash = Sha384::digest(message);
179        self.sign_with_rng(&mut rand::rng(), scheme, &hash)
180            .expect("RSA signing should not fail")
181    }
182
183    fn sign_rs512(&self, message: &[u8]) -> Vec<u8> {
184        let scheme = Pkcs1v15Sign::new::<Sha512>();
185        let hash = Sha512::digest(message);
186        self.sign_with_rng(&mut rand::rng(), scheme, &hash)
187            .expect("RSA signing should not fail")
188    }
189
190    fn sign_ps512(&self, message: &[u8]) -> Vec<u8> {
191        let scheme = Pss::new::<Sha512>();
192        let hash = Sha512::digest(message);
193        self.sign_with_rng(&mut rand::rng(), scheme, &hash)
194            .expect("RSA signing should not fail")
195    }
196
197    fn from_pkcs1_der(der: &[u8]) -> Option<Self>
198    where
199        Self: Sized,
200    {
201        <Self as rsa::pkcs1::DecodeRsaPrivateKey>::from_pkcs1_der(der).ok()
202    }
203
204    fn from_pkcs8_der(der: &[u8]) -> Option<Self>
205    where
206        Self: Sized,
207    {
208        <Self as pkcs8::DecodePrivateKey>::from_pkcs8_der(der).ok()
209    }
210
211    fn verifying_key(&self) -> Box<dyn VerifyingKey> {
212        Box::new(self.to_public_key())
213    }
214}
215
216impl SignatureSchemeExt for Pkcs1v15Sign {
217    fn new<D: 'static + Digest + DynDigest + FixedOutput + AssociatedOid + Send + Sync>() -> Self {
218        Self::new::<D>()
219    }
220}
221impl SignatureSchemeExt for Pss {
222    fn new<D: 'static + Digest + DynDigest + FixedOutput + AssociatedOid + Send + Sync>() -> Self {
223        Self::new::<D>()
224    }
225}