digest.hmac_md5

STRINGdigest.hmac_md5STRINGkeySTRINGs

Available inall subroutines.

Returns the HMAC-MD5 of message using key, as a lowercase hexadecimal string with a 0x prefix.

Parameters

ParameterTypeDescription
keySTRINGThe secret key for HMAC computation
messageSTRINGThe message to authenticate

The key is used directly as the HMAC key. For keys longer than 64 bytes (the MD5 block size), the key is first hashed with MD5 before use, as specified in RFC 2104.

Return value

Returns a 34-character string: a 0x prefix followed by 32 lowercase hexadecimal characters representing the 128-bit (16-byte) HMAC.

Example output: 0x36b89aaa72560638852703acba484b2b

If key is empty or not set, the function returns an empty string (not set).

Security

Unlike plain MD5, no practical attack breaks HMAC-MD5 as an authenticator. However, it is no longer recommended and should only be used when required for compatibility with legacy systems that cannot be upgraded.

The 128-bit output of HMAC-MD5 provides only 64 bits of security against forgery attacks (due to birthday bound considerations). Modern security standards require at least 128 bits of security, which HMAC-SHA256 provides.

Examples

Basic usage

declare local var.hmac STRING;
set var.hmac = digest.hmac_md5("secret-key", "hello world");
# Result: 0x36b89aaa72560638852703acba484b2b

To verify this output using OpenSSL:

$ echo -n "hello world" | openssl dgst -md5 -hmac "secret-key"
MD5(stdin)= 36b89aaa72560638852703acba484b2b

RFC 2104 test vector

declare local var.hmac STRING;
set var.hmac = digest.hmac_md5("key", "The quick brown fox jumps over the lazy dog");
# Result: 0x80070713463e7749b90c2dc24911e275

Security considerations

Use SHA-256 for new applications

For any new integration, use digest.hmac_sha256:

# Recommended
set var.signature = digest.hmac_sha256(var.key, var.message);
# NOT recommended - only for legacy compatibility
set var.legacy_signature = digest.hmac_md5(var.key, var.message);

Constant-time comparison

When comparing HMAC values for authentication, always use digest.secure_is_equal to prevent timing attacks. String comparison with == leaks information about which bytes matched, potentially allowing an attacker to forge valid authentication tags:

if (!digest.secure_is_equal(var.expected, var.actual)) {
error 401 "Invalid signature";
}