digest.hmac_sha1

STRINGdigest.hmac_sha1STRINGkeySTRINGs

Available inall subroutines.

Returns the HMAC-SHA1 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 SHA-1 block size), the key is first hashed with SHA-1 before use, as specified in RFC 2104.

Return value

Returns a 42-character string: a 0x prefix followed by 40 lowercase hexadecimal characters representing the 160-bit (20-byte) HMAC.

Example output: 0xb84b002077152646a6da921cf58121705150a967

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

Security notice

SHA-1 has known cryptographic weaknesses and is considered deprecated for new applications. While HMAC-SHA1 is not directly affected by SHA-1's collision vulnerabilities (HMAC security relies on different properties), using SHA-256 or SHA-512 is recommended for new code.

Use HMAC-SHA1 only when required for compatibility with existing systems or protocols that mandate it, such as:

  • OAuth 1.0 signature base strings.
  • Older webhook systems.
  • Legacy TOTP implementations.

For new applications, use digest.hmac_sha256 or digest.hmac_sha512 instead.

Examples

Basic usage

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

To verify this output using OpenSSL:

$ echo -n "hello world" | openssl dgst -sha1 -hmac "secret-key"
SHA1(stdin)= b84b002077152646a6da921cf58121705150a967

RFC 2104 test vector

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

OAuth 1.0 signature

OAuth 1.0 requires HMAC-SHA1 for request signing:

sub vcl_recv {
declare local var.base_string STRING;
declare local var.signing_key STRING;
declare local var.signature STRING;
# Build the signature base string (simplified example)
set var.base_string = "POST&"
+ urlencode("https://api.example.com/oauth/token") + "&"
+ urlencode("oauth_consumer_key=key123&oauth_signature_method=HMAC-SHA1&...");
# Signing key = consumer_secret&token_secret (URL-encoded, joined by &)
set var.signing_key = table.lookup(oauth_secrets, "consumer_secret") + "&"
+ table.lookup(oauth_secrets, "token_secret");
set var.signature = digest.hmac_sha1(var.signing_key, var.base_string);
}

Legacy webhook verification

Some older webhook systems use HMAC-SHA1:

sub vcl_recv {
declare local var.expected STRING;
declare local var.secret STRING;
set var.secret = table.lookup(webhook_secrets, "legacy-service");
if (var.secret == "") {
error 500 "Webhook secret not configured";
}
set var.expected = digest.hmac_sha1(var.secret, req.body);
# Use constant-time comparison
if (!digest.secure_is_equal(var.expected, req.http.X-Hub-Signature)) {
error 401 "Invalid signature";
}
}

Security considerations

Use SHA-256 for new applications

For any new integration, prefer digest.hmac_sha256:

# Recommended for new code
set var.signature = digest.hmac_sha256(var.key, var.message);
# Only use SHA-1 when required for protocol compatibility
set var.legacy_signature = digest.hmac_sha1(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";
}

Try it out

digest.hmac_sha1 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.

Create self-destructing URLs for time-limited access

Make URLs expire after a configurable period.