digest.hmac_sha256_base64
Available inall subroutines.
Returns the HMAC-SHA256 of message using key, encoded as a Base64 string.
Parameters
| Parameter | Type | Description |
|---|---|---|
key | STRING | The secret key for HMAC computation |
message | STRING | The message to authenticate |
The key is used directly as the HMAC key. For keys longer than 64 bytes (the SHA-256 block size), the key is first hashed with SHA-256 before use, as specified in RFC 2104.
Return value
Returns a 44-character Base64-encoded string representing the 256-bit (32-byte) HMAC, using standard Base64 encoding (RFC 4648 Section 4) with padding.
Example output: CV1aIf5tBkbbIj/fPeZDa7jfsvqwtRZ37PZEH89fKmc=
If key is empty or not set, the function returns an empty string (not set).
Base64 encoding
This function uses standard Base64 encoding as defined in RFC 4648 Section 4:
| Property | Value |
|---|---|
| Alphabet | A-Za-z0-9+/ |
| Padding | = (always used) |
For URL-safe Base64 output, apply digest.base64url_nopad to convert the result, or compute the hex version and convert with bin.hex_to_base64url_nopad().
Examples
Basic usage
declare local var.hmac STRING;set var.hmac = digest.hmac_sha256_base64("secret-key", "hello world");# Result: CV1aIf5tBkbbIj/fPeZDa7jfsvqwtRZ37PZEH89fKmc=To verify this output using OpenSSL:
$ echo -n "hello world" | openssl dgst -sha256 -hmac "secret-key" -binary | openssl base64CV1aIf5tBkbbIj/fPeZDa7jfsvqwtRZ37PZEH89fKmc=Signing for an API that expects Base64 signatures
Many APIs expect Base64-encoded HMAC signatures:
sub vcl_recv { declare local var.string_to_sign STRING; declare local var.signature STRING; declare local var.api_secret STRING;
set var.api_secret = table.lookup(api_keys, "service-secret"); if (var.api_secret == "") { error 500 "API secret not configured"; }
set var.string_to_sign = req.http.Date + "\n" + req.url.path; set var.signature = digest.hmac_sha256_base64(var.api_secret, var.string_to_sign);
set req.http.Authorization = "Signature " + var.signature;}Verifying a webhook with Base64 signature
sub vcl_recv { declare local var.expected_sig STRING; declare local var.secret STRING;
set var.secret = table.lookup(webhook_secrets, "stripe"); if (var.secret == "") { error 500 "Webhook secret not configured"; }
set var.expected_sig = digest.hmac_sha256_base64(var.secret, req.body);
# Use constant-time comparison to prevent timing attacks if (!digest.secure_is_equal(var.expected_sig, req.http.Stripe-Signature)) { error 401 "Invalid signature"; }}Converting to URL-safe Base64
If you need URL-safe Base64 without padding (common in JWTs and URLs):
declare local var.hmac_b64 STRING;declare local var.hmac_b64url STRING;
set var.hmac_b64 = digest.hmac_sha256_base64("secret-key", "hello world");# Result: CV1aIf5tBkbbIj/fPeZDa7jfsvqwtRZ37PZEH89fKmc=
# Convert + to -, / to _, and remove paddingset var.hmac_b64url = regsuball(regsuball(var.hmac_b64, "\+", "-"), "/", "_");set var.hmac_b64url = regsub(var.hmac_b64url, "=+$", "");# Result: CV1aIf5tBkbbIj_fPeZDa7jfsvqwtRZ37PZEH89fKmcComparison with hex output
| Function | Output | Length |
|---|---|---|
digest.hmac_sha256 | 0x095d5a21fe6d0646db223fdf3de6436bb8dfb2fab0b51677ecf6441fcf5f2a67 | 66 chars |
digest.hmac_sha256_base64 | CV1aIf5tBkbbIj/fPeZDa7jfsvqwtRZ37PZEH89fKmc= | 44 chars |
Base64 encoding is more compact (44 characters vs 66 for hex) and is often required by APIs and protocols.
Security considerations
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:
# CORRECT - constant-time comparisonif (digest.secure_is_equal(var.computed_hmac, req.http.X-Signature)) { ... }Validate keys before use
Always check that key lookups succeed:
declare local var.key STRING;set var.key = table.lookup(secrets, "api-key");if (var.key == "") { error 500 "API key not found";}Related content
digest.hmac_sha256- Returns hex-encoded output with0xprefix.digest.hmac_sha512_base64- HMAC-SHA512 with Base64 output.digest.hmac_sha1_base64- HMAC-SHA1 with Base64 output (legacy).digest.secure_is_equal- Constant-time string comparison.
Try it out
digest.hmac_sha256_base64 is used in the following code examples. Examples apply VCL to real-world use cases and can be deployed as they are, or adapted for your own service. See the full list of code examples for more inspiration.
Click RUN on a sample below to provision a Fastly service, execute the code on Fastly, and see how the function behaves.
Authenticate JSON Web Tokens at the edge
Decode the popular JWT format to verify user session tokens before forwarding trusted authentication data to your origin.