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 where D: Digest, { pub(super) inner: RsaPublicKey, pub(super) salt_len: usize, pub(super) phantom: PhantomData, } impl VerifyingKey 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, ::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 DigestVerifier for VerifyingKey where D: Digest + FixedOutputReset, { fn verify_digest(&self, digest: D, signature: &Signature) -> signature::Result<()> { verify_digest::( &self.inner, &digest.finalize(), &signature.inner, signature.len, self.salt_len, ) .map_err(|e| e.into()) } } impl PrehashVerifier for VerifyingKey where D: Digest + FixedOutputReset, { fn verify_prehash(&self, prehash: &[u8], signature: &Signature) -> signature::Result<()> { verify_digest::( &self.inner, prehash, &signature.inner, signature.len, self.salt_len, ) .map_err(|e| e.into()) } } impl Verifier for VerifyingKey where D: Digest + FixedOutputReset, { fn verify(&self, msg: &[u8], signature: &Signature) -> signature::Result<()> { verify_digest::( &self.inner, &D::digest(msg), &signature.inner, signature.len, self.salt_len, ) .map_err(|e| e.into()) } } // // Other trait impls // impl AsRef for VerifyingKey where D: Digest, { fn as_ref(&self) -> &RsaPublicKey { &self.inner } } impl AssociatedAlgorithmIdentifier for VerifyingKey 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 Clone for VerifyingKey where D: Digest, { fn clone(&self) -> Self { Self { inner: self.inner.clone(), salt_len: self.salt_len, phantom: Default::default(), } } } impl EncodePublicKey for VerifyingKey where D: Digest, { fn to_public_key_der(&self) -> pkcs8::spki::Result { self.inner.to_public_key_der() } } impl From for VerifyingKey where D: Digest, { fn from(key: RsaPublicKey) -> Self { Self::new(key) } } impl From> for RsaPublicKey where D: Digest, { fn from(key: VerifyingKey) -> Self { key.inner } }