rsa/pss/
verifying_key.rs

1use super::{verify_digest, Signature};
2use crate::RsaPublicKey;
3use core::marker::PhantomData;
4use digest::{Digest, FixedOutputReset};
5use pkcs8::{
6    spki::{der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier},
7    Document, EncodePublicKey,
8};
9use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier};
10
11/// Verifying key for checking the validity of RSASSA-PSS signatures as
12/// described in [RFC8017 § 8.1].
13///
14/// [RFC8017 § 8.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.1
15#[derive(Debug)]
16pub struct VerifyingKey<D>
17where
18    D: Digest,
19{
20    pub(super) inner: RsaPublicKey,
21    pub(super) salt_len: usize,
22    pub(super) phantom: PhantomData<D>,
23}
24
25impl<D> VerifyingKey<D>
26where
27    D: Digest,
28{
29    /// Create a new RSASSA-PSS verifying key.
30    /// Digest output size is used as a salt length.
31    pub fn new(key: RsaPublicKey) -> Self {
32        Self::new_with_salt_len(key, <D as Digest>::output_size())
33    }
34
35    /// Create a new RSASSA-PSS verifying key.
36    pub fn new_with_salt_len(key: RsaPublicKey, salt_len: usize) -> Self {
37        Self {
38            inner: key,
39            salt_len,
40            phantom: Default::default(),
41        }
42    }
43}
44
45//
46// `*Verifier` trait impls
47//
48
49impl<D> DigestVerifier<D, Signature> for VerifyingKey<D>
50where
51    D: Digest + FixedOutputReset,
52{
53    fn verify_digest(&self, digest: D, signature: &Signature) -> signature::Result<()> {
54        verify_digest::<D>(
55            &self.inner,
56            &digest.finalize(),
57            &signature.inner,
58            signature.len,
59            self.salt_len,
60        )
61        .map_err(|e| e.into())
62    }
63}
64
65impl<D> PrehashVerifier<Signature> for VerifyingKey<D>
66where
67    D: Digest + FixedOutputReset,
68{
69    fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> signature::Result<()> {
70        verify_digest::<D>(
71            &self.inner,
72            prehash,
73            &signature.inner,
74            signature.len,
75            self.salt_len,
76        )
77        .map_err(|e| e.into())
78    }
79}
80
81impl<D> Verifier<Signature> for VerifyingKey<D>
82where
83    D: Digest + FixedOutputReset,
84{
85    fn verify(&self, msg: &[u8], signature: &Signature) -> signature::Result<()> {
86        verify_digest::<D>(
87            &self.inner,
88            &D::digest(msg),
89            &signature.inner,
90            signature.len,
91            self.salt_len,
92        )
93        .map_err(|e| e.into())
94    }
95}
96
97//
98// Other trait impls
99//
100
101impl<D> AsRef<RsaPublicKey> for VerifyingKey<D>
102where
103    D: Digest,
104{
105    fn as_ref(&self) -> &RsaPublicKey {
106        &self.inner
107    }
108}
109
110impl<D> AssociatedAlgorithmIdentifier for VerifyingKey<D>
111where
112    D: Digest,
113{
114    type Params = AnyRef<'static>;
115
116    const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
117}
118
119// Implemented manually so we don't have to bind D with Clone
120impl<D> Clone for VerifyingKey<D>
121where
122    D: Digest,
123{
124    fn clone(&self) -> Self {
125        Self {
126            inner: self.inner.clone(),
127            salt_len: self.salt_len,
128            phantom: Default::default(),
129        }
130    }
131}
132
133impl<D> EncodePublicKey for VerifyingKey<D>
134where
135    D: Digest,
136{
137    fn to_public_key_der(&self) -> pkcs8::spki::Result<Document> {
138        self.inner.to_public_key_der()
139    }
140}
141
142impl<D> From<RsaPublicKey> for VerifyingKey<D>
143where
144    D: Digest,
145{
146    fn from(key: RsaPublicKey) -> Self {
147        Self::new(key)
148    }
149}
150
151impl<D> From<VerifyingKey<D>> for RsaPublicKey
152where
153    D: Digest,
154{
155    fn from(key: VerifyingKey<D>) -> Self {
156        key.inner
157    }
158}