# Timing Attack via Non-Constant-Time String Comparison in HMAC Authentication

Language: Python
Severity: High
CWE: CWE-208

## Source
4

## Flow
4-5

## Sink
5

## Vulnerable Code
```python
import hmac, hashlib
def verify_iot_device_token(dev_id, provided_sig, payload, secret_key):
    raw = f"{dev_id}:{payload}".encode()
    expected_mac = hmac.new(secret_key.encode(), raw, hashlib.sha256).hexdigest()
    if provided_sig == expected_mac:
        return {"status": "authorized", "device": dev_id}
    return {"status": "denied"}
```

## Explanation

The HMAC signature is computed on line 4 using hmac.new(), but compared on line 5 using Python's built-in == operator, which performs a short-circuit lexicographic comparison. This leaks timing information: comparisons fail faster when early bytes differ, allowing an attacker to brute-force the HMAC value byte-by-byte by measuring response times. The fix is to use hmac.compare_digest() instead of ==.

## Remediation

The fix replaces the Python == operator on line 5 with hmac.compare_digest(), which performs a constant-time comparison of the two strings. This ensures that the comparison always takes the same amount of time regardless of how many bytes match, preventing an attacker from using timing side-channel analysis to brute-force the HMAC signature byte-by-byte.

## Secure Code
```python
import hmac, hashlib
def verify_iot_device_token(dev_id, provided_sig, payload, secret_key):
    raw = f"{dev_id}:{payload}".encode()
    expected_mac = hmac.new(secret_key.encode(), raw, hashlib.sha256).hexdigest()
    if hmac.compare_digest(provided_sig, expected_mac):
        return {"status": "authorized", "device": dev_id}
    return {"status": "denied"}
```
