HMAC(3)
π HMAC(3) β library functions manual, but make it make sense π
okay bestie so this is the HMAC(3) page from the library functions manual and it's genuinely one of those pages that looks scary and then turns out to be a whole vibe once you actually read it. we're doing message authentication codes today. hydrate first. π₯€
β¨ NAME β¨
HMAC, HMAC_CTX_new, HMAC_CTX_reset, HMAC_CTX_free, HMAC_Init_ex, HMAC_Update, HMAC_Final, HMAC_CTX_copy, HMAC_CTX_set_flags, HMAC_CTX_get_md, HMAC_size β HMAC message authentication code. that's the whole roster, no one's getting left out π
πΈ SYNOPSIS πΈ
so first of all, this whole thing lives in library βlibcryptoβ, and you get to it like this:
#include <openssl/hmac.h>
then the functions, in all their glory:
unsigned char *
HMAC(const EVP_MD *evp_md, const void *key, int key_len,
const unsigned char *d, size_t n, unsigned char *md,
unsigned int *md_len);
HMAC_CTX *
HMAC_CTX_new(void);
int
HMAC_CTX_reset(HMAC_CTX *ctx);
void
HMAC_CTX_free(HMAC_CTX *ctx);
int
HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len,
const EVP_MD *md, ENGINE *engine);
int
HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
int
HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
int
HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx);
void
HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
const EVP_MD *
HMAC_CTX_get_md(const HMAC_CTX *ctx);
size_t
HMAC_size(const HMAC_CTX *e);
copy those exactly babe, don't freestyle the signatures, that's not the assignment π
π¦ DESCRIPTION π¦
so HMAC is a MAC β that's a message authentication code β which is literally just a keyed hash function used for message authentication, built on top of a hash function. it's giving "hash but with a secret" and honestly? iconic. π
π the one-shot girlies π
HMAC() computes the message authentication code of the n bytes at d, using the hash function evp_md and the key key which is key_len bytes long.
it drops the result into md, which must have space for the output of the hash function β and that output is no more than EVP_MAX_MD_SIZE bytes, so plan accordingly bestie. the size of the output goes into md_len, unless that's NULL, in which case, fine, keep your secrets.
evp_md can be EVP_sha1(3), EVP_ripemd160(3), etc. mix and match, live your truth β¨
π the context girlies π
HMAC_CTX_new() allocates and initializes a brand new HMAC_CTX object. new context, new me.
HMAC_CTX_reset() zeroes and re-initializes ctx and its associated resources, making it suitable for new computations β like it was deleted with HMAC_CTX_free() and freshly created with HMAC_CTX_new() all over again. glow-up via reset, we love a reinvention arc π«
HMAC_CTX_free() erases the key and other data from ctx, releases any associated resources, and finally frees ctx itself. it's the goodbye tour, and it's thorough π
π when your message doesn't fit in memory π
the following functions may be used if the message is not completely stored in memory. streaming era fr fr:
HMAC_Init_ex() sets up or reuses ctx to use the hash function evp_md and the key key. either one can be NULL, in which case the existing one is reused. honestly so chill of it.
ok important detail: thectxmust have been created withHMAC_CTX_new()before the first use in this function. don't skip steps babe.
and also β if HMAC_Init_ex() is called with a NULL key but evp_md is neither NULL nor the same as the previous digest used by ctx, then an error is returned, because reuse of an existing key with a different digest is not supported. it's a compatibility thing, not a you thing.
the ENGINE *engine argument is always ignored and passing NULL is recommended. it's giving decorative. it's giving background character energy. π«₯
HMAC_Update() can be called repeatedly with chunks of the message to be authenticated (len bytes at data). feed it piece by piece, it eats π
HMAC_Final() places the message authentication code in md, which must have space for the hash function output. final answer, no takesies backsies.
HMAC_CTX_copy() copies all of the internal state from sctx into dctx. clone behavior, and we're obsessed.
HMAC_CTX_set_flags() applies the specified flags to the internal EVP_MD_CTX objects. the possible flag values EVP_MD_CTX_FLAG_* are defined in <openssl/evp.h>. go read the header, it's free β¨
HMAC_size() returns the length in bytes of the underlying hash function output. and heads up β it's implemented as a macro, so it's not a real function call, keep that in mind iykyk.
β RETURN VALUES β
vibe check on what comes back to you:
HMAC()returns a pointer to the message authentication code, orNULLif an error occurred.HMAC_CTX_new()returns a pointer to the newHMAC_CTXobject, orNULLif an error occurred.HMAC_CTX_reset(),HMAC_Init_ex(),HMAC_Update(),HMAC_Final(), andHMAC_CTX_copy()return1for success or0if an error occurred. classic binary yes/no, very demure.HMAC_CTX_get_md()returns the message digest that was previously set forctxwithHMAC_Init_ex(), orNULLif none was set.HMAC_size()returns the length in bytes of the underlying hash function output, or0on error.
π₯ SEE ALSO π₯
go read these next, bestie, they're the supporting cast:
π STANDARDS π
RFC 2104. that's it, that's the standard. periodt. π
πΈ HISTORY πΈ
the lore drop, chronological order, and yes it goes all the way back:
HMAC(),HMAC_Update(),HMAC_Final(), andHMAC_size()first appeared in SSLeay 0.9.0 and have been available since OpenBSD 2.4.HMAC_Init_ex()first appeared in OpenSSL 0.9.7 and have been available since OpenBSD 3.2.HMAC_CTX_set_flags()first appeared in OpenSSL 0.9.7f and have been available since OpenBSD 3.8.HMAC_CTX_copy()first appeared in OpenSSL 1.0.0 and has been available since OpenBSD 4.9.HMAC_CTX_new(),HMAC_CTX_reset(),HMAC_CTX_free(), andHMAC_CTX_get_md()first appeared in OpenSSL 1.1.0 and have been available since OpenBSD 6.3.
generational icons, all of them π§
π CAVEATS π
not me having to tell you this but: other implementations allowmdinHMAC()to beNULLand return a static array, which is not thread safe. so like, that's a them thing, not a here thing. do not assume. do not copy that behavior. π
that's the whole page bestie, you ate it up, no crumbs left ππ
Debian Β· June 8, 2025 Β· HMAC(3) β mwah, go authenticate something responsibly. ππ«Ά
π¦ where this page comes from
- alpine 3.24: libressl-doc 4.3.1-r0 Β· custom
- arch rolling: libressl 4.4.0-1 Β· ISC AND custom:OpenSSL
- Copyright (c) 2000-2002, 2006, 2008, 2009, 2013, 2015, 2016 The OpenSSL Project. All rights reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms