parity_crypto/hmac/
mod.rs1use std::marker::PhantomData;
10use std::ops::Deref;
11
12use digest::generic_array::{
13 typenum::{U32, U64},
14 GenericArray,
15};
16use hmac::{Hmac, Mac as _, NewMac as _};
17use zeroize::Zeroize;
18
19use crate::digest::{Sha256, Sha512};
20
21#[derive(Debug)]
23pub struct Signature<T>(HashInner, PhantomData<T>);
24
25#[derive(Debug)]
26enum HashInner {
27 Sha256(GenericArray<u8, U32>),
28 Sha512(GenericArray<u8, U64>),
29}
30
31impl<T> Deref for Signature<T> {
32 type Target = [u8];
33
34 fn deref(&self) -> &Self::Target {
35 match &self.0 {
36 HashInner::Sha256(a) => a.as_slice(),
37 HashInner::Sha512(a) => a.as_slice(),
38 }
39 }
40}
41
42pub struct SigKey<T>(KeyInner, PhantomData<T>);
44
45#[derive(PartialEq)]
46struct DisposableBox(Box<[u8]>);
48
49impl std::fmt::Debug for DisposableBox {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 write!(f, "{:?}", &self.0.as_ref())
52 }
53}
54
55impl DisposableBox {
56 fn from_slice(data: &[u8]) -> Self {
57 Self(data.to_vec().into_boxed_slice())
58 }
59}
60
61impl Drop for DisposableBox {
62 fn drop(&mut self) {
63 self.0.zeroize()
64 }
65}
66
67#[derive(Debug, PartialEq)]
68enum KeyInner {
69 Sha256(DisposableBox),
70 Sha512(DisposableBox),
71}
72
73impl SigKey<Sha256> {
74 pub fn sha256(key: &[u8]) -> SigKey<Sha256> {
75 SigKey(KeyInner::Sha256(DisposableBox::from_slice(key)), PhantomData)
76 }
77}
78
79impl SigKey<Sha512> {
80 pub fn sha512(key: &[u8]) -> SigKey<Sha512> {
81 SigKey(KeyInner::Sha512(DisposableBox::from_slice(key)), PhantomData)
82 }
83}
84
85pub fn sign<T>(k: &SigKey<T>, data: &[u8]) -> Signature<T> {
87 let mut signer = Signer::with(k);
88 signer.update(data);
89 signer.sign()
90}
91
92pub struct Signer<T>(SignerInner, PhantomData<T>);
94
95enum SignerInner {
96 Sha256(Hmac<sha2::Sha256>),
97 Sha512(Hmac<sha2::Sha512>),
98}
99
100impl<T> Signer<T> {
101 pub fn with(key: &SigKey<T>) -> Signer<T> {
102 match &key.0 {
103 KeyInner::Sha256(key_bytes) => Signer(
104 SignerInner::Sha256(Hmac::<sha2::Sha256>::new_varkey(&key_bytes.0).expect("always returns Ok; qed")),
105 PhantomData,
106 ),
107 KeyInner::Sha512(key_bytes) => Signer(
108 SignerInner::Sha512(Hmac::<sha2::Sha512>::new_varkey(&key_bytes.0).expect("always returns Ok; qed")),
109 PhantomData,
110 ),
111 }
112 }
113
114 pub fn update(&mut self, data: &[u8]) {
115 match &mut self.0 {
116 SignerInner::Sha256(hmac) => hmac.update(data),
117 SignerInner::Sha512(hmac) => hmac.update(data),
118 }
119 }
120
121 pub fn sign(self) -> Signature<T> {
122 match self.0 {
123 SignerInner::Sha256(hmac) => Signature(HashInner::Sha256(hmac.finalize().into_bytes()), PhantomData),
124 SignerInner::Sha512(hmac) => Signature(HashInner::Sha512(hmac.finalize().into_bytes()), PhantomData),
125 }
126 }
127}
128
129pub struct VerifyKey<T>(KeyInner, PhantomData<T>);
131
132impl VerifyKey<Sha256> {
133 pub fn sha256(key: &[u8]) -> VerifyKey<Sha256> {
134 VerifyKey(KeyInner::Sha256(DisposableBox::from_slice(key)), PhantomData)
135 }
136}
137
138impl VerifyKey<Sha512> {
139 pub fn sha512(key: &[u8]) -> VerifyKey<Sha512> {
140 VerifyKey(KeyInner::Sha512(DisposableBox::from_slice(key)), PhantomData)
141 }
142}
143
144pub fn verify<T>(key: &VerifyKey<T>, data: &[u8], sig: &[u8]) -> bool {
146 match &key.0 {
147 KeyInner::Sha256(key_bytes) => {
148 let mut ctx = Hmac::<sha2::Sha256>::new_varkey(&key_bytes.0).expect("always returns Ok; qed");
149 ctx.update(data);
150 ctx.verify(sig).is_ok()
151 }
152 KeyInner::Sha512(key_bytes) => {
153 let mut ctx = Hmac::<sha2::Sha512>::new_varkey(&key_bytes.0).expect("always returns Ok; qed");
154 ctx.update(data);
155 ctx.verify(sig).is_ok()
156 }
157 }
158}
159
160#[cfg(test)]
161mod test;