std/digest/hmac
std/digest/src/hmac.trb
Hmac, HMAC (RFC 2104) over any Hasher: SCRAM (postgres, mongodb), S3's Signature Version 4, JWT's HS256, SMTP's
CRAM-MD5. HmacSha256, HmacSha1 and HmacMd5 name the three combinations the packages after std need.
The key is folded into the hasher once, not once a round. Hmac.keyed pads the key to a block, hashes the two
pads into a fresh inner and outer hasher, and keeps only those two - never the key itself. From there, Hmac is a
hasher itself: Hmac.add feeds the message into the (already-keyed) inner hasher, and Hmac.finished closes it and
folds the result into a copy of the outer one. A round of Hmac.pbkdf2 copies the keyed Hmac - copying a value
costs its size, not its history - so 4 096 rounds hash the key's two blocks once between them, not 8 192 times.
type Hmac
type Hmac<H: Hasher>
HMAC over H, keyed once and reused: the shape of Sha256 and the rest, so it is fed the same way.
Examples
print HmacSha256.of("key".bytes(), "message".bytes()).hex()
fn keyed
static fn keyed(key: Bytes): Self
A fresh Hmac keyed with key: the key alone, folded into an inner and an outer hasher and then forgotten.
fn add
var fn add(bytes: Bytes)
Feeds the next bytes of the message.
fn finished
fn finished(): Digest
The MAC of everything added so far. self is unchanged - the inner and outer hashers are copied first - so an
Hmac keeps being fed after this, exactly as Sha256.finished leaves its hasher open.
fn of
static fn of(key: Bytes, message: Bytes): Digest
The MAC of message under key, in one call.
alias HmacSha256
type HmacSha256 = Hmac<Sha256>
HMAC-SHA-256: SCRAM-SHA-256, AWS Signature Version 4, JWT's HS256.
alias HmacSha1
type HmacSha1 = Hmac<Sha1>
HMAC-SHA-1: SCRAM-SHA-1 (mongodb), and the older signature schemes that have not moved to SHA-256.
alias HmacMd5
type HmacMd5 = Hmac<Md5>
HMAC-MD5: SMTP's CRAM-MD5, the one place HMAC still meets Md5.