use alloc::vec::Vec;
use core::ops::{Deref, DerefMut};
use thiserror::Error;
use super::JsonWebSignature;
use crate::{
crypto,
format::{DecodeFormat, DecodeFormatWithContext, Format, JsonGeneral},
jwa::{JsonWebAlgorithm, JsonWebSigningAlgorithm},
jwk::FromKey,
};
#[derive(Debug, Error)]
pub enum VerifyError {
#[error("signature is invalid")]
InvalidSignature,
#[error("crypto backend error")]
CryptoBackend(
#[from]
#[source]
crypto::Error,
),
}
pub trait Verifier {
fn verify(&mut self, msg: &[u8], signature: &[u8]) -> Result<(), VerifyError>;
}
#[derive(Debug)]
pub struct Unverified<T> {
pub(crate) value: T,
pub(crate) signature: Vec<u8>,
pub(crate) msg: Vec<u8>,
}
impl<T> Unverified<T> {
pub fn decode<F: Format>(input: F) -> Result<Self, T::Error>
where
T: DecodeFormat<F, Decoded<T> = Unverified<T>>,
{
T::decode(input)
}
pub fn decode_with_context<F: Format, C>(input: F, context: &C) -> Result<Self, T::Error>
where
T: DecodeFormatWithContext<F, C, Decoded<T> = Unverified<T>>,
{
T::decode_with_context(input, context)
}
pub fn verify(self, verifier: &mut dyn Verifier) -> Result<Verified<T>, VerifyError> {
verifier.verify(&self.msg, &self.signature)?;
Ok(Verified(self.value))
}
}
impl<T, F> Unverified<JsonWebSignature<F, T>>
where
F: Format,
{
pub fn expose_unverified_header(&self) -> &F::JwsHeader {
&self.value.header
}
pub fn expose_unverified_payload(&self) -> &T {
&self.value.payload
}
pub fn expose_unverified_raw_signature(&self) -> &[u8] {
self.signature.as_slice()
}
}
#[derive(Debug)]
pub struct ManyUnverified<T> {
pub(crate) value: T,
pub(crate) signatures: Vec<(Vec<u8>, Vec<u8>)>,
}
impl<T> ManyUnverified<T> {
pub fn decode(input: JsonGeneral) -> Result<Self, T::Error>
where
T: DecodeFormat<JsonGeneral, Decoded<T> = ManyUnverified<T>>,
{
T::decode(input)
}
pub fn signature_count(&self) -> usize {
self.signatures.len()
}
pub fn verify_many<'a>(
self,
verifiers: impl IntoIterator<Item = &'a mut dyn Verifier>,
) -> Result<Verified<T>, VerifyError> {
let verifiers = verifiers.into_iter().collect::<Vec<_>>();
if verifiers.len() != self.signatures.len() {
return Err(VerifyError::InvalidSignature);
}
for (verifier, (msg, signature)) in verifiers.into_iter().zip(self.signatures) {
verifier.verify(&msg, &signature)?;
}
Ok(Verified(self.value))
}
}
impl<T, F> ManyUnverified<JsonWebSignature<F, T>>
where
F: Format,
{
pub fn expose_unverified_header(&self) -> &F::JwsHeader {
&self.value.header
}
pub fn expose_unverified_payload(&self) -> &T {
&self.value.payload
}
pub fn expose_unverified_raw_signatures(&self) -> impl Iterator<Item = (&[u8], &[u8])> {
self.signatures
.iter()
.map(|(msg, sig)| (msg.as_slice(), sig.as_slice()))
}
}
#[derive(Debug)]
pub struct Verified<T>(T);
impl<T> Verified<T> {
pub fn into_inner(self) -> T {
self.0
}
}
impl<T> Deref for Verified<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Verified<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub trait IntoVerifier<V>
where
V: Verifier,
{
type Error;
fn into_verifier(self, alg: JsonWebSigningAlgorithm) -> Result<V, Self::Error>;
}
impl<K, V> IntoVerifier<V> for K
where
V: FromKey<K> + Verifier,
{
type Error = <V as FromKey<K>>::Error;
fn into_verifier(self, alg: JsonWebSigningAlgorithm) -> Result<V, Self::Error> {
V::from_key(self, JsonWebAlgorithm::Signing(alg))
}
}