---
title: digest.hmac_sha1
summary: null
url: >-
  https://www.fastly.com/documentation/reference/vcl/functions/cryptographic/digest-hmac-sha1
---

```
STRING digest.hmac_sha1(STRING key, STRING s)
```

**Available in:** all 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

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

To verify this output using OpenSSL:

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

### RFC 2104 test vector

```vcl
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:

```vcl
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:

```vcl
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()`:

```vcl
# 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:

```vcl
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.
