| use super::{verify_digest, Signature}; |
| use crate::RsaPublicKey; |
| use core::marker::PhantomData; |
| use digest::{Digest, FixedOutputReset}; |
| use pkcs8::{ |
| spki::{der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier}, |
| Document, EncodePublicKey, |
| }; |
| use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier}; |
| |
| /// Verifying key for checking the validity of RSASSA-PSS signatures as |
| /// described in [RFC8017 § 8.1]. |
| /// |
| /// [RFC8017 § 8.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.1 |
| #[derive(Debug)] |
| pub struct VerifyingKey<D> |
| where |
| D: Digest, |
| { |
| pub(super) inner: RsaPublicKey, |
| pub(super) salt_len: usize, |
| pub(super) phantom: PhantomData<D>, |
| } |
| |
| impl<D> VerifyingKey<D> |
| where |
| D: Digest, |
| { |
| /// Create a new RSASSA-PSS verifying key. |
| /// Digest output size is used as a salt length. |
| pub fn new(key: RsaPublicKey) -> Self { |
| Self::new_with_salt_len(key, <D as Digest>::output_size()) |
| } |
| |
| /// Create a new RSASSA-PSS verifying key. |
| pub fn new_with_salt_len(key: RsaPublicKey, salt_len: usize) -> Self { |
| Self { |
| inner: key, |
| salt_len, |
| phantom: Default::default(), |
| } |
| } |
| } |
| |
| // |
| // `*Verifier` trait impls |
| // |
| |
| impl<D> DigestVerifier<D, Signature> for VerifyingKey<D> |
| where |
| D: Digest + FixedOutputReset, |
| { |
| fn verify_digest(&self, digest: D, signature: &Signature) -> signature::Result<()> { |
| verify_digest::<D>( |
| &self.inner, |
| &digest.finalize(), |
| &signature.inner, |
| signature.len, |
| self.salt_len, |
| ) |
| .map_err(|e| e.into()) |
| } |
| } |
| |
| impl<D> PrehashVerifier<Signature> for VerifyingKey<D> |
| where |
| D: Digest + FixedOutputReset, |
| { |
| fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> signature::Result<()> { |
| verify_digest::<D>( |
| &self.inner, |
| prehash, |
| &signature.inner, |
| signature.len, |
| self.salt_len, |
| ) |
| .map_err(|e| e.into()) |
| } |
| } |
| |
| impl<D> Verifier<Signature> for VerifyingKey<D> |
| where |
| D: Digest + FixedOutputReset, |
| { |
| fn verify(&self, msg: &[u8], signature: &Signature) -> signature::Result<()> { |
| verify_digest::<D>( |
| &self.inner, |
| &D::digest(msg), |
| &signature.inner, |
| signature.len, |
| self.salt_len, |
| ) |
| .map_err(|e| e.into()) |
| } |
| } |
| |
| // |
| // Other trait impls |
| // |
| |
| impl<D> AsRef<RsaPublicKey> for VerifyingKey<D> |
| where |
| D: Digest, |
| { |
| fn as_ref(&self) -> &RsaPublicKey { |
| &self.inner |
| } |
| } |
| |
| impl<D> AssociatedAlgorithmIdentifier for VerifyingKey<D> |
| where |
| D: Digest, |
| { |
| type Params = AnyRef<'static>; |
| |
| const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID; |
| } |
| |
| // Implemented manually so we don't have to bind D with Clone |
| impl<D> Clone for VerifyingKey<D> |
| where |
| D: Digest, |
| { |
| fn clone(&self) -> Self { |
| Self { |
| inner: self.inner.clone(), |
| salt_len: self.salt_len, |
| phantom: Default::default(), |
| } |
| } |
| } |
| |
| impl<D> EncodePublicKey for VerifyingKey<D> |
| where |
| D: Digest, |
| { |
| fn to_public_key_der(&self) -> pkcs8::spki::Result<Document> { |
| self.inner.to_public_key_der() |
| } |
| } |
| |
| impl<D> From<RsaPublicKey> for VerifyingKey<D> |
| where |
| D: Digest, |
| { |
| fn from(key: RsaPublicKey) -> Self { |
| Self::new(key) |
| } |
| } |
| |
| impl<D> From<VerifyingKey<D>> for RsaPublicKey |
| where |
| D: Digest, |
| { |
| fn from(key: VerifyingKey<D>) -> Self { |
| key.inner |
| } |
| } |