Skip to main content

Detect tampered signed values

When you need to ensure that a piece of data has not been modified by a third party, itsdangerous provides the Signer class to create and verify cryptographic signatures. If a signed value is tampered with—even by a single byte—the verification process fails, preventing the application from processing corrupted or malicious data.

The Signer.sign method appends a signature to the original bytes, separated by a delimiter (defaulting to .). To verify the data, Signer.unsign checks the signature against the payload. If the signature does not match the data, itsdangerous raises a BadSignature exception. This exception includes a payload attribute, which contains the original data that failed the signature check, allowing for inspection if necessary.

from itsdangerous import BadSignature, Signer

# Initialize the Signer with a fixed secret key
signer = Signer(b"secret-key")
original_data = b"my-secure-data"

# Sign the data to produce a signed value
signed_value = signer.sign(original_data)

# Verify the unchanged value with unsign
unsigned_data = signer.unsign(signed_value)
assert unsigned_data == original_data

# Tamper with the signed value by changing one byte
tampered_value = signed_value[:-1] + (b"a" if signed_value[-1:] != b"a" else b"b")

# Prove that unsign raises itsdangerous.BadSignature for tampered data
try:
signer.unsign(tampered_value)
except BadSignature as e:
# The exception provides access to the payload that failed verification
assert e.payload == original_data

Internally, Signer.unsign splits the signed value using the configured separator (accessible via signer.sep). It then uses Signer.verify_signature to compare the provided signature against a newly generated signature of the payload. This verification uses hmac.compare_digest to prevent timing attacks. If the comparison fails, Signer.unsign constructs and raises the BadSignature exception defined in itsdangerous.exc.