Version 0.2 – Draft Status of This Memo This document specifies a proposed protocol for the Internet community and requests discussion and suggestions for improvement. Distribution of this memo is unlimited.
Submitted 7/6/2025: https://datatracker.ietf.org/submit/status/153510/
This document defines the Web Content Authenticity Protocol (WCAP), a mechanism for ensuring the end-to-end authenticity and integrity of web resources. WCAP is designed to be transport-agnostic, meaning it can verify content regardless of how it was delivered—via HTTP, peer-to-peer networks, or other channels. By using digital signatures, WCAP allows a verifier to cryptographically confirm that a resource is exactly what the originator intended to publish, and has not been tampered with by any intermediary, including compromised servers, state-level actors, or malicious networks. This provides a powerful guarantee against censorship, manipulation, and unauthorized modification of information.
While Transport Layer Security (TLS) provides a secure channel between a client and a server, it does not protect content once it has been delivered or if an intermediary in the chain (such as a CDN or proxy) is compromised. The Web Content Authenticity Protocol (WCAP) provides a mechanism for a web server (the Signer) to digitally sign web resources, allowing a client (the Verifier) to confirm that the content is exactly what the origin server intended to send.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
WCAP is designed to protect against the following threats:
- Content Injection/Modification: A malicious actor alters content in transit.
- Compromised Infrastructure: A CDN, reverse proxy, or hosting server is compromised.
- DNS Manipulation: An adversary reroutes traffic to a malicious server.
- TLS Interception: A rogue or coerced CA enables a man-in-the-middle.
- Censorship and Takedowns: A government forces a platform to alter or remove content.
- Signer Coercion: A publisher is forced to hand over their private signing keys.
- Resource: Any HTTP-delivered content (HTML, JS, images, JSON, etc.)
- Signer: The server or entity that holds a private key and signs Resources.
- Verifier: The client or tool that retrieves and verifies the Signature using the Signer’s public key.
- Signature: The result of signing a Resource body with a private key.
- Public Key URI: A URI where the Signer’s public key is published.
Step 1: Generate a Key Pair
openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem
openssl ec -in private-key.pem -pubout -out public-key.pem
Step 2: Sign Your Content
openssl dgst -sha256 -sign private-key.pem -out signature.bin message.txt
openssl base64 -in signature.bin -out signature.b64
Step 3: Serve Content with Content-Signature
Header
Content-Signature: alg=ecdsa-p256-sha256; key_uri=/.well-known/wcap-public-key.pem; sig=<base64 signature>
Ensure the public key is served at the path specified in key_uri
.
- The Verifier requests a Resource.
- The Signer generates the Resource body and its Signature.
- The Signer returns the Resource with the
Content-Signature
HTTP header. - The Verifier retrieves the public key from
key_uri
. - The Verifier checks the Signature against the Resource body.
If verification succeeds, the Resource is authentic. If it fails, the Resource is potentially tampered with.
- MUST generate and securely store a public/private key pair.
- RECOMMENDED algorithm: ECDSA (P-256 with SHA-256).
- MAY support other modern, secure digital signature algorithms.
- SHOULD rotate keys periodically and expose metadata for revocation and validity.
-
MUST publish public key at a stable
key_uri
, such as:/.well-known/wcap-public-key.pem
-
MUST serve it over HTTPS with a valid certificate.
-
Public key MUST be in PEM format.
-
MAY include a revocation URI and expiration metadata inside the PEM file.
Header format:
Content-Signature: alg=<algorithm>; key_uri=<uri>; sig=<base64 signature>
alg
: REQUIRED. Digital signature algorithm name.key_uri
: REQUIRED. Public key location (relative or absolute).sig
: REQUIRED. Base64-encoded digital signature of the exact response body.
- MUST check for a
Content-Signature
header in HTTP responses.
- MUST fetch public key from
key_uri
(HTTPS RECOMMENDED). - SHOULD cache keys securely for performance.
- MAY allow preloading or pinning of trusted keys.
The Verifier MUST:
- Parse the
Content-Signature
header. - Retrieve and cache the public key.
- Verify the decoded
sig
against the exact body of the response.
- MUST NOT render or use the resource.
- SHOULD display a clear integrity warning or error.
- SHOULD continue to use Subresource Integrity (SRI) when possible.
- WCAP MAY be used as a fallback or enhancement to SRI.
To sign WebSocket messages:
{
"payload": { ... },
"signature": "<base64 signature of payload>"
}
- Every message MUST be signed individually.
- Receiver MUST verify before acting on the message.
- Key Compromise: MUST allow for key rotation and revocation.
- Replay Attacks: Resources MAY include timestamps or nonces.
- Initial Trust: Relies on HTTPS or DNSSEC for the first key fetch.
- Signature Stripping: Client SHOULD treat unsigned content as untrusted when a signature is expected.
- Header Binding (Optional): Future versions MAY support binding signature to additional headers (e.g., MIME types, CSP).
- Public key fetches can expose access patterns. To reduce this:
- Verifiers SHOULD cache keys aggressively.
- Verifiers MAY pre-fetch public keys for known hosts.
- Alternative key distribution (e.g., IPFS, blockchain, DNSSEC) MAY enhance privacy and resilience.
kid
(Key ID) parameter to support multiple keys.- Structured signature metadata formats (e.g., JSON or COSE).
- Verifiable streaming content using Merkle trees.
- Multi-signature schemes or endorsement chains.
- Web browser integration (e.g., extensions or native WCAP support).
- Blockchain-based or decentralized key registries.
This specification is published under the Apache 2.0 License. (C) 2024–2025 Digital Defiance. Contributions welcome via GitHub.