CRYPTO_SHA512(3MONOCYPHER)
πΈ NAME πΈ
Okay bestie, welcome to the 3monocypher manual page (LOCAL section, yup). This is the whole crypto_sha512 crew: crypto_sha512, crypto_sha512_init, crypto_sha512_update, crypto_sha512_final crypto_sha512_hmac, crypto_sha512_hmac_init, crypto_sha512_hmac_update, crypto_sha512_hmac_final, crypto_sha512_hkdf, crypto_sha512_hkdf_expand β and they handle hashing, message authentication, and key derivation with SHA-512. β¨
β¨ SYNOPSIS β¨
#include <monocypher-ed25519.h>
void
crypto_sha512(uint8_t hash[64], const uint8_t *message,
size_t message_size);
void
crypto_sha512_init(crypto_sha512_ctx *ctx);
void
crypto_sha512_update(crypto_sha512_ctx *ctx, const uint8_t *message,
size_t message_size);
void
crypto_sha512_final(crypto_sha512_ctx *ctx, uint8_t hash[64]);
void
crypto_sha512_hmac(uint8_t hmac[64], const uint8_t *key,
size_t key_size, const uint8_t *message, size_t message_size);
void
crypto_sha512_hmac_init(crypto_sha512_hmac_ctx *ctx, const uint8_t *key,
size_t key_size);
void
crypto_sha512_hmac_update(crypto_sha512_hmac_ctx *ctx,
const uint8_t *message, size_t message_size);
void
crypto_sha512_hmac_final(crypto_sha512_hmac_ctx *ctx, uint8_t hmac[64]);
void
crypto_sha512_hkdf(uint8_t *okm, size_t okm_size, const uint8_t *ikm,
size_t ikm_size, const uint8_t *salt, size_t salt_size,
const uint8_t *info, size_t info_size);
void
crypto_sha512_hkdf_expand(uint8_t *okm, size_t okm_size,
const uint8_t *prk, size_t prk_size, const uint8_t *info,
size_t info_size);
void
π DESCRIPTION π
π Hashing π
crypto_sha512(), crypto_sha512_init(), crypto_sha512_update(), and crypto_sha512_final() implement SHA-512, a cryptographically secure hash. They exist so you can be compatible with other cryptographic systems. But lowkey, itβs generally recommended to use crypto_blake2b(3monocypher) instead, because it performs faster on x86_64 CPUs and lacks many of the pitfalls of SHA-512. π
β οΈ SHA-512 itself is not suitable for hashing passwords and deriving keys from them. Use the crypto_argon2(3monocypher) family of functions for that purpose instead. No cap.
π SHA-512 is vulnerable to length extension attacks, so it cannot directly be used for message authentication codes (MAC), nor as a random oracle. For those, use the crypto_sha512_hmac() family of functions instead.
The arguments are:
hashβ the output SHA-512 hash; itβs always 64 bytes long.messageβ the message to hash. It may beNULLifmessage_sizeis0.message_sizeβ length ofmessage, in bytes.
π Message authentication codes π
crypto_sha512_hmac(), crypto_sha512_hmac_init(), crypto_sha512_hmac_update(), and crypto_sha512_hmac_final() implement HMAC with SHA-512, and can be used for message authentication codes or as a random oracle. Theyβre here for compatibility with other cryptographic systems. Itβs generally recommended to use keyed crypto_blake2b(3monocypher) instead, since it performs faster on x86_64 CPUs. π¦
The arguments are:
hmacβ the output MAC, which is always 64 bytes long. When used as a message authentication code, it can safely be truncated down to 16 bytes. To avoid timing attacks, usecrypto_verify16(3monocypher),crypto_verify32(3monocypher), orcrypto_verify64(3monocypher)to compare (possibly truncated) MACs. πkeyβ some secret key. When itβs uniformly random, one cannot predict the final HMAC without it. Users may want to wipe the key withcrypto_wipe(3monocypher)once they are done with it. Also stands for thesaltargument when usingcrypto_sha512_hmac()for HKDF extraction.key_sizeβ length ofkey, in bytes.32is a good default. Keys longer than128bytes will be reduced to64bytes by hashing the key with SHA-512.messageβ the message to compute the HMAC for. May beNULLifmessage_sizeis0. Also stands for theikmargument when usingcrypto_sha512_hmac()for HKDF extraction.message_sizeβ length ofmessage, in bytes.
π¦ Key derivation π¦
crypto_sha512_hkdf() and crypto_sha512_hkdf_expand() implement HKDF key derivation on top of SHA-512. HKDF is divided in two phases: first we extract entropy from some input key material to produce a pseudo-random key (PRK) which is indistinguishable from uniform random bytes. Then we expand that pseudo-random key into a longer stream of independent random bytes called output key material (OKM). π
HKDF extraction is already implemented in crypto_sha512_hmac(), so there is no dedicated function. HKDF expansion is implemented by crypto_sha512_hkdf_expand(). Note that expansion works with any uniformly random key β the PRK does not have to come from crypto_sha512_hmac() specifically. Likewise, if compatibility or standard compliance is not an issue, expansion could in principle use any pseudo-random function, such as crypto_chacha20_djb(3monocypher).
crypto_sha512_hkdf() is a convenience function that performs crypto_sha512_hmac() and crypto_sha512_hkdf_expand().
π Contrary to most functions in Monocypher, the inputs ofcrypto_sha512_hkdf()andcrypto_sha512_hkdf_expand()cannot overlap with their output. The unlimited size of both inputs and output prevents us from from caching one of them in a local variable. (Yes, βfrom fromβ is in the original β keeping the lore exact.)
The arguments are:
okmβ the output key material of HKDF or HKDF expansion, usable as a symmetric encryption key, or set thereof.okm_sizeβ length ofokm, in bytes. Must not exceed16320.ikmβ input key material containing enough secret entropy to derive uniformly random keys from, such as the shared secret of a key exchange performed withcrypto_x25519(3monocypher). Passwords do not contain enough entropy to be used as input key material. Hash them withcrypto_argon2(3monocypher)instead.ikm_sizeβ length ofikm, in bytes.prkβ pseudo-random key. Typically comes from an HKDF extraction withcrypto_sha512_hmac(), but can come from any source as long as it is uniformly random. Should be at least32bytes long.prk_sizeβ length ofprk, in bytes.saltβ an optional random salt, used to increase the security of the output key materialokmin some settings. Can beNULLifsalt_sizeis zero. Otherwise it should contain at least16bytes.salt_sizeβ length ofsalt, in bytes.infoβ optional domain separation string for key derivation. Can beNULLifinfo_sizeis zero.info_sizeβ length ofinfo, in bytes.
π§ Incremental interface π§
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
crypto_sha512_init()orcrypto_sha512_hmac_init(), which sets up a context with the hashing parameters; - update with
crypto_sha512_update()orcrypto_sha512_hmac_update(), which hashes the message chunk by chunk and keeps the intermediary result in the context; - and finalisation with
crypto_sha512_final()orcrypto_sha512_hmac_final(), which produces the final hash. Thecrypto_sha512_ctxorcrypto_sha512_hmac_ctxis automatically wiped upon finalisation.
crypto_sha512() is a convenience function that performs crypto_sha512_init(), crypto_sha512_update(), and crypto_sha512_final().
crypto_sha512_hmac() is a convenience function that performs crypto_sha512_hmac_init(), crypto_sha512_hmac_update(), and crypto_sha512_hmac_final().
β RETURN VALUES β
These functions return nothing. π
β¨ EXAMPLES β¨
Okay bestie, this is the part where it all clicks. Every single one of these is a real, copy-pasteable vibe β I'm not changing a character of the code, so you can trust it fr fr. π
Hashing a message all at once πΈ
If you've got the whole thing in your hand already, this is your moment β one call, done, iconic:
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 π¦
Big message? Don't panic, just feed it in chunks. Init, update a bunch, final. That's the whole storyline:
uint8_t hash [ 64]; /* Output hash (64 bytes) */
uint8_t message[500] = {1}; /* Message to hash */
crypto_sha512_ctx ctx;
crypto_sha512_init(&ctx);
for (size_t i = 0; i < 500; i += 100) {
crypto_sha512_update(&ctx, message + i, 100);
}
crypto_sha512_final(&ctx, hash);
Computing a message authentication code all at once π₯
Now we're doing HMAC β same "all at once" energy, but with a key. The key gets arc4random_buf()'d (32 bytes of randomness, slay), and then β important β we wipe the secrets when we're done. Not me being dramatic, this is just good hygiene:
uint8_t hash [64]; /* Output hash */
uint8_t key [32]; /* Key */
uint8_t message[10] = "Lorem ipsu"; /* Message to authenticate */
arc4random_buf(key, 32);
crypto_sha512_hmac(hash, key, 32, message, 10);
/* Wipe secrets if they are no longer needed */
crypto_wipe(message, 10);
crypto_wipe(key, 32);
Computing a message authentication code incrementally π
Same deal, but streamed. Notice the flex here: the key gets wiped right after init, because the context already has what it needs. Then each chunk gets wiped as we go. Careful, considerate, main character energy:
uint8_t hash [64]; /* Output hash */
uint8_t key [32]; /* Key */
uint8_t message[500] = {1}; /* Message to authenticate */
crypto_sha512_hmac_ctx ctx;
arc4random_buf(key, 32);
crypto_sha512_hmac_init(&ctx, key, 32);
/* Wipe the key */
crypto_wipe(key, 32);
for (size_t i = 0; i < 500; i += 100) {
crypto_sha512_hmac_update(&ctx, message + i, 100);
/* Wipe secrets if they are no longer needed */
crypto_wipe(message + i, 100);
}
crypto_sha512_hmac_final(&ctx, hash);
Deriving keys from input key material π
HKDF time, bestie. You give it input key material (ikm), a random salt, and a little info string for domain separation, and it hands you back a big ol' okm you can slice into separate keys. One call, four keys, we love efficiency:
uint8_t okm[128]; /* Output random keys */
uint8_t ikm [96]; /* Input key material */
uint8_t salt[16]; /* Random salt */
uint8_t info[11] = "Lorem ipsum"; /* Domain separation */
arc4random_buf(salt, sizeof(salt));
crypto_sha512_hkdf(okm, sizeof(okm),
ikm, sizeof(ikm),
salt, sizeof(salt),
info, sizeof(info));
uint8_t *key1 = okm + 0;
uint8_t *key2 = okm + 32;
uint8_t *key3 = okm + 64;
uint8_t *key4 = okm + 96;
/* Wipe okm when it is no longer needed */
π Don't forget that last comment, okay? /* Wipe okm when it is no longer needed */ β those are secrets you're holding.
Deriving keys from several bits of input key material π
This one's the full two-step serve: Extract, then Expand. You're mixing several pieces (Alice's public X25519 key, Bob's public X25519 key, their shared secret) into a prk, then expanding that into your okm. Chef's kiss:
uint8_t okm [96]; /* Output secret keys */
uint8_t pk_a[32]; /* Alice public X25519 key */
uint8_t pk_b[32]; /* Bob public X25519 key */
uint8_t skab[32]; /* Alice & bob shared secret */
uint8_t ikm [96]; /* Input key material */
uint8_t salt[16]; /* Random salt */
uint8_t info[ 6] = "X25519"; /* Domain separation */
arc4random_buf(salt, sizeof(salt));
/* Extract */
uint8_t prk[64]; /* pseudo-random key */
crypto_sha512_hmac_ctx ctx;
crypto_sha512_hmac_init (&ctx, salt, sizeof(salt));
crypto_sha512_hmac_update(&ctx, pk_a, sizeof(pk_a));
crypto_sha512_hmac_update(&ctx, pk_b, sizeof(pk_b));
crypto_sha512_hmac_update(&ctx, skab, sizeof(skab));
crypto_sha512_hmac_final (&ctx, prk);
/* Expand */
crypto_sha512_hkdf_expand(okm, sizeof(okm),
prk, sizeof(prk),
info, sizeof(info));
uint8_t *key1 = okm + 0;
uint8_t *key2 = okm + 32;
uint8_t *key3 = okm + 64;
/* Wipe okm when it is no longer needed */
π SEE ALSO π
Go read these next, they're all in the family:
crypto_blake2b(3monocypher)crypto_aead_lock(3monocypher)crypto_poly1305(3monocypher)intro(3monocypher)
π STANDARDS π
Here's the receipts, ngl β these functions implement SHA-512, HMAC with SHA-512, and HKDF with SHA-512.
- HMAC and SHA-512 are described in RFC 6234.
- SHA-512 is also described in the Federal Information Processing Standard (FIPS) 180-4.
- HMAC is also described in FIPS 198-1.
- HKDF is described in RFC 5869.
π°οΈ HISTORY π°οΈ
Storytime, bestie. π
The crypto_sha512(), crypto_sha512_init(), crypto_sha512_update(), and crypto_sha512_final() functions first appeared in Monocypher 0.3, but they were not intended for use outside Monocypher itself and thus went undocumented. They became part of the official API in Monocypher 3.0.0.
The crypto_hmac_sha512(), crypto_hmac_sha512_init(), crypto_hmac_sha512_update(), and crypto_hmac_sha512_final() functions first appeared in Monocypher 3.0.0, then got renamed to crypto_sha512_hmac(), crypto_sha512_hmac_init(), crypto_sha512_hmac_update(), and crypto_sha512_hmac_final() in Monocypher 4.0.0.
crypto_sha512_hkdf() and crypto_sha512_hkdf_expand() were added in Monocypher 4.0.0.
β οΈ 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. Like, actually check them. Please.
π SECURITY CONSIDERATIONS π
Okay this part matters a lot, so listen up. π«Ά
SHA-512 is a general-purpose cryptographic hash function β which means it is not suited for hashing passwords and deriving cryptographic keys from passwords. Why? Because 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. And since passwords tend to be simple, it's important to artificially slow attackers down by using especially computationally difficult hashing algorithms. That's exactly why Monocypher provides crypto_argon2(3monocypher) for password hashing and deriving keys from passwords. Use that one for passwords, bestie. π
And one more thing β while HKDF and HMAC are proper key derivation functions (KDF), the HKDF expand step alone is not. It's a pseudo-random function (PRF) that only works with a uniformly random key. You can't just feed it regular (non-uniform) input key material without making unusually strong assumptions about the security of HMAC. So don't do that. π
That's the whole page, babes β source/version is Debian, dated February 25, 2023, and this was CRYPTO_SHA512(3MONOCYPHER). Go forth and hash responsibly. ππ
π¦ where this page comes from
- nixpkgs unstable: monocypher 4.0.3
- π the page's license: BSD-2-Clause OR CC0-1.0
- Copyright (c) 2019-2020, 2023 Fabio Scotoni
- Copyright (c) 2023 Loup Vaillant
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms