# Cryptographic Timing Attack via Non-Constant-Time HMAC Comparison

Language: Python
Severity: High
CWE: CWE-208

## Source
6

## Flow
6-7-8-9

## Sink
9

## Vulnerable Code
```python
import hmac
import hashlib
from flask import request, jsonify
def verify_iot_device_token(dev_id):
    raw_secret = b'iot_master_key_2024'
    inbound_sig = request.headers.get('X-Device-Sig', '')
    payload = f'{dev_id}:{request.remote_addr}'.encode()
    expected_mac = hmac.new(raw_secret, payload, hashlib.sha256).hexdigest()
    if inbound_sig == expected_mac:
        return jsonify({'status': 'authorized', 'device': dev_id})
    return jsonify({'status': 'denied'}), 403
```

## Explanation

The untrusted HMAC signature is retrieved from the HTTP header at line 6 and compared to the expected MAC at line 9 using Python's native == operator. This performs a non-constant-time string comparison that short-circuits on the first mismatched byte, leaking timing information that allows an attacker to progressively reconstruct the valid HMAC value through statistical latency measurements.

## Remediation

The fix replaces the vulnerable == operator on line 9 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, completely eliminating the timing side-channel that would allow an attacker to progressively reconstruct the valid HMAC signature.

## Secure Code
```python
import hmac
import hashlib
from flask import request, jsonify
def verify_iot_device_token(dev_id):
    raw_secret = b'iot_master_key_2024'
    inbound_sig = request.headers.get('X-Device-Sig', '')
    payload = f'{dev_id}:{request.remote_addr}'.encode()
    expected_mac = hmac.new(raw_secret, payload, hashlib.sha256).hexdigest()
    if hmac.compare_digest(inbound_sig, expected_mac):
        return jsonify({'status': 'authorized', 'device': dev_id})
    return jsonify({'status': 'denied'}), 403
```
