Verify HTTP content with Digest Fields
RFC 9530 separates digests of conveyed message content from digests of representation data and replaces the older Digest field.
- standards updates
- digest fields
- integrity
- representations
- structured fields
Choose what the digest is about
RFC 9530 defines two related integrity fields:
Content-Digestcovers the actual content carried in this HTTP message.Repr-Digestcovers the complete selected representation data associated with the message.
They can have the same value when a response carries the complete
representation. They diverge when HTTP semantics change what is enclosed, such
as a HEAD response with no content or a 206 Partial Content response carrying
only a selected range.
Use Content-Digest when the question is “did these conveyed content bytes
arrive unchanged?” Use Repr-Digest when the application needs integrity for
the representation, including cases where the message contains only part of it
or no representation data at all.
Read the value as a Structured Dictionary
Both fields are Structured Field Dictionaries. Each member key names a hash algorithm and each member value is a Byte Sequence containing the digest output.
Content-Digest: sha-256=:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=:
Expected result: the value declares the SHA-256 digest of empty content. The colons delimit a Structured Fields Byte Sequence; they are not part of the digest bytes.
A Dictionary can carry more than one algorithm during a migration:
Repr-Digest: sha-256=:ZmFrZS0yNTY=:, sha-512=:ZmFrZS01MTI=:
Expected result: a parser finds two algorithm members. These short, illustrative byte sequences are not real SHA-256 or SHA-512 outputs and are unsuitable as verification test vectors.
Do not compare the base64 text with a locally invented encoding. Parse the Structured Field, select an acceptable registered algorithm, calculate its bytes, and compare the decoded byte sequences according to the application’s policy.
Hash the exact selected bytes
A digest is sensitive to every byte. Reformatting JSON, normalizing line endings, changing Unicode encoding, or decompressing at the wrong stage produces a different input.
Content-Digest is calculated over HTTP content. Content codings such as gzip
are part of the content as conveyed, so an intermediary that changes the coding
also changes the applicable content digest.
Repr-Digest follows representation semantics. It can describe the complete
selected representation even when the current message encloses only a range or
when HEAD encloses no content. The method, status, range selection,
Content-Encoding, and representation metadata therefore matter when deciding
which bytes the field represents.
For a normal 200 OK response carrying the complete selected representation,
the two fields often cover the same bytes:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Digest: sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:
Repr-Digest: sha-256=:RK/0qy18MlBSVnWgjwz6lZEWjP/lF5HF9bvEF8FabDg=:
Content-Length: 19
{"hello": "world"}
Expected result: both values match because the message content is the complete representation data, including the final line feed counted in the 19-byte content. Removing that line feed changes both digests.
Do not confuse HEAD with an empty resource
A HEAD response has no content, but it can still describe a representation.
Its Content-Digest can therefore be the digest of an empty byte sequence while
its Repr-Digest describes the representation that would be selected.
This distinction also matters for partial responses. A Content-Digest on a
206 response covers the enclosed partial content. A Repr-Digest can support
checking the complete representation reconstructed from multiple ranges.
Do not assume that a matching value on one partial message verifies every other part. The application still needs correct range metadata, a consistent selected representation, and a policy for assembling and validating the whole.
Express algorithm preferences as hints
Want-Content-Digest and Want-Repr-Digest let either endpoint express interest
and relative algorithm preferences. Their Dictionary values range from 0 to
10: zero means not acceptable, and larger positive values mean stronger
preference.
Want-Content-Digest: sha-512=5, sha-256=10
Expected result: the sender prefers sha-256 over sha-512. The recipient
can ignore the hint, choose another supported algorithm, or omit a digest unless
an application-specific contract requires one.
Consult the current IANA registry instead of hard-coding the original algorithm
list forever. At publication, sha-256 and sha-512 are Active. Legacy entries
including md5 and sha are Deprecated and must not be used in an adversarial
setting.
A digest is not proof of who sent the message
Anyone who can alter both the content and an unprotected digest field can produce a new matching pair. Digest Fields alone do not provide authenticity, confidentiality, authorization, or complete protection for all HTTP metadata.
TLS protects data on each secured connection, but an HTTP path can contain multiple TLS-terminating hops. An application that needs a digest to remain trustworthy across those hops can cover the integrity field with an HTTP message signature and must still verify the digest against the received content.
Signing only the Content-Digest field value is not enough if the verifier never
recalculates it. The signature proves that the signer covered that field value;
the digest comparison binds the value to the actual bytes.
Plan for transformations and trailers
Integrity fields can appear in a trailer section, which lets a sender calculate a digest while streaming content. Trailers are not guaranteed to survive every intermediary, so confirm support through the complete deployment path.
Compression, transcoding, range handling, and content adaptation can legitimately change the bytes and invalidate an earlier digest. Decide which component is allowed to transform content, whether it removes the old field, and whether it calculates a new field under a new trust boundary.
Resource limits also matter. A verifier should bound accepted content size, supported algorithms, simultaneous digest calculations, and buffering. Digest validation should not become an unbounded CPU or memory operation.
Migrate away from the old Digest field
RFC 9530 was published in February 2024 and obsoletes RFC 3230. The older
Digest and Want-Digest fields are now obsoleted. New implementations should
use the explicit Content-Digest, Repr-Digest, and corresponding preference
fields.
During migration, do not treat the old and new field names as aliases. They have different definitions and registries. Document which form each peer supports, verify the intended bytes with test vectors, and remove fallback behavior after the compatibility window closes.
