use rsa::{
pss::{Signature, VerifyingKey},
sha2::{Sha256, Sha384, Sha512},
signature::Verifier,
BigUint, RsaPublicKey,
};
use spki::SubjectPublicKeyInfoRef;
use x509_parser::der_parser::ber::{parse_ber_sequence, BerObject};
use crate::raw_signature::{RawSignatureValidationError, RawSignatureValidator};
#[non_exhaustive]
pub enum RsaValidator {
Ps256,
Ps384,
Ps512,
}
impl RawSignatureValidator for RsaValidator {
fn validate(
&self,
sig: &[u8],
data: &[u8],
public_key: &[u8],
) -> Result<(), RawSignatureValidationError> {
let signature: Signature = sig
.try_into()
.map_err(|_| RawSignatureValidationError::InvalidSignature)?;
let spki = SubjectPublicKeyInfoRef::try_from(public_key)
.map_err(|_| RawSignatureValidationError::InvalidPublicKey)?;
let (_, seq) = parse_ber_sequence(spki.subject_public_key.raw_bytes())
.map_err(|_| RawSignatureValidationError::InvalidPublicKey)?;
let modulus = biguint_val(&seq[0]);
let exp = biguint_val(&seq[1]);
let public_key = RsaPublicKey::new(modulus, exp)
.map_err(|_| RawSignatureValidationError::InvalidPublicKey)?;
let result = match self {
Self::Ps256 => {
let vk = VerifyingKey::<Sha256>::new(public_key);
vk.verify(data, &signature)
}
Self::Ps384 => {
let vk = VerifyingKey::<Sha384>::new(public_key);
vk.verify(data, &signature)
}
Self::Ps512 => {
let vk = VerifyingKey::<Sha512>::new(public_key);
vk.verify(data, &signature)
}
};
result.map_err(|_| RawSignatureValidationError::SignatureMismatch)
}
}
pub(super) fn biguint_val(ber_object: &BerObject) -> BigUint {
ber_object
.as_biguint()
.map(|x| x.to_u32_digits())
.map(rsa::BigUint::new)
.unwrap_or_default()
}