use core::fmt;
use crate::{
crypto,
format::Format,
jwa::{JsonWebAlgorithm, JsonWebSigningAlgorithm},
jwk::FromKey,
};
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct Signed<F> {
pub(crate) value: F,
}
impl<F: Format> fmt::Display for Signed<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.value, f)
}
}
impl<F: Format> Signed<F> {
#[inline]
pub fn encode(self) -> F {
self.value
}
}
pub trait Signer<S: AsRef<[u8]>> {
fn sign(&mut self, msg: &[u8]) -> Result<S, crypto::Error>;
fn algorithm(&self) -> JsonWebSigningAlgorithm;
fn key_id(&self) -> Option<&str> {
None
}
fn without_key_id(self) -> SignerWithoutKeyId<Self>
where
Self: Sized,
{
SignerWithoutKeyId { inner: self }
}
}
#[derive(Debug, Clone)]
pub struct SignerWithoutKeyId<S> {
inner: S,
}
impl<SIG: AsRef<[u8]>, S: Signer<SIG>> Signer<SIG> for SignerWithoutKeyId<S> {
fn sign(&mut self, msg: &[u8]) -> Result<SIG, crypto::Error> {
S::sign(&mut self.inner, msg)
}
fn algorithm(&self) -> JsonWebSigningAlgorithm {
S::algorithm(&self.inner)
}
fn key_id(&self) -> Option<&str> {
None
}
}
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
#[error("Invalid algorithm")]
pub struct InvalidSigningAlgorithmError;
pub trait IntoSigner<T, S>
where
T: Signer<S>,
S: AsRef<[u8]>,
{
type Error;
fn into_signer(self, alg: JsonWebSigningAlgorithm) -> Result<T, Self::Error>;
}
impl<K, T, S> IntoSigner<T, S> for K
where
T: FromKey<K> + Signer<S>,
S: AsRef<[u8]>,
{
type Error = <T as FromKey<K>>::Error;
fn into_signer(self, alg: JsonWebSigningAlgorithm) -> Result<T, Self::Error> {
T::from_key(self, JsonWebAlgorithm::Signing(alg))
}
}