use digest::generic_array::typenum;
use rand_core::CryptoRngCore;
use serde::{Deserialize, Serialize};
use crate::session::{SessionParameters, WireFormat};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TestSigner(u8);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TestVerifier(u8);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TestSignature {
signed_by: u8,
randomness: u64,
}
impl TestSigner {
pub fn new(id: u8) -> Self {
Self(id)
}
}
impl<D: digest::Digest> signature::RandomizedDigestSigner<D, TestSignature> for TestSigner {
fn try_sign_digest_with_rng(
&self,
rng: &mut impl CryptoRngCore,
_digest: D,
) -> Result<TestSignature, signature::Error> {
Ok(TestSignature {
signed_by: self.0,
randomness: rng.next_u64(),
})
}
}
impl signature::Keypair for TestSigner {
type VerifyingKey = TestVerifier;
fn verifying_key(&self) -> Self::VerifyingKey {
TestVerifier(self.0)
}
}
impl<D: digest::Digest> signature::DigestVerifier<D, TestSignature> for TestVerifier {
fn verify_digest(&self, _digest: D, signature: &TestSignature) -> Result<(), signature::Error> {
if self.0 == signature.signed_by {
Ok(())
} else {
Err(signature::Error::new())
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct TestHasher {
cursor: usize,
buffer: digest::Output<Self>,
}
impl digest::HashMarker for TestHasher {}
impl digest::Update for TestHasher {
fn update(&mut self, data: &[u8]) {
for byte in data {
*self.buffer.get_mut(self.cursor).expect("index within bounds") ^= byte;
self.cursor = (self.cursor + 1) % self.buffer.len();
}
}
}
impl digest::FixedOutput for TestHasher {
fn finalize_into(self, out: &mut digest::Output<Self>) {
AsMut::<[u8]>::as_mut(out).copy_from_slice(&self.buffer)
}
}
impl digest::OutputSizeUser for TestHasher {
type OutputSize = typenum::U32;
}
#[derive(Debug, Clone, Copy)]
pub struct TestSessionParams<S>(core::marker::PhantomData<S>);
impl<F: WireFormat> SessionParameters for TestSessionParams<F> {
type Signer = TestSigner;
type Verifier = TestVerifier;
type Signature = TestSignature;
type Digest = TestHasher;
type WireFormat = F;
}
#[cfg(test)]
mod tests {
use impls::impls;
use super::TestHasher;
#[test]
fn test_hasher_bounds() {
assert!(impls!(TestHasher: digest::Digest));
}
}