1#[cfg(feature = "alloc")]
2use super::pkcs1v15_generate_prefix;
3#[cfg(not(feature = "alloc"))]
4use super::{pkcs1v15_generate_prefix_helper, Prefix};
5use super::{verify_generic, GenericSignature};
6use crate::{
7 key::GenericRsaPublicKey,
8 traits::{modular::ModulusParams, PublicKeyParts, UnsignedModularInt},
9};
10#[cfg(feature = "alloc")]
11use alloc::vec::Vec;
12use const_oid::AssociatedOid;
13use core::marker::PhantomData;
14#[cfg(feature = "alloc")]
15use crypto_bigint::{modular::BoxedMontyParams, BoxedUint};
16use digest::{Digest, FixedOutput, HashMarker, Update};
17use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier};
18
19#[cfg(all(feature = "alloc", feature = "encoding"))]
20use crate::key::RsaPublicKey;
21#[cfg(feature = "encoding")]
22use {
23 super::oid,
24 spki::{
25 der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier, Document,
26 EncodePublicKey, SignatureAlgorithmIdentifier,
27 },
28};
29#[cfg(feature = "serde")]
30use {
31 serdect::serde::{de, ser, Deserialize, Serialize},
32 spki::DecodePublicKey,
33};
34
35#[derive(Debug)]
39pub struct GenericVerifyingKey<D, T, M>
40where
41 D: Digest,
42 T: UnsignedModularInt,
43 M: ModulusParams<Modulus = T>,
44{
45 pub(super) inner: GenericRsaPublicKey<T, M>,
46 #[cfg(feature = "alloc")]
47 pub(super) prefix: Vec<u8>,
48 #[cfg(not(feature = "alloc"))]
49 pub(super) prefix: Prefix,
50 pub(super) phantom: PhantomData<D>,
51}
52
53#[cfg(feature = "alloc")]
55pub type VerifyingKey<D> = GenericVerifyingKey<D, BoxedUint, BoxedMontyParams>;
56
57impl<D, T, M> GenericVerifyingKey<D, T, M>
58where
59 D: Digest + AssociatedOid,
60 T: UnsignedModularInt,
61 M: ModulusParams<Modulus = T>,
62{
63 pub fn new(key: GenericRsaPublicKey<T, M>) -> Self {
65 Self {
66 inner: key,
67 #[cfg(feature = "alloc")]
68 prefix: pkcs1v15_generate_prefix::<D>(),
69 #[cfg(not(feature = "alloc"))]
70 prefix: pkcs1v15_generate_prefix_helper::<D>(),
71 phantom: Default::default(),
72 }
73 }
74}
75
76impl<D, T, M> GenericVerifyingKey<D, T, M>
77where
78 D: Digest,
79 T: UnsignedModularInt,
80 M: ModulusParams<Modulus = T>,
81{
82 pub fn new_unprefixed(key: GenericRsaPublicKey<T, M>) -> Self {
88 Self {
89 inner: key,
90 #[cfg(feature = "alloc")]
91 prefix: Vec::new(),
92 #[cfg(not(feature = "alloc"))]
93 prefix: Prefix::new(),
94 phantom: Default::default(),
95 }
96 }
97
98 fn verify_prehash_signature(
99 &self,
100 prehash: &[u8],
101 signature: &GenericSignature<T>,
102 ) -> signature::Result<()> {
103 let mut storage = self.inner.n().as_ref().to_be_bytes();
104 verify_generic(
105 &self.inner,
106 self.prefix.as_ref(),
107 prehash,
108 signature.inner(),
109 storage.as_mut(),
110 )
111 .map_err(Into::into)
112 }
113}
114
115impl<D, T, M> DigestVerifier<D, GenericSignature<T>> for GenericVerifyingKey<D, T, M>
120where
121 D: Default + FixedOutput + HashMarker + Update,
122 T: UnsignedModularInt,
123 M: ModulusParams<Modulus = T>,
124{
125 fn verify_digest<F: Fn(&mut D) -> signature::Result<()>>(
126 &self,
127 f: F,
128 signature: &GenericSignature<T>,
129 ) -> signature::Result<()> {
130 let mut digest = D::default();
131 f(&mut digest)?;
132 self.verify_prehash_signature(&digest.finalize_fixed(), signature)
133 }
134}
135
136impl<D, T, M> PrehashVerifier<GenericSignature<T>> for GenericVerifyingKey<D, T, M>
137where
138 D: Digest,
139 T: UnsignedModularInt,
140 M: ModulusParams<Modulus = T>,
141{
142 fn verify_prehash(
143 &self,
144 prehash: &[u8],
145 signature: &GenericSignature<T>,
146 ) -> signature::Result<()> {
147 self.verify_prehash_signature(prehash, signature)
148 }
149}
150
151impl<D, T, M> Verifier<GenericSignature<T>> for GenericVerifyingKey<D, T, M>
152where
153 D: Digest,
154 T: UnsignedModularInt,
155 M: ModulusParams<Modulus = T>,
156{
157 fn verify(&self, msg: &[u8], signature: &GenericSignature<T>) -> signature::Result<()> {
158 self.verify_prehash_signature(&D::digest(msg), signature)
159 }
160}
161
162impl<D, T, M> AsRef<GenericRsaPublicKey<T, M>> for GenericVerifyingKey<D, T, M>
167where
168 D: Digest,
169 T: UnsignedModularInt,
170 M: ModulusParams<Modulus = T>,
171{
172 fn as_ref(&self) -> &GenericRsaPublicKey<T, M> {
173 &self.inner
174 }
175}
176
177#[cfg(feature = "encoding")]
178#[cfg(feature = "alloc")]
179impl<D> AssociatedAlgorithmIdentifier for VerifyingKey<D>
180where
181 D: Digest,
182{
183 type Params = AnyRef<'static>;
184
185 const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
186}
187
188impl<D, T, M> Clone for GenericVerifyingKey<D, T, M>
190where
191 D: Digest,
192 T: UnsignedModularInt,
193 M: ModulusParams<Modulus = T> + Clone,
194{
195 fn clone(&self) -> Self {
196 Self {
197 inner: self.inner.clone(),
198 prefix: self.prefix.clone(),
199 phantom: Default::default(),
200 }
201 }
202}
203
204#[cfg(feature = "encoding")]
205#[cfg(feature = "alloc")]
206impl<D> EncodePublicKey for VerifyingKey<D>
207where
208 D: Digest,
209{
210 fn to_public_key_der(&self) -> spki::Result<Document> {
211 self.inner.to_public_key_der()
212 }
213}
214
215impl<D, T, M> From<GenericRsaPublicKey<T, M>> for GenericVerifyingKey<D, T, M>
216where
217 D: Digest + AssociatedOid,
218 T: UnsignedModularInt,
219 M: ModulusParams<Modulus = T>,
220{
221 fn from(key: GenericRsaPublicKey<T, M>) -> Self {
222 Self::new(key)
223 }
224}
225
226impl<D, T, M> From<GenericVerifyingKey<D, T, M>> for GenericRsaPublicKey<T, M>
227where
228 D: Digest,
229 T: UnsignedModularInt,
230 M: ModulusParams<Modulus = T>,
231{
232 fn from(key: GenericVerifyingKey<D, T, M>) -> Self {
233 key.inner
234 }
235}
236
237#[cfg(feature = "encoding")]
238#[cfg(feature = "alloc")]
239impl<D> SignatureAlgorithmIdentifier for VerifyingKey<D>
240where
241 D: Digest + oid::RsaSignatureAssociatedOid,
242{
243 type Params = AnyRef<'static>;
244
245 const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> =
246 AlgorithmIdentifierRef {
247 oid: D::OID,
248 parameters: Some(AnyRef::NULL),
249 };
250}
251
252#[cfg(feature = "encoding")]
253#[cfg(feature = "alloc")]
254impl<D> TryFrom<pkcs8::SubjectPublicKeyInfoRef<'_>> for VerifyingKey<D>
255where
256 D: Digest + AssociatedOid,
257{
258 type Error = spki::Error;
259
260 fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> spki::Result<Self> {
261 spki.algorithm.assert_algorithm_oid(pkcs1::ALGORITHM_OID)?;
262
263 RsaPublicKey::try_from(spki).map(Self::new)
264 }
265}
266
267impl<D, T, M> PartialEq for GenericVerifyingKey<D, T, M>
268where
269 D: Digest,
270 T: UnsignedModularInt + PartialEq,
271 M: ModulusParams<Modulus = T>,
272{
273 fn eq(&self, other: &Self) -> bool {
274 self.inner == other.inner && self.prefix == other.prefix
275 }
276}
277
278#[cfg(feature = "serde")]
279#[cfg(feature = "alloc")]
280impl<D> Serialize for VerifyingKey<D>
281where
282 D: Digest,
283{
284 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
285 where
286 S: serde::Serializer,
287 {
288 let der = self.to_public_key_der().map_err(ser::Error::custom)?;
289 serdect::slice::serialize_hex_lower_or_bin(&der, serializer)
290 }
291}
292
293#[cfg(feature = "serde")]
294#[cfg(feature = "alloc")]
295impl<'de, D> Deserialize<'de> for VerifyingKey<D>
296where
297 D: Digest + AssociatedOid,
298{
299 fn deserialize<De>(deserializer: De) -> Result<Self, De::Error>
300 where
301 De: serde::Deserializer<'de>,
302 {
303 let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?;
304 Self::from_public_key_der(&der_bytes).map_err(de::Error::custom)
305 }
306}
307
308#[cfg(test)]
309mod tests {
310 #[test]
311 #[cfg(all(feature = "hazmat", feature = "serde"))]
312 fn test_serde() {
313 use super::*;
314 use crate::RsaPrivateKey;
315 use rand::rngs::ChaCha8Rng;
316 use rand_core::SeedableRng;
317 use serde_test::{assert_tokens, Configure, Token};
318 use sha2::Sha256;
319
320 let mut rng = ChaCha8Rng::from_seed([42; 32]);
321 let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
322 let pub_key = priv_key.to_public_key();
323 let verifying_key = GenericVerifyingKey::<Sha256, _, _>::new(pub_key);
324
325 let tokens = [Token::Str(
326 "3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
327 )];
328
329 assert_tokens(&verifying_key.readable(), &tokens);
330 }
331}