![]() |
![]()
| ![]() |
![]()
NAME
SYNOPSIS
void
void
void
void
void
DESCRIPTIONHashing
Note that BLAKE2b itself is not suitable for hashing passwords and deriving keys from them; use the crypto_argon2(3monocypher) family of functions for that purpose instead. While BLAKE2b is immune to length
extension attacks, and as such requires fewer precautions than older hashes,
we do recommend avoiding prefix-MAC and using keyed mode with
The arguments are:
Message authentication codes
Key derivationBLAKE2b can be used to implement “key derivation functions” (KDF) very similar to HKDF. The typical parameters of a KDF are:
From these parameters, the KDF derives an arbitrary amount of independent random bytes, also called “output key material” (OKM), that can be used as regular encryption or secret keys. In practice, KDFs are often separated in two steps: “extraction” and “expansion”. The extraction step reads the IKM (and optional salt) to derive a “pseudo-random key” (PRK), which can be used either directly as a regular key, or as an input for the extraction step. The expansion step then reads the PRK (and optional info) to make the OKM. To implement KDF extraction, just call
For KDF expansion any
pseudo-random-function (PRF) can be used. You can call
Incremental interfaceAn incremental interface is provided. It is useful for handling streams of data or large files without using too much memory. This interface uses three steps:
Calling
Calling
RETURN VALUESThese functions return nothing. EXAMPLESThe following examples assume the existence of
Hashing a message all at once: uint8_t hash [64]; /* Output hash (64 bytes) */ uint8_t message[12] = "Lorem ipsum"; /* Message to hash */ crypto_blake2b(hash, sizeof(hash), message, sizeof(message)); Computing a message authentication code all at once: uint8_t hash [16]; uint8_t key [32]; uint8_t message[11] = "Lorem ipsu"; /* Message to authenticate */ arc4random_buf(key, sizeof(key)); crypto_blake2b_keyed(hash , sizeof(hash), key , sizeof(key), message, sizeof(message)); /* Wipe secrets if they are no longer needed */ crypto_wipe(message, sizeof(message)); crypto_wipe(key, sizeof(key)); Hashing a message incrementally (without a key): uint8_t hash [ 64]; /* Output hash (64 bytes) */ uint8_t message[500] = {1}; /* Message to hash */ crypto_blake2b_ctx ctx; crypto_blake2b_init(&ctx, sizeof(hash)); for (size_t i = 0; i < 500; i += 100) { crypto_blake2b_update(&ctx, message + i, 100); } crypto_blake2b_final(&ctx, hash); Computing a message authentication code incrementally: uint8_t hash [ 16]; uint8_t key [ 32]; uint8_t message[500] = {1}; /* Message to authenticate */ arc4random_buf(key, sizeof(key)); crypto_blake2b_ctx ctx; crypto_blake2b_keyed_init(&ctx, sizeof(hash), key, sizeof(key)); /* Wipe the key */ crypto_wipe(key, sizeof(key)); for (size_t i = 0; i < 500; i += 100) { crypto_blake2b_update(&ctx, message + i, 100); /* Wipe secrets if they are no longer needed */ crypto_wipe(message + i, 100); } crypto_blake2b_final(&ctx, hash); Computing key derivation with BLAKE2b and ChaCha20: void kdf(uint8_t *okm, size_t okm_size, /* unlimited */ uint8_t *ikm, size_t ikm_size, /* unlimited */ uint8_t *salt, size_t salt_size, /* <= 64 bytes */ uint8_t info[8]) /* == 8 bytes */ { /* Extract */ uint8_t prk[32]; crypto_blake2b_keyed(prk , sizeof(prk), salt, salt_size, ikm , ikm_size); /* Expand */ crypto_chacha20_djb(okm, NULL, okm_size, prk, info, 0); } Computing key derivation with BLAKE2b and XChaCha20: void xkdf(uint8_t *okm, size_t okm_size, /* unlimited */ uint8_t *ikm, size_t ikm_size, /* unlimited */ uint8_t *salt, size_t salt_size, /* <= 64 bytes */ uint8_t *info, size_t info_size) /* unlimited */ { /* Extract */ uint8_t prk[32]; crypto_blake2b_keyed(prk , sizeof(prk), salt, salt_size, ikm , ikm_size); /* Expand */ uint8_t nonce[24]; crypto_blake2b(nonce, sizeof(nonce), info, info_size); crypto_chacha20_x(okm, NULL, okm_size, prk, nonce, 0); } Computing key derivation with BLAKE2b alone (a little tedious indeed): #define MIN(a, b) ((a) < (b) ? (a) : (b)) void b2kdf(uint8_t *okm, size_t okm_size, /* unlimited */ uint8_t *ikm, size_t ikm_size, /* unlimited */ uint8_t *salt, size_t salt_size, /* <= 64 bytes */ uint8_t *info, size_t info_size) /* unlimited */ { /* Extract */ uint8_t prk[64]; crypto_blake2b_keyed(prk , sizeof(prk), salt, salt_size, ikm , ikm_size); /* Expand */ uint8_t ctr[8] = {0}; while(okm_size > 0) { size_t size = MIN(okm_size, 64); crypto_blake2b_ctx ctx; crypto_blake2b_keyed_init(&ctx, size, prk, 64); crypto_blake2b_update(&ctx, ctr, sizeof(ctr)); crypto_blake2b_update(&ctx, info, info_size); crypto_blake2b_final(&ctx, okm); okm += size; okm_size -= size; /* increment ctr */ unsigned acc = 1; for (size_t i = 0; i < sizeof(ctr); i++) { acc = ctr[i] + acc; ctr[i] = acc & 0xff; acc >>= 8; } } } SEE ALSOcrypto_x25519(3monocypher), crypto_aead_lock(3monocypher), intro(3monocypher) STANDARDSThese functions implement BLAKE2b, described in RFC 7693. HISTORYThe CAVEATSMonocypher does not perform any input validation. Any deviation from the specified input and output length ranges results in undefined behaviour. Make sure your inputs are correct. SECURITY CONSIDERATIONSBLAKE2b is a general-purpose cryptographic hash function; this means that it is not suited for hashing passwords and deriving cryptographic keys from passwords. While cryptographic keys usually have hundreds of bits of entropy, passwords are often much less complex. When storing passwords as hashes or when deriving keys from them, the goal is normally to prevent attackers from quickly iterating all possible passwords. Because passwords tend to be simple, it is important to artificially slow down attackers by using computationally difficult hashing algorithms. Monocypher therefore provides crypto_argon2(3monocypher) for password hashing and deriving keys from passwords. IMPLEMENTATION DETAILSThe core loop is unrolled by default. This speeds up BLAKE2b by about 20% on modern processors. On the other hand, this inflates the binary size by several kilobytes, and is slower on some embedded platforms. To roll the loop and generate a smaller binary, compile Monocypher with the -DBLAKE2_NO_UNROLLING option.
|