Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

hmac/
simple.rs

1use crate::utils::{IPAD, OPAD, get_der_key};
2use core::fmt;
3use digest::{
4    Digest, FixedOutput, KeyInit, MacMarker, Output, OutputSizeUser, Update,
5    common::{Block, BlockSizeUser, InvalidLength, Key, KeySizeUser},
6};
7
8/// Simplified HMAC instance able to operate over hash functions
9/// which do not expose block-level API and hash functions which
10/// process blocks lazily (e.g. BLAKE2).
11#[derive(Clone)]
12pub struct SimpleHmac<D: Digest + BlockSizeUser> {
13    digest: D,
14    opad_key: Block<D>,
15}
16
17impl<D: Digest + BlockSizeUser> KeySizeUser for SimpleHmac<D> {
18    type KeySize = D::BlockSize;
19}
20
21impl<D: Digest + BlockSizeUser> MacMarker for SimpleHmac<D> {}
22
23impl<D: Digest + BlockSizeUser> KeyInit for SimpleHmac<D> {
24    fn new(key: &Key<Self>) -> Self {
25        Self::new_from_slice(key.as_slice()).unwrap()
26    }
27
28    #[inline]
29    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
30        let mut buf = get_der_key::<D>(key);
31        buf.iter_mut().for_each(|b: &mut u8| *b ^= IPAD);
32
33        let mut digest = D::new();
34        digest.update(&buf);
35
36        buf.iter_mut().for_each(|b: &mut u8| *b ^= OPAD ^ IPAD);
37
38        Ok(Self {
39            digest,
40            opad_key: buf,
41        })
42    }
43}
44
45impl<D: Digest + BlockSizeUser> Update for SimpleHmac<D> {
46    #[inline(always)]
47    fn update(&mut self, data: &[u8]) {
48        self.digest.update(data);
49    }
50}
51
52impl<D: Digest + BlockSizeUser> OutputSizeUser for SimpleHmac<D> {
53    type OutputSize = D::OutputSize;
54}
55
56impl<D: Digest + BlockSizeUser> FixedOutput for SimpleHmac<D> {
57    fn finalize_into(self, out: &mut Output<Self>) {
58        let mut h = D::new();
59        h.update(&self.opad_key);
60        h.update(self.digest.finalize());
61        h.finalize_into(out);
62    }
63}
64
65impl<D: Digest + BlockSizeUser + fmt::Debug> fmt::Debug for SimpleHmac<D> {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        f.write_str("SimpleHmac { ... }")
68    }
69}