1use std::marker::PhantomData;
8
9use digest::{
10 Digest, Mac, OutputSizeUser,
11 crypto_common::BlockSizeUser,
12 generic_array::{ArrayLength, GenericArray},
13};
14use signature::{Signer, Verifier};
15use thiserror::Error;
16
17pub struct Signature<S: ArrayLength<u8>> {
18 signature: GenericArray<u8, S>,
19}
20
21impl<S: ArrayLength<u8>> PartialEq for Signature<S> {
22 fn eq(&self, other: &Self) -> bool {
23 self.signature == other.signature
24 }
25}
26
27impl<S: ArrayLength<u8>> Eq for Signature<S> {}
28
29impl<S: ArrayLength<u8>> std::fmt::Debug for Signature<S> {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 write!(f, "{:?}", self.signature)
32 }
33}
34
35impl<S: ArrayLength<u8>> Clone for Signature<S> {
36 fn clone(&self) -> Self {
37 Self {
38 signature: self.signature.clone(),
39 }
40 }
41}
42
43impl<S: ArrayLength<u8>> From<Signature<S>> for GenericArray<u8, S> {
44 fn from(val: Signature<S>) -> Self {
45 val.signature
46 }
47}
48
49impl<'a, S: ArrayLength<u8>> TryFrom<&'a [u8]> for Signature<S> {
50 type Error = InvalidLength;
51
52 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
53 if value.len() != S::to_usize() {
54 return Err(InvalidLength);
55 }
56 let mut signature = GenericArray::default();
57 signature.copy_from_slice(value);
58 Ok(Self { signature })
59 }
60}
61
62impl<S: ArrayLength<u8>> signature::SignatureEncoding for Signature<S> {
63 type Repr = GenericArray<u8, S>;
64}
65
66impl<S: ArrayLength<u8>> AsRef<[u8]> for Signature<S> {
67 fn as_ref(&self) -> &[u8] {
68 self.signature.as_ref()
69 }
70}
71
72pub struct Hmac<D> {
73 key: Vec<u8>,
74 digest: PhantomData<D>,
75}
76
77impl<D> Hmac<D> {
78 pub const fn new(key: Vec<u8>) -> Self {
79 Self {
80 key,
81 digest: PhantomData,
82 }
83 }
84}
85
86#[derive(Error, Debug)]
87#[error("invalid length")]
88pub struct InvalidLength;
89
90impl<D> From<Vec<u8>> for Hmac<D> {
91 fn from(key: Vec<u8>) -> Self {
92 Self {
93 key,
94 digest: PhantomData,
95 }
96 }
97}
98
99impl<D: Digest + BlockSizeUser>
100 Signer<Signature<<hmac::SimpleHmac<D> as OutputSizeUser>::OutputSize>> for Hmac<D>
101{
102 fn try_sign(
103 &self,
104 msg: &[u8],
105 ) -> Result<Signature<<hmac::SimpleHmac<D> as OutputSizeUser>::OutputSize>, signature::Error>
106 {
107 let mut mac = <hmac::SimpleHmac<D> as Mac>::new_from_slice(&self.key)
108 .map_err(signature::Error::from_source)?;
109 mac.update(msg);
110 let signature = mac.finalize().into_bytes();
111 Ok(Signature { signature })
112 }
113}
114
115impl<D: Digest + BlockSizeUser>
116 Verifier<Signature<<hmac::SimpleHmac<D> as OutputSizeUser>::OutputSize>> for Hmac<D>
117{
118 fn verify(
119 &self,
120 msg: &[u8],
121 signature: &Signature<<hmac::SimpleHmac<D> as OutputSizeUser>::OutputSize>,
122 ) -> Result<(), signature::Error> {
123 let new_signature = self.try_sign(msg)?;
124 if &new_signature != signature {
125 return Err(signature::Error::new());
126 }
127 Ok(())
128 }
129}