1use rsa::{BoxedUint, RsaPrivateKey, RsaPublicKey, traits::PublicKeyParts};
4use sha2::{Digest as _, Sha256};
5
6pub use rsa::{Pkcs1v15Sign as Pkcs1v15, Pss};
7
8use crate::Digest;
9
10pub trait SignatureScheme: rsa::traits::SignatureScheme {
12 fn new<D: Digest>() -> Self;
14}
15impl SignatureScheme for Pkcs1v15 {
16 fn new<D: Digest>() -> Self {
17 Self::new::<D>()
18 }
19}
20impl SignatureScheme for Pss {
21 fn new<D: Digest>() -> Self {
22 Self::new::<D>()
23 }
24}
25
26pub struct RsaVerifyingKey(pub RsaPublicKey);
28
29pub struct RsaSigningKey(pub RsaPrivateKey);
31
32impl RsaVerifyingKey {
33 pub fn modulus(&self) -> Vec<u8> {
35 self.0.n_bytes().to_vec()
36 }
37
38 pub fn exponent(&self) -> Vec<u8> {
40 self.0.e_bytes().to_vec()
41 }
42
43 pub fn from_parameters(modulus: &[u8], exponent: &[u8]) -> Option<Self> {
45 let modulus = BoxedUint::from_be_slice_vartime(modulus);
46 let exponent = BoxedUint::from_be_slice_vartime(exponent);
47 let key = RsaPublicKey::new(modulus, exponent).ok()?;
48 Some(Self(key))
49 }
50
51 pub fn verifies<S: SignatureScheme, D: Digest>(
53 &self,
54 signature: &[u8],
55 message: &[u8],
56 ) -> bool {
57 let hash = D::digest(message);
58 let scheme = S::new::<D>();
59 self.0.verify(scheme, &hash, signature).is_ok()
60 }
61
62 pub fn key_id(&self) -> Vec<u8> {
64 let modulus = self.modulus();
65 let exponent = self.exponent();
66 let digest = Sha256::new()
67 .chain_update(modulus)
68 .chain_update(exponent)
69 .finalize();
70 digest.to_vec()
71 }
72}
73
74impl RsaSigningKey {
75 pub fn sign<S: SignatureScheme, D: Digest>(&self, message: &[u8]) -> Vec<u8> {
80 let digest = D::digest(message);
81 let scheme = S::new::<D>();
82 self.0
83 .sign_with_rng(&mut rand::rng(), scheme, digest.as_slice())
84 .expect("RSA signing with valid parameters should not fail")
85 }
86
87 pub fn verifying_key(&self) -> RsaVerifyingKey {
89 RsaVerifyingKey(self.0.to_public_key())
90 }
91}