v2 / vlib / crypto / hmac / hmac.v
38 lines · 34 sloc · 1.16 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1// HMAC: Keyed-Hashing for Message Authentication implemented in v
2// implementation based on https://tools.ietf.org/html/rfc2104
3module hmac
4
5import crypto.internal.subtle
6
7// new returns a HMAC byte array, depending on the hash algorithm used.
8pub fn new(key []u8, data []u8, hash_func fn ([]u8) []u8, blocksize int) []u8 {
9 mut inner := []u8{len: blocksize, init: 0x36}
10 mut outer := []u8{len: blocksize, init: 0x5C}
11
12 mut b_key := []u8{}
13 if key.len <= blocksize {
14 b_key =
15 key.clone() // TODO: remove .clone() once https://github.com/vlang/v/issues/6604 gets fixed
16 } else {
17 b_key = hash_func(key)
18 }
19 if b_key.len > blocksize {
20 b_key = b_key[..blocksize].clone()
21 }
22 for i, b in b_key {
23 inner[i] = b ^ 0x36
24 outer[i] = b ^ 0x5c
25 }
26 inner << data
27 inner_hash := hash_func(inner)
28 outer << inner_hash
29 digest := hash_func(outer)
30 return digest
31}
32
33// equal compares 2 MACs for equality, without leaking timing info.
34// Note: if the lengths of the 2 MACs are different, probably a completely different
35// hash function was used to generate them => no useful timing information.
36pub fn equal(mac1 []u8, mac2 []u8) bool {
37 return subtle.constant_time_compare(mac1, mac2) == 1
38}
39