Boring crypto that simply works

cryptographic hashing with the SHA-512 algorithm

#include <monocypher-ed25519.h>

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

crypto_sha512_init(crypto_sha512_ctx *ctx);

crypto_sha512_update(crypto_sha512_ctx *ctx, const uint8_t *message, size_t message_size);

crypto_sha512_final(crypto_sha512_ctx *ctx, uint8_t hash[64]);

SHA-512 is a cryptographically secure hash, provided to enable compatibility with other cryptographic systems. It is generally recommended to use crypto_blake2b() instead, as it both performs faster on x86_64 CPUs and lacks many of the pitfalls of SHA-512.

Note that SHA-512 itself is not suitable for hashing passwords and deriving keys from them; use the crypto_argon2i() family of functions for that purpose instead.

SHA-512 is ; using it as a message authentication code (MAC) algorithm or keyed hash requires precautions. The crypto_hmac_sha512() family of functions provides HMAC with SHA-512. Use crypto_verify64() to compare MACs created this way.

The arguments are:

The output hash, which is always 64-bytes long.
The message to hash. May overlap with hash. May be NULL if message_size is 0.
Length of message, in bytes.

An 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:

  • initialisation with (), which sets up a context with the hashing parameters;
  • update with (), which hashes the message chunk by chunk and keeps the intermediary result in the context;
  • and finalisation with (), which produces the final hash. The crypto_sha512_ctx is automatically wiped upon finalisation.

() is a convenience function that performs crypto_sha512_init(), crypto_sha512_update(), and crypto_sha512_final().

These functions return nothing.

Hashing a message all at once:

uint8_t hash   [64]; /* Output hash (64 bytes)          */
uint8_t message[12] = "Lorem ipsum"; /* Message to hash */
crypto_sha512(hash, message, 12);

Hashing a message incrementally:

uint8_t hash   [ 64]; /* Output hash (64 bytes) */
uint8_t message[500] = {1}; /* Message to hash  */
crypto_sha512_ctx ctx;
for (size_t i = 0; i < 500; i += 100) {
    crypto_sha512_update(&ctx, message + i, 100);
crypto_sha512_final(&ctx, hash);

crypto_blake2b(), crypto_hmac_sha512(), crypto_lock(), intro()

These functions implement SHA-512, described in RFC 6234 and the Federal Information Processing Standard (FIPS) 180-4.

The crypto_sha512(), crypto_sha512_init(), crypto_sha512_update(), and crypto_sha512_final() functions first appeared in Monocypher 0.3, but were not intended for use outside Monocypher itself and thus undocumented. They became part of the official API in Monocypher 3.0.0.

SHA-512 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 especially computationally difficult hashing algorithms. Monocypher therefore provides crypto_argon2i() for password hashing and deriving keys from passwords.

February 5, 2020 Debian