Verification runs on this device. Files are never uploaded. Trust depends
on the configured verifier key and its clock. Only this response is
authenticated.
Proving the source of archived web content
Suppose someone walks into a notary’s office with a screenshot printed
on paper and signs it in front of the notary. The notary can witness
the signature and record when it happened, but cannot establish whether
the screenshot was edited in Photoshop before it was printed. The
notary did not observe what the website actually served.
The same problem applies if someone tampers with a page in their browser
before capturing it as evidence, then hashes, timestamps and signs the
capture. Those checks can all pass for the altered copy. They do not
establish that the website served the content shown in it.
Non-repudiation of web content requires evidence of what
a server sent that a third party can verify later. Ordinary HTTPS does
not provide that evidence by itself. TLSNotary addresses this by involving
a verifier during the connection, without disclosing the page contents
to that verifier.
01 · Preservation and provenance
File integrity and source authentication
A hash is a digital fingerprint of a file. It helps
detect changes. A trusted timestamp can establish that those bytes
existed by a particular time. Neither, on its own, establishes who
supplied the original bytes. A fabricated page can be hashed and
timestamped just as successfully as a genuine one.
Imagine someone fabricates a social media post by editing it in their
browser or Photoshop, then takes a printout to a notary and signs it
in front of them.
1
Capture “authentic” content
Save a screenshot, HTML, or a recording of requests and responses.
The content may already have been altered.
→
2
Sign and record the time
Bring it to a notary, timestamping service or blockchain:
“I saw ‘xyz’ at this time. Record it.” The signature and timestamp
can be valid even if the content is fabricated.
→
3
Mistake preservation for authenticity
In court, someone argues: “The signature and timestamp verify,
and the hashes match. It’s unchanged, so it must be authentic.”
Those checks do not establish the source of step 1.
A fabricated capture can pass the same checks. The unanswered question
is: did facebook.com/some/post actually serve “xyz” to this
viewer on Thursday at 2 p.m.?
Hashing a saved response and retaining its SSL/TLS certificate leaves
the same gap. Even if you sign or timestamp that package, you have
preserved a claim about its origin—not cryptographically established
that origin. The certificate identifies a server’s key; it is not the
server’s signature on the saved page.
Integrity: “This copy has not changed since it was recorded.”
Origin: “This server actually sent these bytes.”
A common pitfall when evaluating existing products in this space
(e.g. Hunchly, Snapoena, Page Vault, ProofSnap and GoFullPage) is assuming
that a signed or timestamped archive proves remote origin. An assessment
needs to establish how the capture process rules out fabrication
before hashing. A signature on the evidence package alone does
not resolve that question.
Technical detail · TLS connection authentication and server signatures
TLS authenticates the connection to its participants. Its application
records use symmetric authentication keys available to the endpoints.
A client controlling its capture environment can construct a false
transcript and authenticate it with those keys. Saving network
packets, certificates, HAR or WARC files does not by itself eliminate
that possibility.
In TLS 1.3, the server’s CertificateVerify signature covers the
handshake transcript; later application records use symmetric AEAD
protection. The distinction is explicit in the
IETF’s TLS 1.3 handshake specification
and record protection specification.
TLS 1.2 makes the corresponding separation in
RFC 5246.
For evidence reviewers · What timestamps establish
Preservation, timing and source authentication answer different
questions. A timestamp is useful evidence about when particular data
existed; a hash helps check whether it changed afterward. Neither
mechanism examines whether the material was fabricated before it was
submitted. See the IETF time-stamping protocol.
TLSNotary adds evidence of remote origin. It does not replace record
keeping, context or an assessment of evidentiary weight. This service’s
receipt is not a qualified electronic timestamp or a legal notarial act.
02 · Protocol
Verification during the TLS connection
TLSNotary brings an independent verifier into the cryptographic process
while the website is being contacted. The person making
the capture cannot simply substitute an invented response and convince
an honest verifier that it came from that website.
A capture, message by message
Follow the request through the network
Play the exchange slowly, or drag the timeline to inspect any hop.
Session / metadataWebsite TLS recordsMPC / ZK messagesSigned receiptLocal operation
Before notarization
The browser loads the page normally
The plugin opens the target URL in Chrome to obtain the request headers for the logged-in session. This initial navigation is ordinary HTTPS and is not the notarized request.
NowYour browser → Website
A direct HTTPS connection to the website. No TLSNotary verifier participates yet.
Message contents · example values
GET /private/report?key=example HTTP/1.1
Host: documents.example
Cookie: session=example-secret
Readable at the browser and website. Encrypted on the network.
Message ordering and implementation sources
The routes come from the plugin’s gateway, tunnel configuration and capture hook. See also the extension’s session and disclosure sequence, TLSNotary’s joint TLS handshake and private encryption and decryption.
Cloudflare terminates the outer HTTPS/WSS connection. It can inspect that transport’s metadata and payload, but the website application data inside it remains protected by a separate TLS session. The tunnel encrypts the edge-to-connector hop. On the local container network, the gateway forwards WebSocket payloads to either the verifier or its TCP bridge; it does not decrypt the website response.
An independent service could always visit a public page and attest to
what it saw. TLSNotary uses secure multi-party computation (MPC) and
zero-knowledge proofs to verify the source without disclosing the
content to the verifier.
TLSNotary has a
published protocol dating to 2014.
Its current MPC-TLS protocol
addresses the problem without requiring websites to adopt a new signing system.
Technical detail · What MPC and zero-knowledge each contribute
MPC lets the browser and verifier perform the TLS operations together
without giving the browser unilateral control of the authentication
secrets. Zero-knowledge then lets the browser prove that a concealed
response matches a cryptographic commitment—a fingerprint locked to
those bytes—without revealing the response itself.
A zero-knowledge proof alone would not fix a transcript the client was
free to fabricate. Participation in the connection is essential.
This plugin uses TLSNotary’s MPC mode, plus a SHA-256 hash commitment;
it does not use the separate protocol called “proxy mode.” See
why an online verifier is needed
and commitment strategies.
Research context · Other protocol approaches
The 2017 TLS-N paper
describes extending TLS to support transferable proofs. TLSNotary
instead uses a separate verifier and works without changes to the
website’s server software.
03 · Privacy
Capturing pages that require authentication
A public archive can visit a news article itself. It cannot ordinarily
see your private social media posts, a document shared only with you,
or a page behind your login without being given access. Giving the
service credentials or a readable copy discloses that private data.
TLSNotary makes it possible to authenticate data from a session without
revealing its contents or the user’s cookies to a third-party verifier.
It allows you to authenticate and sign logged-in content such as social
media posts, paywalled articles and private Google Docs without revealing
them to a verifier service that could spy on your data.
Kept from this verifier
- Readable page contents and response headers
- Cookies, authorization headers and embedded secrets
- The URL path and query, including private document IDs
Your saved archive is still sensitive. It contains the
actual response, including any secrets the website sent in it. Someone
you give that file to can read it. The verifier at the top of this page
checks selected files locally; it does not upload them.
Technical detail · Redaction, transport and the limits of this integration
The capture configuration discloses no request transcript. It hashes
the complete received response and reveals only fixed syntax such as
HTTP/1.1, spaces and line endings. The response opening
stays local. The destination is deliberately visible to the transport
proxy; this is not an anonymity service. Cloudflare, which fronts this
deployment, can also observe transport metadata. A sensitive value
encoded in a hostname is not hidden like a value in the URL path.
TLSNotary supports selective disclosure, but this ArchiveBox receipt
binds the whole saved response. Editing or redacting that file
afterward makes this receipt fail verification. The plugin currently
authenticates a separate main-document request made by the extension,
using captured browser request headers. It does not certify all tab
traffic, downloaded assets, video content or the rendered screenshot.
A JavaScript application’s initial response may not contain the document
visible on screen.
See the extension’s disclosure model
and this plugin’s capture and server code.
04 · Trust assumptions
What receipt verification establishes
A successful check of an ArchiveBox TLSNotary receipt establishes that:
These saved response bytes match a commitment signed by the configured
verifier. That verifier attests to their origin from the named server
and records its own time of issuing the receipt.
Someone cannot alter the response and retain a valid result without
defeating the cryptography or obtaining a different valid receipt.
A valid signature identifies the signing key, but does not establish
that its holder was honest. Verification therefore depends on the
following trust assumptions.
The verifier operator
You trust it to run the protocol correctly, sign only successful results, protect its signing key and not collude with the person making the capture. You also trust its clock for the displayed time.
The server’s identity
You rely on TLS certificate validation and the trusted certificate authorities that bind a key to a hostname. This authenticates a domain—not a particular human author or the truth of a statement.
The checking software and key
You trust the software doing the check, the device running it, and the source of the verifier’s public key. A key supplied only by the person presenting the evidence is not an independent trust anchor.
The cryptography and its implementation
You rely on TLSNotary’s protocol, the signature and hash algorithms, and their correct implementation. This integration is experimental software.
For evidence reviewers · What this receipt does not establish
- The whole page: it covers the accompanying response, not every file in an ArchiveBox snapshot or an ArchiveWeb.page WACZ.
- The exact requested URL or account: the signed payload names the server, not the private request path, query, cookies or user identity.
- Truth or authorship: a server can publish false statements, display user-supplied text or be compromised.
- A publication date: the receipt’s time is the verifier’s issuance time, not when the website first published the content or a separately certified time.
- Automatic legal acceptance: admissibility and weight still depend on the applicable rules, context and supporting evidence.
Technical detail · The signed receipt and delegated verification
During capture, the upstream TLSNotary verifier checks the protocol
and commitment proof. ArchiveBox’s gateway signs a payload containing
the authenticated hostname, its issuance time, the response range and
the commitment. Later verification checks that signature and opens
the commitment using your saved response. It does not replay
the interactive proof or independently repeat certificate validation.
This is an ArchiveBox receipt backed by a verifier’s attestation,
not a website-issued signature or a standalone TLSNotary presentation.
A dishonest operator, a compromised signing key or collusion could
produce a false receipt that passes the local check. Running your own
verifier gives you operational control, but does not make your
self-issued receipts independent evidence to someone who distrusts you.
See TLSNotary’s explanation of delegated trust.
05 · Independent verification
Required files and verification procedure
response.httpThe original response bytes, stored once. This is the content being authenticated.
+
receipt.jsonThe signed commitment and the data needed to check it against the response. It contains no copy of the page.
You do not need this public service to stay online to check an existing
capture. Preserve both files unchanged, the verification software, and
an independently obtained copy of the verifier’s public key. You can
give those to another reviewer to check on their own device.
Developer instructions · Verify locally with Node.js
Review and obtain verify.mjs from the source repository.
Place it alongside the two capture files. With a current Node.js
version supporting Web Crypto and DecompressionStream,
run the command below from that directory. Replace the placeholder
with the base64 SPKI public key you independently trust for the
verifier that issued the receipt.
TRUSTED_KEY='INDEPENDENTLY_TRUSTED_BASE64_SPKI_KEY' node --input-type=module <<'JS'
import { readFileSync } from 'node:fs';
import { verifyReceipt } from './verify.mjs';
const receipt = JSON.parse(readFileSync('receipt.json', 'utf8'));
const response = new Uint8Array(readFileSync('response.http'));
const result = await verifyReceipt(receipt, response, process.env.TRUSTED_KEY);
console.log('Verified:', result.server_name);
console.log('Verifier time:', new Date(result.time * 1000).toISOString());
console.log('Authenticated bytes:', response.length);
JS
The check validates an Ed25519 signature over the decoded payload,
recomputes SHA-256(response.http bytes || 16-byte blinder),
matches the signed byte range and requires a complete successful HTTP
response. The blinder is random data that hides the commitment from
guessing while the response is private. It is saved locally in the receipt.
A green result on a website controlled by an untrusted party is not
independent verification. For contested evidence, review the code and
establish the key through a separate trusted channel. Keep the original
key when an operator rotates keys; newly published keys do not
automatically authenticate older receipts.
For self-hosted verification, the plugin includes
Docker Compose, example configuration and setup instructions.
Captures are opt-in because the cryptographic work adds time and bandwidth.