digest.hmac_sha1
Available inall subroutines.
Returns the HMAC-SHA1 of message using key as a lowercase hexadecimal string with a 0x prefix.
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-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: 0xb84b002077152646a6da921cf58121705150a967To verify this output using OpenSSL:
$ echo -n "hello world" | openssl dgst -sha1 -hmac "secret-key"SHA1(stdin)= b84b002077152646a6da921cf58121705150a967RFC 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: 0xde7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9OAuth 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 codeset var.signature = digest.hmac_sha256(var.key, var.message);
# Only use SHA-1 when required for protocol compatibilityset 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";}Related content
digest.hmac_sha1_base64- Returns Base64-encoded output instead of hex.digest.hmac_sha256- HMAC with SHA-256 (recommended for new code).digest.hmac_sha512- HMAC with SHA-512.digest.secure_is_equal- Constant-time string comparison.
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.