chiark / gitweb /
own hmac, Digest one's key length rules are annoying
[hippotat.git] / src / utils.rs
1 // Copyright 2021 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: AGPL-3.0-or-later
3 // There is NO WARRANTY.
4
5 use crate::prelude::*;
6
7 #[ext(pub)]
8 impl<T> T where T: Debug {
9   fn to_debug(&self) -> String { format!("{:?}", self) }
10 }
11
12 #[ext(pub)]
13 impl<T,E> Result<T,E> where AE: From<E> {
14   fn dcontext<D:Debug>(self, d: D) -> anyhow::Result<T> {
15     self.map_err(|e| AE::from(e)).with_context(|| d.to_debug())
16   }
17 }
18
19 use sha2::Digest as _;
20
21 type HmacH = sha2::Sha256;
22 const HMAC_L: usize = 32;
23
24 #[throws(AE)]
25 fn token_hmac(key: &[u8], message: &[u8]) -> [u8; HMAC_L] {
26   let key = {
27     let mut padded = [0; HMAC_L];
28     if key.len() > HMAC_L {
29       padded = HmacH::digest(key).into();
30     } else {
31       padded[0.. key.len()].copy_from_slice(key);
32     }
33     padded
34   };
35   let mut ikey = key;  for k in &mut ikey { *k ^= 0x36; }
36   let mut okey = key;  for k in &mut okey { *k ^= 0x5C; }
37
38   let h1 = HmacH::new()
39     .chain(&ikey)
40     .chain(message)
41     .finalize();
42   let h2 = HmacH::new()
43     .chain(&okey)
44     .chain(h1)
45     .finalize();
46   h2.into()
47 }