HTTP Integrity - RFC 9530 and more

HTTP integrity demos

HTTP has extensions that support multiple forms of integrity protection related to HTTP messages and representations. These concepts can be a little unintuitive, so this site provides some demos to aid understanding.

The common theme is running a hashing algorithm over some bytes and exchanging the result using the following HTTP header fields:

  • Content-Digest covers whatever bytes actually end up in a message's content. RFC 9530
  • Repr-Digest covers the complete selected representation. This factors in HTTP content coding (e.g., gzip, brotli, etc.). RFC 9530
  • Unencoded-Digest is also related to selected representations but always before any encoding, so it stays constant even if content coding is applied. draft-ietf-httpbis-unencoded-digest
  • Patched-Digest is a proposal for integrity related to PATCH requests and documents. draft-pardue-httpbis-patched-digest

The finer details of how to correctly determine the precise bytes to use for digests has a lot of nuance that stems from the nature of HTTP semantics. Especially when it comes to resources and representation data and metadata as defined in Section 8 of HTTP. Expand the section below for a comprehensive explanation with static worked examples.

Below is a playground for live and interactive digest experimentation. Each tab focuses on a particular area: regular request digests, regular response digests, and the non-adopted PATCH request digest.

Test HTTP response integrity: edit the resource below, then use request properties (Range and/or preferred content coding) to control how digests behave differently. Use the Verify panel at the bottom of the page to simulate validation of the digests.

Client

GET /items/123 HTTP/1.1
Host: foo.example
Accept-Encoding: identity
Range: bytes=0-0
Want-Content-Digest:
Want-Repr-Digest:
Want-Unencoded-Digest:
Accept-Encoding

A range request allows a server to return partial content.

Range header

Integrity preference fields are only hints; a receiver can ignore them entirely, so these don't change anything in the Server panel.

Want-Content-Digest
Want-Repr-Digest
Want-Unencoded-Digest

Server

HTTP/1.1 200 OK
Content-Type: application/json
Content-Digest: computing…
Repr-Digest: computing…
Unencoded-Digest: computing…
Content-Length: 0
Content-Range: bytes 0-0/0
Content-Encoding: gzip
Hashing algorithm(s)

Origin resource

The resource as the origin holds it with no content coding. This provides the input to digest calculation(s).

Content-Type

algorithm (Dictionary key)   digest, base64 (Byte Sequence value)

Verify

Verify the digest(s) received by the client. Content-Digest is checked against the bytes in the message. Repr-Digest is checked against the selected representation. This box tracks the Server panel above automatically until you edit it directly or tamper with it, at which point it stops, so your changes don't get overwritten.

Test HTTP request integrity: edit the resource below, then use request properties (content coding) to control how digests behave differently. Use the Verify panel at the bottom of the page to simulate validation of the digests.

Client

PUT /items/123 HTTP/1.1
Host: foo.example
Content-Type: application/json
Content-Digest: computing…
Repr-Digest: computing…
Unencoded-Digest: computing…
Content-Length: 0
Content-Encoding: gzip
Hashing algorithm(s)
Content-Encoding

Request resource

The payload a client would send as request content with no content coding. This provides the input to digest calculation(s).

Content-Type

algorithm (Dictionary key)   digest, base64 (Byte Sequence value)

Server

HTTP/1.1 200 OK
Content-Length: 0
Want-Content-Digest:
Want-Repr-Digest:
Want-Unencoded-Digest:

A server can optionally hint back what digest algorithm it wants for future requests.

Want-Content-Digest
Want-Repr-Digest
Want-Unencoded-Digest

Verify

Verify the digest(s) received by the server. Content-Digest, Repr-Digest, and Unencoded-Digest are all checked directly against the received body. This box tracks the Client panel above automatically until you edit it directly or tamper with it, at which point it stops, so your changes don't get overwritten.

Test Patched-Digest: the demo uses JSON Merge Patch whereby the content of the PATCH request is a JSON document representing the changes to merge into the target resource (not a list of operations like JSON Patch, RFC 6902). Content-Digest/Repr-Digest apply to the patch document and cannot describe what the patched resource should look like afterwards. Patched-Digest fills this gap, so a server can catch a stale expectation instead of silently applying a patch against the wrong base state.

Use the client panel to edit the patch document. Click “Update expected result” to compute the patch result, then “Send PATCH request” to check it. You can simulate validation failures by modifying either the patch document or the origin resource after locking in the expected result.

Client

PATCH /file.json HTTP/1.1
Host: foo.example
Content-Type: application/merge-patch+json
Content-Digest: computing…
Repr-Digest: computing…
Patched-Digest: computing…
Content-Length: 0
Hashing algorithm(s)

Patch document

A JSON Merge Patch document, merged into the origin resource above to compute the result. A new key is added; an existing key is replaced; a key set to null deletes that key.

Expected resulting resource

The result the client expects the patch to produce. It is never sent on the wire itself, only its digest is. A server computes this patch result independently and compares.

Server

HTTP/1.1 204 No Content
Content-Type: application/problem+json
Want-Patched-Digest:

A server can optionally hint back what digest algorithm it wants for future PATCH requests.

Want-Patched-Digest

Origin resource

The resource as it currently stands. Stays editable even after you send a PATCH request. Further edits here simulate another client's change landing before your PATCH arrives.

This page runs entirely in your client and nothing is sent to the server.