Skip to content

crypto.hmac #

HMAC: Keyed-Hashing for Message Authentication implemented in v implementation based on https://tools.ietf.org/html/rfc2104

fn equal #

fn equal(mac1 []u8, mac2 []u8) bool

equal compares 2 MACs for equality, without leaking timing info.

Note: if the lengths of the 2 MACs are different, probably a completely different hash function was used to generate them => no useful timing information.

fn new #

fn new(key []u8, data []u8, hash_func fn ([]u8) []u8, blocksize int) []u8

new returns a HMAC byte array, depending on the hash algorithm used.

fn new_hmac #

@[direct_array_access]
fn new_hmac[D](h fn () D, key []u8) &Hmac[D]

new_hmac returns an Hmac for key, using the digests returned by h, for example sha256.new, sha256.new224, sha512.new384 or sha1.new. It is ready for write.

fn (Hmac[D]) reset #

fn (mut m Hmac[D]) reset()

reset discards the message written so far, for example after an error, and starts a new one. The key is kept. sum_into already does this, so it is not needed between messages.

fn (Hmac[D]) write #

fn (mut m Hmac[D]) write(data []u8) !int

write adds data to the message. It never returns an error.

fn (Hmac[D]) sum_into #

fn (mut m Hmac[D]) sum_into(mut out []u8)

sum_into writes the HMAC of the message written since the last sum_into or reset into the first size() bytes of out, without allocating, and starts a new message. It panics if out is shorter than size().

fn (Hmac[D]) size #

fn (m &Hmac[D]) size() int

size returns the size of the HMAC in bytes, which is the size of the digest.

struct Hmac #

struct Hmac[D] {
mut:
	// inner and outer are the states after absorbing `key ^ ipad` and `key ^ opad`
	inner D
	outer D
	// work holds the message written since the last `sum_into` or `reset`
	work D
}

Hmac computes HMAC for one key and many messages. The key is processed once, in new_hmac, and after that write, sum_into and reset do not allocate. Each sum_into completes one message, and the next write starts a new one. D is the digest type of a crypto.sha1, crypto.sha256 or crypto.sha512 digest, for example &sha256.Digest. Use hmac.new for other hash functions.

The keyed states are equivalent to the key, so treat an Hmac as a secret.

Example

import crypto.hmac
import crypto.sha256

mut mac := hmac.new_hmac(sha256.new, 'key'.bytes())
mut out := []u8{len: mac.size()}
for message in ['one', 'two'] {
	mac.write(message.bytes())!
	mac.sum_into(mut out)
	assert out == hmac.new('key'.bytes(), message.bytes(), sha256.sum256, sha256.block_size)
}