Monocypher

Boring crypto that simply works

Hashing

Cryptographic hashing with Blake2b.

Synopsis

#include <monocypher.h>

void crypto_blake2b(uint8_t        hash[64],
                    const uint8_t *message,
                    size_t         message_size);

void crypto_blake2b_general(
    uint8_t       *hash   , size_t  hash_size,
    const uint8_t *key    , size_t  key_size,
    const uint8_t *message, size_t  message_size);

void crypto_blake2b_init(crypto_blake2b_ctx *ctx);

void crypto_blake2b_general_init(crypto_blake2b_ctx *ctx,
                                 size_t              hash_size,
                                 const uint8_t      *key,
                                 size_t              key_size);

void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
                           const uint8_t      *message,
                           size_t              message_size);

void crypto_blake2b_final(crypto_blake2b_ctx *ctx,
                          uint8_t            *hash);

Description

BLAKE2b is a fast cryptographically secure hash, based on the ideas of Chacha20. It is faster than MD5, yet just as secure as SHA-3.

BLAKE2b is immune to length extension attacks, and as such does not require any specific precautions, such as using the HMAC algorithm.

The arguments are:

Direct interface

The direct interface has two functions, crypto_blake2b() and crypto_blake2b_general(). crypto_blake2b() is provided for convenience, and is equivalent to calling crypto_blake2b_general() with no key and a 64-byte hash.

crypto_blake2b_general() users can specify the size of the hash, and use a secret key to make the hash unpredictable—useful for message authentication codes. Even when using a key, you do not have to wipe the context struct with crypto_wipe().

Incremental interface

The incremental interface is useful for handling streams of data or large files without using too much memory. This interface uses three steps:

The invariants of the parameters are the same as for crypto_blake2b_general(). crypto_blake2b_init() is a convenience initialisation function that specifies a 64-byte hash and no key. This is considered a good default.

Return values

These functions return nothing.

Examples

Hashing a message all at once:

uint8_t hash   [ 64]; /* Output hash (64 bytes) */
uint8_t message[500]; /* Message to hash        */
crypto_blake2b(hash, message, 500);

Computing a message authentication code all at once:

uint8_t hash   [ 64]; /* Output hash  (between 1 and 64 bytes) */
uint8_t key    [ 32]; /* Optional key (between 0 and 64 bytes) */
uint8_t message[500]; /* Message to hash                       */
crypto_blake2b_general(hash, 64, key, 32, message, 500);
/* Wipe secrets if they are no longer needed */
crypto_wipe(message, 500);
crypto_wipe(key, 32);

Hashing a message incrementally:

uint8_t hash   [ 64]; /* Output hash (64 bytes) */
uint8_t message[500]; /* Message to hash        */
crypto_blake2b_ctx ctx;
crypto_blake2b_init(&ctx);
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   [ 64]; /* Output hash  (between 1 and 64 bytes) */
uint8_t key    [ 32]; /* Optional key (between 0 and 64 bytes) */
uint8_t message[500]; /* Message to hash                       */
crypto_blake2b_ctx ctx;
crypto_blake2b_general_init(&ctx, 64, key, 32);
/* Wipe the key */
crypto_wipe(key, 32);
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);

Standards

These functions implement BLAKE2b.

Caveats

Monocypher 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.