Module hmac

This module implements HMAC (Keyed-Hashing for Message Authentication) [http://www.ietf.org/rfc/rfc2104.txt].

Module provides two common interfaces for calculating HMAC. Classic method allows to process big chunks of data using limited amount of memory, while one-line method allows you to perform HMAC calculation in one line of code.

import nimcrypto

## ``Classic`` method of HMAC calculation.

var stringToHmac = "Hello World!"
var stringHmacKey = "AliceKey"
let ptrToHmac = cast[ptr byte](addr stringToHmac[0])
let ptrHmacKey = cast[ptr byte](addr stringHmacKey[0])
let toHmacLen = uint(len(stringToHmac))
let hmacKeyLen = uint(len(stringHmacKey))

# Declare context objects
var hctx1, hctx2: HMAC[sha256]
# Initalize HMAC[SHA256] contexts with key `AliceKey`.
hctx1.init(stringHmacKey)
hctx2.init(ptrHmacKey, hmacKeyLen)
# Update HMAC[SHA256] context using data `Hello World!` twice.
hctx1.update(stringToHmac)
hctx1.update(stringToHmac)
# Update HMAC[SHA256] context using data `Hello World!` twice.
hctx2.update(ptrToHmac, toHmacLen)
hctx2.update(ptrToHmac, toHmacLen)
# Print HMAC[SHA256] digest.
echo $hctx1.finish()
echo $hctx2.finish()
# Do not forget to clear contexts.
hctx1.clear()
hctx2.clear()

## ``One-line`` method of HMAC calculation.

# Print HMAC[SHA256] digest of `Hello World!Hello World!` using key
# `AliceKey`.
echo $sha256.hmac(stringHmacKey, stringToHmac & stringToHmac)

# Output to stdout must be 3 equal digests:
# 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D
# 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D
# 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D

Types

HMAC[HashType] = object
  mdctx: HashType
  opadctx: HashType
HMAC context object.

Procs

proc init[T](hmctx: var HMAC[T]; key: ptr byte; ulen: uint)

Initialize HMAC context hmctx with key using key and size ulen.

key can be nil.

proc init[T](hmctx: var HMAC[T]; key: openArray[byte]) {...}{.inline.}

Initialize HMAC context hmctx with key using key array.

key can be zero-length array.

proc init[T](hmctx: var HMAC[T]; key: openArray[char]) {...}{.inline.}

Initialize HMAC context hmctx with key using key string/array.

key can be zero-length array.

proc clear(hmctx: var HMAC)
Clear HMAC context hmctx.
proc update(hmctx: var HMAC; data: ptr byte; ulen: uint)

Update HMAC context hmctx with data pointed by data and length ulen. Repeated calls are equivalent to a single call with the concatenation of all data arguments.

data can be nil, but ulen must be 0 in such case.

proc update[T: bchar](hmctx: var HMAC; data: openArray[T]) {...}{.inline.}

Update HMAC context hmctx with data array data. Repeated calls are equivalent to a single call with the concatenation of all data arguments.

data can be zero-length array.

proc finish(hmctx: var HMAC; data: ptr byte; ulen: uint): uint
Finalize HMAC context hmctx and store calculated digest in data pointed by data and length ulen. data must be able to hold
proc finish[T: bchar](hmctx: var HMAC; data: var openArray[T]): uint {...}{.inline.}
Finalize HMAC context hmctx and store calculated digest in array data. data length must be at least hmctx.sizeDigest octets (bytes).
proc finish(hmctx: var HMAC): MDigest[HashType.bits]
Finalize HMAC context hmctx and return calculated digest as MDigest object.
proc hmac(HashType: typedesc; key: ptr byte; klen: uint; data: ptr byte; ulen: uint): MDigest[
    HashType.bits]
Perform HMAC computation with hash algorithm HashType using key key of length klen on data buffer pointed by data of length ulen.

import nimcrypto

var stringToHmac = "Hello World!"
var stringHmacKey = "AliceKey"
let data = cast[ptr byte](addr stringToHmac[0])
let datalen = uint(len(stringToHmac))
let key = cast[ptr byte](addr stringHmacKey[0])
let keylen = uint(len(stringHmacKey))
# Print HMAC[SHA256](key = "AliceKey", data = "Hello World!")
echo sha256.hmac(key, keylen, data, datalen)
# Print HMAC[SHA512](key = "AliceKey", data = "Hello World!")
echo sha512.hmac(key, keylen, data, datalen)
# Print HMAC[KECCAK256](key = "AliceKey", data = "Hello World!")
echo keccak256.hmac(key, keylen, data, datalen)
# Print HMAC[RIPEMD160](key = "AliceKey", data = "Hello World!")
echo ripemd160.hmac(key, keylen, data, datalen)

proc hmac[A, B](HashType: typedesc; key: openArray[A]; data: openArray[B];
              ostart: int = 0; ofinish: int = -1): MDigest[HashType.bits]
Perform HMAC computation with hash algorithm HashType using key key of data data, in slice [ostart, ofinish], both ostart and ofinish are inclusive.

import nimcrypto

var stringToHmac = "Hello World!"
var stringHmacKey = "AliceKey"
# Print HMAC[SHA256] digest of whole string `Hello World!` using
# key `AliceKey`.
echo sha256.hmac(stringHmacKey, stringToHmac)
# Print HMAC[SHA256] digest of `Hello` using key `AliceKey`.
echo sha256.hmac(stringHmacKey, stringToHmac, ofinish = 4)
# Print HMAC[SHA256] digest of `World!` using key `AliceKey`.
echo sha256.hmac(stringHmacKey, stringToHmac, ostart = 6)
# Print HMAC[SHA256] digest of constant `Hello` using constant key
# `AliceKey`.
echo sha256.hmac("AliceKey", "Hello")
# Print HMAC[SHA256] digest of constant `World!` using constant key
# `AliceKey`
echo sha256.hmac("AliceKey", "World!")

Templates

template sizeBlock(h: HMAC[Sha2Context]): uint
Size of processing block in octets (bytes), while perform HMAC operation using SHA2 algorithms.
template sizeBlock(h: HMAC[RipemdContext]): uint
Size of processing block in octets (bytes), while perform HMAC operation using RIPEMD algorithms.
template sizeBlock(h: HMAC[KeccakContext]): uint
Size of processing block in octets (bytes), while perform HMAC operation using KECCAK/SHA3/SHAKE algorithms.
template sizeBlock(h: HMAC[Blake2Context]): uint
Size of processing block in octets (bytes), while perform HMAC operation using BLAKE2b/BLAKE2s algorithms.
template sizeDigest(h: HMAC[Sha2Context]): uint
Size of HMAC digest in octets (bytes) using SHA2 algorithms.
template sizeDigest(h: HMAC[RipemdContext]): uint
Size of HMAC digest in octets (bytes) using RIPEMD algorithms.
template sizeDigest(h: HMAC[KeccakContext]): uint
Size of HMAC digest in octets (bytes) using KECCAK/SHA3/SHAKE algorithms.
template sizeDigest(h: HMAC[Blake2Context]): uint
Size of HMAC digest in octets (bytes) using BLAKE2b/BLAKE2s algorithms.