Skip to main content

Implementation of the Digest HTTP headers according to RFC 3230.

Project description

Test Coverage Versions

Introduction

A small library to provide the server and client side methods to require, negotiation and generate Digest HTTP headers as per RFC 3230. Clients can generate Digest headers of the form: Digest: SHA-256=xyz, MD5=abc. Server can require certain algorithms by sending Want-Digest headers of the form: Want-Digest: SHA-256, SHA;q=0.5, MD5;q=0.

Installation

Install using pip:

pip install rfc3230-digest-headers

Overview of the protocol

The protocol works as follows:

  1. Client and server agree on what the instance bytes are for the endpoint in question. Usually the request body or the content of the resource before applying transformations.
  2. Client sends request
  3. If the client did not directly send a valid Digest, the server responds with Want-Digest header to indicate which algorithms it supports.
    • Form of the Want-Digest header: Want-Digest: SHA-256, SHA;q=0.5, MD5;q=0
    • The server can specify qvalues to indicate preference of algorithms.
    • No value equals q=1.0.
    • q=0 means "do not use this algorithm".
  4. Client generates Digest header using one of the supported algorithms and sends it in the request.
    • Form of the Digest header: Digest: SHA-256=xyz, MD5=abc
  5. Server verifies the Digest header and processes the request.

Usage

The library provides only one enum class, DigestHeaderAlgorithm, which can be used by server and client to fully specify, negotiate and generate Digest HTTP headers. You do not use these algorithms directly, but instead have to use a couple of static methods provided by the enum class.

Example: Generate a Digest header

The client generates a Digest for their instance.

from rfc3230_digest_headers import DigestHeaderAlgorithm

instance_bytes = b"Hello, World!"
(header_name, header_value) = DigestHeaderAlgorithm.make_digest_header(
    instance=instance_bytes,
    algorithms=[DigestHeaderAlgorithm.SHA256, DigestHeaderAlgorithm.MD5]
)
print(header_name)  # "Digest"
print(header_value) # "SHA-256=..., MD5=..."

Usage: Verify a Digest header

The server receives a request with a Digest header and verifies it.

from rfc3230_digest_headers import DigestHeaderAlgorithm

instance_bytes = b"Hello, World!"
request_headers = {"Digest": "SHA-256=..., MD5=..."}
is_valid, want_digest_header_should_be_added = DigestHeaderAlgorithm.verify_request(
    request_headers=request_headers,
    instance=instance_bytes,
    qvalues={
        DigestHeaderAlgorithm.SHA256: 1.0,
        DigestHeaderAlgorithm.SHA: 0.5,
        DigestHeaderAlgorithm.MD5: 0.0 # If the client sends MD5, they will receive an error
    },
)
print(is_valid)  # True if the Digest header is valid
print(want_digest_header_should_be_added)  # None if valid, otherwise contains the `Want-Digest` header to be sent to the client for negotiation

Usage: Server-side negotiation of algorithms

The server can indicate which algorithms the endpoint requires by sending a Want-Digest header. The header is automatically generated when attempting to verify invalid request headers.

from rfc3230_digest_headers import DigestHeaderAlgorithm

# Fake request from client without an invalid Digest header
instance_bytes = b"Hello, World!"
request_headers = {"Digest": "SHA-256=..., MD5=..."}
is_valid, want_digest_header_should_be_added = DigestHeaderAlgorithm.verify_request(
    request_headers=request_headers,
    instance=instance_bytes,
    qvalues={
        DigestHeaderAlgorithm.SHA256: 1.0,
        DigestHeaderAlgorithm.SHA: 0.5,
        DigestHeaderAlgorithm.MD5: 0.0 # If the client sends MD5, they will receive an error
    },
)
if want_digest_header_should_be_added:
    print(want_digest_header_should_be_added.header_name)  # "Want-Digest"
    print(want_digest_header_should_be_added.header_value) # "SHA-256, SHA
    # Send the response with the generated Want-Digest header
    ...

In this example the request fails because the client sent MD5, which is not supported by the server.

Usage: Client-side negotiation of algorithms

When an endpoint responds with a Want-Digest header, the client can parse it and generate a valid Digest header.

from rfc3230_digest_headers import DigestHeaderAlgorithm

# Fake response from server with Want-Digest header
instance_bytes = b"Hello, World!"
response_headers = {"Want-Digest": "SHA-256, SHA;q=0.5, MD5;q=0"}
want_digest_header = DigestHeaderAlgorithm.parse_want_digest_header(
    response_headers=response_headers
)

# Parse the response and generate a valid Digest header (if possible)
if want_digest_header:
    (header_name, header_value) = DigestHeaderAlgorithm.make_digest_header(
        instance=instance_bytes,
        algorithms=want_digest_header.supported_algorithms
    )
    print(header_name)  # "Digest"
    print(header_value) # "SHA-256=..., SHA=..."
    # re-send the request with the generated Digest header
    ...

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rfc3230_digest_headers-1.0.1.tar.gz (7.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rfc3230_digest_headers-1.0.1-py3-none-any.whl (12.3 kB view details)

Uploaded Python 3

File details

Details for the file rfc3230_digest_headers-1.0.1.tar.gz.

File metadata

  • Download URL: rfc3230_digest_headers-1.0.1.tar.gz
  • Upload date:
  • Size: 7.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for rfc3230_digest_headers-1.0.1.tar.gz
Algorithm Hash digest
SHA256 44da6a020486b70a76d8f6f3d7e2dbfc72e2183324052287e004f9b57cb7fa56
MD5 89ba39daeabd5eb603c4f9f6af04fa76
BLAKE2b-256 88ccc35b3e11f568ebeb77253edc117d009c01a1619396502aadafdea87da0ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for rfc3230_digest_headers-1.0.1.tar.gz:

Publisher: publish.yml on Mari6814/py-rfc3230-digest-headers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rfc3230_digest_headers-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for rfc3230_digest_headers-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 845e24244337dd4042b0cdf8cb98628dda45147d2eff079c1db08dc48f5eff7d
MD5 99b120ab4ee43b190d080454f687a58a
BLAKE2b-256 6a1da6437ef7a949200a18d6e175fe53297cda08fc942034583cc5c39bfe1e7d

See more details on using hashes here.

Provenance

The following attestation bundles were made for rfc3230_digest_headers-1.0.1-py3-none-any.whl:

Publisher: publish.yml on Mari6814/py-rfc3230-digest-headers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page