http-message-signatures: An implementation of RFC 9421, the IETF HTTP Message Signatures standard¶
http-message-signatures is an implementation of the IETF RFC 9421 HTTP Message Signatures standard in Python.
Security considerations
It is recommended that you read and understand section 7 of the RFC, Security Considerations before using this library.
Installation¶
pip install http-message-signatures
Synopsis¶
import hashlib
import requests
from http_sf.compat import Dictionary
from http_message_signatures import HTTPMessageSigner, HTTPMessageVerifier, HTTPSignatureKeyResolver, algorithms
class MyHTTPSignatureKeyResolver(HTTPSignatureKeyResolver):
keys = {"my-key": b"top-secret-key"}
def resolve_public_key(self, key_id: str):
return self.keys[key_id]
def resolve_private_key(self, key_id: str):
return self.keys[key_id]
request = requests.Request('POST', 'https://example.com/foo?param=Value&Pet=dog', json={"hello": "world"})
request = request.prepare()
request.headers["Content-Digest"] = str(Dictionary({"sha-256": hashlib.sha256(request.body).digest()}))
signer = HTTPMessageSigner(signature_algorithm=algorithms.HMAC_SHA256, key_resolver=MyHTTPSignatureKeyResolver())
signer.sign(request, key_id="my-key", covered_component_ids=("@method", "@authority", "@target-uri", "content-digest"))
verifier = HTTPMessageVerifier(signature_algorithm=algorithms.HMAC_SHA256, key_resolver=MyHTTPSignatureKeyResolver())
verifier.verify(request)
Note that verifying the body content-digest is outside the scope of this package’s functionality, so it remains the caller’s responsibility. The requests-http-signature library builds upon this package to provide integrated signing and validation of the request body.
See what is signed
It is important to understand and follow the best practice rule of “See what is signed” when verifying HTTP message signatures. The gist of this rule is: if your application neglects to verify that the information it trusts is what was actually signed, the attacker can supply a valid signature but point you to malicious data that wasn’t signed by that signature. Failure to follow this rule can lead to vulnerability against signature wrapping and substitution attacks.
In http-message-signatures, you can ensure that the information signed is what you expect to be signed by only trusting the
data returned by the verify() method:
verify_results = verifier.verify(request)
This returns a list of VerifyResult s, which are namedtuple s with the following attributes:
label (str): The label for the signature
algorithm: (same as signature_algorithm above)
covered_components: A mapping of component names to their values, as covered by the signature
parameters: A mapping of signature parameters to their values, as covered by the signature
body: Always
None(the requests-http-signature package implements returning the body upon successful digest validation).
Remote and asynchronous signing¶
Use prepare() and apply() when a KMS, HSM, SSH agent, or asynchronous client holds the signing key.
prepare() builds the RFC 9421 signature base without reading a private key or modifying the message.
It accepts the signing options used by sign(), including covered components, creation and expiration times,
nonce, tag, label, and include_alg. The returned PreparedSignature contains immutable bytes and strings.
apply() writes the Signature-Input and Signature headers after the external signer returns.
This example expects an asynchronous sign_base function that signs the supplied bytes with Ed25519 and
returns the raw 64-byte signature. The client must use the private key identified by key_id:
from collections.abc import Awaitable, Callable
from http_message_signatures import HTTPMessageSigner, algorithms
async def sign_request(request, key_id: str, sign_base: Callable[[bytes], Awaitable[bytes]]):
signer = HTTPMessageSigner(signature_algorithm=algorithms.ED25519)
prepared = signer.prepare(
request,
key_id=key_id,
label="sig1",
covered_component_ids=("@method", "@authority", "@target-uri", "content-digest"),
)
signature = await sign_base(prepared.signature_base)
signer.apply(request, prepared, signature)
Populate Content-Digest from the request body before this example runs, as in the synopsis above.
The same two calls work with a synchronous signer or a signing job completed in another process.
No local key_resolver is needed. The existing sign() method still resolves a local key and performs all three
steps synchronously.
Pass prepared.signature_base to the signing algorithm as bytes, without base64 encoding or a trailing newline.
prepared.signature_params is the serialized @signature-params value; it is useful for inspecting the covered
component list and signed metadata. Do not rebuild either value yourself. The selected algorithm applies to the remote
signer even when include_alg=False; omitting the parameter does not negotiate an algorithm.
Remote clients differ in their accepted input and output formats. Configure the algorithm as specified in RFC 9421 section 3.3. Ed25519 signs the base without prehashing. For RSA and ECDSA, a client that accepts raw messages must perform the specified hashing; a client that accepts a digest must receive that digest and be configured to avoid hashing it a second time. The RSA-PSS profile uses SHA-512, MGF1 with SHA-512, and a 64-byte salt.
apply() expects raw signature bytes and performs the Structured Field base64 encoding. Decode base64 responses
from a service before calling it. ECDSA P-256 clients often return DER, while RFC 9421 requires a 64-byte concatenation
of r and s, each padded to 32 bytes. Convert DER output using the algorithm’s helper:
signer = HTTPMessageSigner(signature_algorithm=algorithms.ECDSA_P256_SHA256)
prepared = signer.prepare(request, key_id="p256-key")
# der_signature is the client's ECDSA P-256/SHA-256 signature of prepared.signature_base.
signature = algorithms.ECDSA_P256_SHA256.signature_from_der(der_signature)
signer.apply(request, prepared, signature)
Retain the prepared object and associate each remote result with its input. Use a trusted signing service and protect
queued signing input against modification and disclosure: the base contains covered header and URL values.
apply() compares the message’s current signature base with the prepared bytes and rejects changes before writing
headers. For example, changing a covered method from POST to DELETE while awaiting the signature is rejected.
Changes to uncovered values or values with the same RFC normalization are permitted. This check does not authenticate
the prepared object, verify the returned signature, or check a body against its digest. Applications must handle those
responsibilities and keep the message stable during apply() and until it is sent.
Creation and expiration times are set during preparation and are not refreshed by apply(). Allow for signing delays
when choosing expiration times; an expired result will still be rejected by a verifier. To add the result alongside
existing signatures, pass append_if_signature_exists=True to apply(). Duplicate labels or malformed existing
signature headers are rejected. By default it replaces existing signature headers, just like sign().
Structured Field serialization¶
Use the sf component parameter to cover a whole header field using Structured Fields serialization:
signer.sign(request, key_id="my-key", covered_component_ids=('"priority";sf',))
For example, Priority: u=03, i=?1 produces this signature-base line:
"priority";sf: u=3, i
The field’s Item, List, or Dictionary type is selected by its name using http_sf’s registry.
Both endpoints must use matching type definitions. The registry may omit otherwise standardized fields;
an unknown type or a value invalid for its registered type raises HTTPMessageSignaturesException during
signing, or InvalidSignature during verification. The library does not infer types from field values.
Headers covered without sf use the ordinary HTTP field normalization rules and do not require a registry entry.
The registry also contains retrofit mappings for legacy headers whose parsing rules can differ from Structured Fields. For example, this header:
Cache-Control: max-age=3600
can be changed to:
Cache-Control: max-age=0, max-age=3600
Both produce the same signed component because Structured Fields Dictionary parsing keeps the last duplicate:
"cache-control";sf: max-age=3600
However, RFC 9111 section 4.2.1 says duplicate
freshness directives should use the first occurrence or make the response stale. The change can therefore alter
caching behavior without invalidating a signature that covers "cache-control";sf. The
retrofit draft acknowledges
this difference in duplicate handling.
Omit ;sf when the application’s or other HTTP consumers’ interpretation differs from Structured Fields
semantics, or compatibility is unknown. For example, use covered_component_ids=("cache-control",) to keep
both duplicate directives in the signed value; adding one then changes the signature base. Use ;sf for fields
defined as Structured Fields, or legacy fields only when compatible interpretation is enforced. Applications
must still validate header values: successful signature verification does not establish their semantic validity.
Repeated field lines are combined before parsing. In a response signature, '"priority";req;sf' uses
the associated request’s field. Dictionary-member selection with key continues to work without a registry
entry and may include the redundant sf flag. The bs and tr parameters remain unsupported.
URL components¶
The request’s url supplies the target URL. URL components preserve percent-encoded octets and distinguish an
absent query from an empty query. @authority omits credentials and default ports; @target-uri excludes
credentials and fragments. Empty paths normally become /. For OPTIONS, @target-uri preserves an
empty path so server-wide OPTIONS * remains distinct from
OPTIONS /. The separate @path component still represents an empty path as /.
Supply an encoded absolute URL with a nonempty host. Parsing preserves the supplied spelling and rejects invalid
syntax, including malformed percent escapes (%, %2, or %ZZ), spaces, control characters, and unencoded
non-ASCII characters. It never repairs input. Each signature component applies its own RFC 9421 formatting rules.
This applies during signing, verification, applying a prepared signature, and resolving request components covered
by a response signature. A response’s own url is not used; components marked req use its associated request.
For @request-target, clients can supply message.request_target containing the HTTP/1.1 request
target. This is necessary for absolute-form proxy requests and asterisk-form OPTIONS * requests, since those
forms cannot be inferred from an absolute URL. Without this attribute, the resolver derives origin form from the
URL, or authority form for CONNECT. The supplied target and URL must describe the same request.
Multiple signatures¶
The message’s headers.items() must expose every field line, or values already combined in wire order. Repeated
field names are compared case-insensitively, normalized individually, and joined with a comma followed by a space
before signing or parsing Structured Fields. Containers that discard repeated field lines before passing them to this library cannot be used
to verify those fields reliably. Signing also requires header assignment and deletion; existing Signature and
Signature-Input field lines are replaced together, including when appending a signature.
An HTTP request can potentially have multiple signatures. By default, http-message-signatures overwrites any existing signature when signing, and requires exactly one signature to be present when verifying. Before enabling multi-signature support, please read section 7.2.6 of the RFC, Multiple Signature Confusion.
To append a signature to a message that might already carry an existing signature without overwriting it, use:
signer.sign(request, append_if_signature_exists=True, ...)
To identify a signature using a tag parameter and verify it on a message possibly carrying multiple signatures, use:
verifier.verify(request, expect_tag="my_app_tag")
This will filter all signatures down to only those that set the tag to the expected value, verify each of them, and
return a list of VerifyResult s. Verifying multiple signatures without prior knowledge of the application tag is not
supported.
Error handling¶
Input request methods must be uppercase strings, including the request associated with a response.
Methods such as get or Fetch are rejected before signature construction or verification;
the library does not change their case. This applies even when @method is not covered.
Individual query parameters use the component name @query-param with a name parameter,
for example '"@query-param";name="Pet"'. The previous spelling @query-params is rejected.
Signatures require a created timestamp by default. To accept signatures without one, set
verifier.require_created = False and pass max_age=None to verify(); an age limit cannot be enforced
without a creation timestamp. Expiration checks still apply when expires is present.
If multiple signatures are found in the request but expect_tag=... was not passed, then InvalidSignature is
raised. Also, the verify() method raises HTTPMessageSignaturesException or an exception derived from this class
in case an error occurs (unable to load PEM key, unsupported algorithm specified in signature input, signature doesn’t
match digest etc.)
Links¶
Bugs¶
Please report bugs, issues, feature requests, etc. on GitHub.
License¶
Copyright 2022-2026, Andrey Kislyuk and http-message-signatures contributors. Licensed under the terms of the Apache License, Version 2.0. Distribution of attribution information, LICENSE and NOTICE files with source copies of this package and derivative works is REQUIRED as specified by the Apache License.
API documentation¶
- class http_message_signatures.HTTPSignatureAlgorithm(public_key=None, private_key=None)[source]¶
Interface for explicitly configured signature algorithm implementations.
Subclasses define
algorithm_idand implement initialization,sign(), andverify(). Pass the subclass assignature_algorithmwhen creating a signer or verifier; no registration is required. The configured class is used regardless of whether the signature includes analgparameter. When present,algmust match the class’salgorithm_id.- algorithm_id: str¶
- exception http_message_signatures.HTTPMessageSignaturesException[source]¶
Base class for exceptions raised by http_message_signatures
- args¶
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- exception http_message_signatures.InvalidSignature[source]¶
Class for exceptions raised in the course of verifying an HTTP message signature
- args¶
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- class http_message_signatures.HTTPSignatureComponentResolver(message)[source]¶
Resolve covered components from a request or response object.
The constructor reads
headers. Requests also supply an uppercasemethodand an encoded absoluteurlwith a nonempty host. Invalid URL syntax is rejected, including malformed percent escapes and unencoded spaces, controls, or non-ASCII characters. The presence ofstatus_codeidentifies a response; itsrequestsupplies components qualified withreq. An associated request must also have an uppercase method. The response’s ownurlis not used.headers.items()must expose string names and values for all field lines in order, or values already combined in that order. Signing additionally requires iteration over names, membership testing, assignment, and deletion.A request may provide
request_targetfor an HTTP/1.1 target that cannot be inferred fromurl, such as an absolute-form proxy target or*. The supplied target and URL must describe the same request.Whole-field
sfserialization uses the field type registered inhttp_sf. Unknown types and malformed values raiseHTTPMessageSignaturesException.- field_component_parameters = frozenset({'bs', 'key', 'sf', 'tr'})¶
- derived_component_resolvers: ClassVar[dict[str, Callable[[...], str]]] = {'@authority': <function HTTPSignatureComponentResolver.<lambda>>, '@method': <function HTTPSignatureComponentResolver.<lambda>>, '@path': <function HTTPSignatureComponentResolver.<lambda>>, '@query': <function HTTPSignatureComponentResolver.<lambda>>, '@query-param': <function HTTPSignatureComponentResolver.<lambda>>, '@request-target': <function HTTPSignatureComponentResolver.<lambda>>, '@scheme': <function HTTPSignatureComponentResolver.<lambda>>, '@status': <function HTTPSignatureComponentResolver.<lambda>>, '@target-uri': <function HTTPSignatureComponentResolver.<lambda>>}¶
Callables receive the resolver instance followed by component parameters. Subclasses can copy and extend this mapping to support additional components.
- resolve(component_node)[source]¶
Return the string value of a parsed Structured Field component item.
- Parameters:
component_node (Item)
- class http_message_signatures.HTTPSignatureKeyResolver[source]¶
Subclass this interface to look up keys by their signed key IDs.
Return PEM bytes or the appropriate cryptography key object for asymmetric algorithms. For HMAC, return the same secret bytes from both methods.
- class http_message_signatures.HTTPMessageSigner(*, signature_algorithm, key_resolver=None, component_resolver_class=<class 'http_message_signatures.resolvers.HTTPSignatureComponentResolver'>)[source]¶
Construct HTTP message signatures and write their headers to a message.
Configure the algorithm and component resolver used for signing.
- Parameters:
signature_algorithm (type[HTTPSignatureAlgorithm]) – Built-in or custom subclass of
HTTPSignatureAlgorithm.key_resolver (HTTPSignatureKeyResolver | None) – Required by
sign()for local signing. May be omitted when usingprepare()andapply()with an external signer.component_resolver_class (type) – Resolver class instantiated for each message.
- DEFAULT_SIGNATURE_LABEL = 'pyhms'¶
- sign(message, *, key_id, created=None, expires=None, nonce=None, label=None, tag=None, include_alg=True, covered_component_ids=('@method', '@authority', '@target-uri'), append_if_signature_exists=False)[source]¶
Sign a message in place; return
None.- Parameters:
message – Request or response implementing the message interface documented in
HTTPSignatureComponentResolver.key_id (str) – ID passed to
key_resolver.resolve_private_keyand included in the signed metadata.created (datetime | None) – Creation time; defaults to the current time. A naive datetime is interpreted in the local timezone.
expires (datetime | None) – Optional expiration time, with the same timezone rules.
nonce (str | None) – Optional signed nonce. Replay detection is the caller’s responsibility.
label (str | None) – Signature dictionary key; defaults to
pyhms.tag (str | None) – Optional signed application identifier.
include_alg (bool) – Include the configured algorithm ID in signed metadata.
covered_component_ids (Sequence[str]) – Sequence of component names or serialized Structured Field String items, for example
("date",)or('"@query-param";name="Pet"',). A scalar string is rejected. Defaults cover request method, authority, and target URL. Responses require an explicit list such as("@status", "content-type").append_if_signature_exists (bool) – Preserve existing signatures and add a new label. Otherwise replace existing signature headers.
- Raises:
HTTPMessageSignaturesException – A component or signature parameter is invalid or an existing signature cannot be appended to.
Key resolver and algorithm errors can also propagate. Signing does not calculate a body digest; supply and cover a digest header when needed.
- prepare(message, *, key_id, created=None, expires=None, nonce=None, label=None, tag=None, include_alg=True, covered_component_ids=('@method', '@authority', '@target-uri'))[source]¶
Build the signing input without resolving a key or changing the message.
Arguments have the same meaning and defaults as in
sign(). Creation time is captured here, before any remote signing delay. Header append or replacement policy is selected later inapply().- Returns:
Immutable signing input for a synchronous or asynchronous signer. Sign
signature_basewith the configured algorithm and the key identified bykey_id, then pass the resulting bytes toapply().- Raises:
HTTPMessageSignaturesException – A component, parameter, or label is invalid.
- Parameters:
key_id (str)
created (datetime | None)
expires (datetime | None)
nonce (str | None)
label (str | None)
tag (str | None)
include_alg (bool)
covered_component_ids (Sequence[str])
- Return type:
The component resolver must return stable values for unchanged messages;
apply()resolves them again to check for changes while signing.
- apply(message, prepared, signature, *, append_if_signature_exists=False)[source]¶
Attach an externally generated signature to a message in place.
- Parameters:
message – Message whose covered values still match
prepared.prepared (PreparedSignature) – Input returned by
prepare()with the same algorithm and component resolver configuration.signature (bytes) – Raw algorithm output, before base64 encoding. ECDSA P-256 requires 64 bytes containing
r || s; convert DER output withECDSA_P256_SHA256.signature_from_der()first.append_if_signature_exists (bool) – Preserve existing signatures and add the prepared label. Otherwise replace existing signature headers.
- Raises:
HTTPMessageSignaturesException – Covered values changed, prepared input is inconsistent, signature bytes are empty, or headers cannot be appended to. Validation completes before changing headers.
- Return type:
None
This method neither resolves keys nor verifies the signature. The caller must associate the result with the prepared input and use a trusted signer with the intended key and algorithm. The comparison covers signature-base values only; it does not validate the body against a digest header, check expiration, or prevent concurrent message mutation. Keep the message stable during this call and until it is sent.
- signature_metadata_parameters: ClassVar[set[str]] = {'alg', 'created', 'expires', 'keyid', 'nonce', 'tag'}¶
- class http_message_signatures.HTTPMessageVerifier(*, signature_algorithm, key_resolver, component_resolver_class=<class 'http_message_signatures.resolvers.HTTPSignatureComponentResolver'>)[source]¶
Verify signatures using a configured algorithm and key resolver.
Configure signing or verification.
- Parameters:
signature_algorithm (type[HTTPSignatureAlgorithm]) – Built-in or custom subclass of
HTTPSignatureAlgorithm.key_resolver (HTTPSignatureKeyResolver | None) – Resolves key IDs to key bytes or cryptography key objects.
component_resolver_class (type) – Resolver class instantiated for each message.
- max_clock_skew: timedelta = datetime.timedelta(seconds=5)¶
Tolerance for creation, expiration, and maximum-age checks.
- require_created: bool = True¶
Require a creation timestamp. Set False and use max_age=None to allow its omission.
- allow_label_only_selection: bool = False¶
Permit label selection without a signed tag, with a warning.
- verify(message, *, max_age=datetime.timedelta(days=1), expect_tag=None, expect_label=None)[source]¶
Return verified signatures matching the requested selection.
- Parameters:
message – Request or response implementing the interface documented in
HTTPSignatureComponentResolver.max_age (timedelta | None) – Maximum age since creation, with clock-skew tolerance.
Nonedisables the age limit; expiration checks still apply.expect_tag (str | None) – Require this signed application tag. Required when selecting among multiple signatures unless label-only selection is enabled.
expect_label (str | None) – Also select this signature dictionary label. Labels are not signed; normally
expect_tagmust be supplied with this option.
- Returns:
A list of
VerifyResultobjects. Every selected signature must verify; no partial result is returned.- Raises:
InvalidSignature – A signature is missing, malformed, expired, uses an unexpected algorithm, or fails cryptographic verification.
HTTPMessageSignaturesException – The selection policy is invalid.
- Return type:
list[VerifyResult]
Check the returned coverage before trusting message data. Body digest validation, authorization, and nonce replay detection remain the caller’s responsibility. A valid signature alone does not establish those properties.
- signature_metadata_parameters: ClassVar[set[str]] = {'alg', 'created', 'expires', 'keyid', 'nonce', 'tag'}¶
- class http_message_signatures.PreparedSignature(signature_base, signature_params, label, algorithm_id)[source]¶
Immutable signing input returned by
HTTPMessageSigner.prepare().- Variables:
signature_base – ASCII bytes to pass to the signing algorithm, without additional encoding or an added newline.
signature_params – Serialized
@signature-paramsvalue, including the covered component list and signed metadata.label – Signature dictionary label (not covered by the signature).
algorithm_id – Configured algorithm ID, retained even when
algis omitted.
- Parameters:
signature_base (bytes)
signature_params (str)
label (str)
algorithm_id (str)
Retain this object until applying the corresponding signature. It contains covered message values, which may be sensitive. Immutability prevents accidental edits; it does not authenticate data sent through a queue or service.
- signature_base: bytes¶
- signature_params: str¶
- label: str¶
- algorithm_id: str¶
- class http_message_signatures.VerifyResult(label, algorithm, covered_components, parameters, body, nonce)[source]¶
A verified signature and the values it covers.
- Variables:
label – Signature dictionary label (not covered by the signature).
algorithm – Algorithm class used for verification.
covered_components – Serialized component identifiers mapped to signed values, including the generated
"@signature-params"entry.parameters – Signed signature metadata, such as
keyidandcreated.body –
Nonein this package; reserved for integrations validating body digests.nonce – Signed nonce, or
Nonewhen omitted.
- Parameters:
label (str)
algorithm (type[HTTPSignatureAlgorithm])
covered_components (dict[str, str])
parameters (dict[str, int | str])
body (bytes | None)
nonce (str | None)
Create new instance of VerifyResult(label, algorithm, covered_components, parameters, body, nonce)
- label: str¶
Alias for field number 0
- algorithm: type[HTTPSignatureAlgorithm]¶
Alias for field number 1
- covered_components: dict[str, str]¶
Alias for field number 2
- parameters: dict[str, int | str]¶
Alias for field number 3
- body: bytes | None¶
Alias for field number 4
- nonce: str | None¶
Alias for field number 5
- count(value, /)¶
Return number of occurrences of value.
- index(value, start=0, stop=9223372036854775807, /)¶
Return first index of value.
Raises ValueError if the value is not present.
Algorithms¶
- class http_message_signatures.algorithms.ECDSA_P256_SHA256(public_key=None, private_key=None, password=None)[source]
ECDSA P-256 with SHA-256, using PEM bytes or cryptography EC key objects.
passworddecrypts an encrypted PEM private key when provided.- algorithm_id: str = 'ecdsa-p256-sha256'
- sign(message)[source]
Return signature bytes for the supplied message bytes.
- Parameters:
message (bytes)
- static signature_from_der(signature)[source]
Convert a DER-encoded ECDSA P-256 signature to RFC 9421 signature bytes.
Returns the 64-byte concatenation of unsigned, big-endian
rands, each padded to 32 bytes (RFC 9421 section 3.3.4). Use this for a remote signer’s DER output before callingHTTPMessageSigner.apply(). Malformed DER or integers that do not fit raiseHTTPMessageSignaturesException. Conversion does not verify the signature or the signer’s choice of curve.- Parameters:
signature (bytes)
- Return type:
bytes
- verify(signature, message)[source]
Return None for a valid signature or raise if verification fails.
- Parameters:
signature (bytes)
message (bytes)
- load_pem_keys(public_key=None, private_key=None, password=None)
- class http_message_signatures.algorithms.ED25519(public_key=None, private_key=None, password=None)[source]
Ed25519 using PEM bytes or cryptography Ed25519 key objects.
passworddecrypts an encrypted PEM private key when provided.- algorithm_id: str = 'ed25519'
- sign(message)[source]
Return signature bytes for the supplied message bytes.
- Parameters:
message (bytes)
- verify(signature, message)[source]
Return None for a valid signature or raise if verification fails.
- Parameters:
signature (bytes)
message (bytes)
- load_pem_keys(public_key=None, private_key=None, password=None)
- class http_message_signatures.algorithms.HMAC_SHA256(public_key=None, private_key=None, shared_secret=None)[source]
HMAC with SHA-256 using secret bytes.
Supply
shared_secret,public_key, orprivate_key. At least one is required, and all supplied values must agree. The key resolver integration usesprivate_keyfor signing andpublic_keyfor verification.- algorithm_id: str = 'hmac-sha256'
- sign(message)[source]
Return signature bytes for the supplied message bytes.
- Parameters:
message (bytes)
- verify(signature, message)[source]
Return None for a valid signature or raise if verification fails.
- Parameters:
signature (bytes)
message (bytes)
- class http_message_signatures.algorithms.RSA_PSS_SHA512(public_key=None, private_key=None, password=None)[source]
RSA-PSS with SHA-512. Keys may be PEM bytes or cryptography RSA key objects.
passworddecrypts an encrypted PEM private key when provided.- algorithm_id: str = 'rsa-pss-sha512'
- sign(message)[source]
Return signature bytes for the supplied message bytes.
- Parameters:
message (bytes)
- verify(signature, message)[source]
Return None for a valid signature or raise if verification fails.
- Parameters:
signature (bytes)
message (bytes)
- load_pem_keys(public_key=None, private_key=None, password=None)
- class http_message_signatures.algorithms.RSA_V1_5_SHA256(public_key=None, private_key=None, password=None)[source]
RSA PKCS#1 v1.5 with SHA-256; accepts the same key arguments as RSA-PSS.
- algorithm_id: str = 'rsa-v1_5-sha256'
- padding: AsymmetricPadding
- hash_algorithm: HashAlgorithm
- load_pem_keys(public_key=None, private_key=None, password=None)
- sign(message)
Return signature bytes for the supplied message bytes.
- Parameters:
message (bytes)
- verify(signature, message)
Return None for a valid signature or raise if verification fails.
- Parameters:
signature (bytes)
message (bytes)
- class http_message_signatures.algorithms.HTTPSignatureAlgorithm(public_key=None, private_key=None)[source]
Interface for explicitly configured signature algorithm implementations.
Subclasses define
algorithm_idand implement initialization,sign(), andverify(). Pass the subclass assignature_algorithmwhen creating a signer or verifier; no registration is required. The configured class is used regardless of whether the signature includes analgparameter. When present,algmust match the class’salgorithm_id.- algorithm_id: str
- sign(message)[source]
Return signature bytes for the supplied message bytes.
- Parameters:
message (bytes)
- verify(signature, message)[source]
Return None for a valid signature or raise if verification fails.
- Parameters:
signature (bytes)
message (bytes)
Release Notes¶
Changes for v2.0.1 (2026-01-18)¶
Remove Python 3.8 and 3.9 from PyPI metadata
Changes for v2.0.0 (2026-01-02)¶
Multiple signature support (#22)
Drop Python 3.9 support
Changes for v1.0.1 (2026-01-01)¶
Remove extra ? in get_request_target (#19)
Changes for v1.0.0 (2025-07-26)¶
Vendor http_sfv
Package is stable
Changes for v0.7.0 (2025-06-29)¶
fix: convert url to string in HTTPSignatureComponentResolver constructor (#18)
Changes for v0.6.1 (2025-05-29)¶
Switch to trusted publishing
Changes for v0.6.0 (2025-05-29)¶
[http-message-signatures-add] Add support for ‘tag’ signature parameter (#17)
Changes for v0.5.0 (2024-02-21)¶
Add max_clock_skew to HTTPMessageVerifier (#11)
Documentation and test infrastructure improvements
Changes for v0.4.4 (2022-08-31)¶
Fix call signature in RSA_V1_5_SHA256 algorithm
Test improvements
Changes for v0.4.3 (2022-04-19)¶
Relocate VerifyResult
Changes for v0.4.2 (2022-04-19)¶
Fix casting bug
Changes for v0.4.1 (2022-04-19)¶
Add type information
Clean up algorithms namespace
Use max-age=24h by default
Changes for v0.4.0 (2022-04-14)¶
Validate created and expires params
Changes for v0.3.0 (2022-04-12)¶
Support query parameter addressing
Changes for v0.2.3 (2022-04-12)¶
Raise InvalidSignature in more code paths
Return related request method
Clarify that sign and verify work on both requests and responses
Changes for v0.2.2 (2022-04-10)¶
Add body placeholder
Changes for v0.2.1 (2022-04-10)¶
Return VerifyResult in verifier
Changes for v0.2.0 (2022-04-10)¶
Organize exceptions
Changes for v0.1.0 (2022-04-09)¶
Initial release.
Changes for v0.0.3 (2022-04-04)¶
Begin http-message-signatures