HTTP Message Signatures

2.0.1 · active · verified Sat Apr 11

An implementation of the IETF HTTP Message Signatures draft standard, providing tools to sign and verify HTTP messages using various cryptographic algorithms. The current stable version is 2.0.1, with a moderate release cadence driven by specification updates and bug fixes.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to sign and verify an HTTP request using `http-message-signatures`. It involves generating a temporary RSA key pair, creating a `requests.Request` object, signing it with `HTTPSignatureKeySigner`, and then verifying the resulting message with `HTTPSignatureKeyVerifier`. This example requires `requests` and `cryptography`.

import requests
from http_message_signatures import HTTPSignatureKeySigner, HTTPSignatureKeyVerifier, algorithms
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization

# 1. Generate a dummy RSA key pair (for demonstration)
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()

# Serialize keys for signer/verifier
private_jwk = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
).decode()

public_jwk = public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
).decode()

key_id = "test-key"

# 2. Prepare an HTTP request
request = requests.Request(
    method="POST",
    url="https://example.com/data",
    headers={
        "Host": "example.com",
        "Content-Type": "application/json",
        "Date": "Tue, 20 Apr 2021 02:07:55 GMT"
    },
    data='{"message": "hello world"}'
)

# 3. Sign the request
signer = HTTPSignatureKeySigner(
    key_id=key_id,
    private_key=private_jwk,
    algorithm=algorithms.RSA_V1_5_SHA256
)
signed_request = signer.sign(request)

print("--- Signed Request Headers ---")
for k, v in signed_request.headers.items():
    print(f"{k}: {v}")

# 4. Verify the signed request (simulate receiving the request)
verifier = HTTPSignatureKeyVerifier(
    key_id=key_id,
    public_key=public_jwk,
    algorithm=algorithms.RSA_V1_5_SHA256
)

# Create a dummy requests.Response object for verification
# In a real scenario, this would be the actual received request
dummy_received_request = requests.Request(
    method=signed_request.method,
    url=signed_request.url,
    headers=signed_request.headers,
    data=signed_request.data
)

try:
    is_valid = verifier.verify(dummy_received_request)
    print(f"\nSignature is valid: {is_valid}")
except Exception as e:
    print(f"\nSignature verification failed: {e}")

view raw JSON →