1use core::marker::PhantomData;
4
5use const_oid::AssociatedOid;
6use digest::{Digest, DynDigest};
7use rsa::{
8 BoxedUint, Pkcs1v15Sign, Pss as PssSign,
9 traits::{PublicKeyParts, SignatureScheme},
10};
11use sha2::{Sha256, Sha384, Sha512};
12
13use crate::{SignMessage, ToVerifier, VerifySignature};
14
15pub trait Scheme {
17 type Padding: SignatureScheme;
19
20 fn padding<K: KeySize>() -> Self::Padding;
22}
23
24pub trait KeySize {
26 const SIZE: usize;
28
29 type Digest: 'static + Digest + DynDigest + AssociatedOid + Send + Sync;
31}
32
33pub trait Parameters: VerifySignature {
35 fn modulus(&self) -> Vec<u8>;
37
38 fn exponent(&self) -> Vec<u8>;
40
41 fn size(&self) -> usize;
43}
44
45pub trait SetScheme<S: Scheme> {
47 type Output;
49 fn set_scheme(self) -> Self::Output;
51}
52
53pub struct U256;
55pub struct U384;
57pub struct U512;
59
60impl KeySize for U256 {
61 const SIZE: usize = 256;
62 type Digest = Sha256;
63}
64impl KeySize for U384 {
65 const SIZE: usize = 384;
66 type Digest = Sha384;
67}
68impl KeySize for U512 {
69 const SIZE: usize = 512;
70 type Digest = Sha512;
71}
72
73pub struct Pss;
75pub struct Pkcs;
77
78impl Scheme for Pss {
79 type Padding = PssSign;
80
81 fn padding<K: KeySize>() -> Self::Padding {
82 Self::Padding::new::<K::Digest>()
83 }
84}
85
86impl Scheme for Pkcs {
87 type Padding = Pkcs1v15Sign;
88
89 fn padding<K: KeySize>() -> Self::Padding {
90 Self::Padding::new::<K::Digest>()
91 }
92}
93
94pub struct VerifyingKey<S: Scheme, K: KeySize> {
96 pub(crate) key: rsa::RsaPublicKey,
98 pub(crate) scheme: PhantomData<S>,
100 pub(crate) size: PhantomData<K>,
102}
103
104pub struct SigningKey<S: Scheme, K: KeySize> {
106 pub(crate) key: rsa::RsaPrivateKey,
108 pub(crate) scheme: PhantomData<S>,
110 pub(crate) size: PhantomData<K>,
112}
113
114impl<S: Scheme, K: KeySize> VerifyingKey<S, K> {
115 pub fn from_parameters(modulus: &[u8], exponent: &[u8]) -> Option<Self> {
117 let modulus = BoxedUint::from_be_slice_vartime(modulus);
118 let exponent = BoxedUint::from_be_slice_vartime(exponent);
119 let key = rsa::RsaPublicKey::new(modulus, exponent).ok()?;
120 if key.size() != K::SIZE {
121 return None;
122 }
123 Some(Self {
124 key,
125 scheme: PhantomData,
126 size: PhantomData,
127 })
128 }
129}
130
131impl<S1: Scheme, S2: Scheme, K: KeySize> SetScheme<S2> for VerifyingKey<S1, K> {
132 type Output = VerifyingKey<S2, K>;
133
134 fn set_scheme(self) -> Self::Output {
135 Self::Output {
136 key: self.key,
137 scheme: PhantomData,
138 size: PhantomData,
139 }
140 }
141}
142
143impl<S: Scheme, K: KeySize> Parameters for VerifyingKey<S, K> {
144 fn modulus(&self) -> Vec<u8> {
145 self.key.n_bytes().to_vec()
146 }
147
148 fn exponent(&self) -> Vec<u8> {
149 self.key.e_bytes().to_vec()
150 }
151
152 fn size(&self) -> usize {
153 K::SIZE
154 }
155}
156
157impl<S: Scheme, K: KeySize> VerifySignature for VerifyingKey<S, K> {
158 fn verifies_signature(&self, signature: &[u8], message: &[u8]) -> bool {
159 let hash = K::Digest::digest(message);
160 let scheme = S::padding::<K>();
161 self.key.verify(scheme, &hash, signature).is_ok()
162 }
163}
164
165impl<S1: Scheme, S2: Scheme, K: KeySize> SetScheme<S2> for SigningKey<S1, K> {
166 type Output = SigningKey<S2, K>;
167
168 fn set_scheme(self) -> Self::Output {
169 Self::Output {
170 key: self.key,
171 scheme: PhantomData,
172 size: PhantomData,
173 }
174 }
175}
176
177impl<S: Scheme, K: KeySize> SignMessage for SigningKey<S, K> {
178 fn sign(&self, message: &[u8]) -> Vec<u8> {
179 let hash = K::Digest::digest(message);
180 self.key
181 .sign(S::padding::<K>(), &hash)
182 .expect("signing should not fail")
183 .to_vec()
184 }
185}
186
187impl<S: Scheme, K: KeySize> ToVerifier for SigningKey<S, K> {
188 type Key = VerifyingKey<S, K>;
189
190 fn verifying_key(&self) -> Self::Key {
191 Self::Key {
192 key: self.key.to_public_key(),
193 scheme: PhantomData,
194 size: PhantomData,
195 }
196 }
197}