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.
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.
Capture “authentic” content
Save a screenshot, HTML, or a recording of requests and responses. The content may already have been altered.
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.
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.
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.
Prepare the private request
The extension prepares a separate TLSNotary request using the URL and request headers from Chrome. The path and cookies remain private client inputs.
NowClient · local operation
No network transfer at this step.
GET /private/report?key=example HTTP/1.1 Host: example.com Cookie: session=example-secret
Readable at the browser and website. Encrypted on the network.
Example exchange with condensed protocol messages and a symbolic signature. The saved package contains response.http and receipt.json.
Protocol sources
The sequence follows TLSNotary’s joint TLS handshake, private encryption and decryption and the extension’s session and disclosure flow. The compact signed receipt is part of ArchiveBox’s integration.
The ordinary browser page load precedes this request. TLS traffic and joint computations can interleave. The example hash uses the displayed response and an all-zero blinder; real captures use a random blinder.
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.
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. A transport provider can also observe connection 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.
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.
Arrows show who relies on whose honesty for each claim.
Origin and time
The reviewer trusts the verifier to attest honestly, protect its signing key and report its issuance time accurately.
Unchanged response bytes
With an honest verifier and its independently trusted key, the reviewer checks the saved bytes without taking the client’s word for them.
Authenticity during capture
The protocol lets an honest verifier reject a fabricated exchange, even when the client is dishonest.
Privacy during capture
The protocol keeps unrevealed URLs, cookies and page contents private even if the verifier tries to learn them.
These guarantees assume correct cryptography and software. Crossed arrows do not remove the reviewer’s reliance on an independent verifier or establish the truth of the website’s statements.
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.
Reducing reliance on one verifier
Independent attestations from several verifiers can reduce the risk of one operator being compromised, coerced or collaborating with a dishonest client. A possible arrangement would use separately operated services in the United States, China, Russia, India, France and Brazil. Different jurisdictions and political interests can make coordinated interference harder, provided the operators also have independent management, administrators and signing keys. Geography alone does not establish independence.
Universities, government agencies and other large institutions could provide these services with published operating policies, independent audits and formal procedures for exceptional access. Recorded approvals and auditable administrative actions can make bribery, social engineering or pressure harder to conceal. That paper trail should concern operation of the service, without recording users’ private URLs, cookies or page contents. Institutional size is useful only when these controls exist.
Keeping content private also limits selective interference: the verifier cannot inspect hidden pages and decide to falsify every capture containing a particular phrase. Targeting hidden content would require additional information, such as a signal from a cooperating client. Visible metadata, including the destination hostname, can still be used to select sessions.
Technical detail · What multiple verifiers would need to check
Each operator must independently authenticate the claimed exchange; several signatures on one operator’s unchecked assertion do not provide that independence. A reviewer must choose the required operators and acceptance rule in advance. Requiring every designated operator to attest to the same claim means all would have to fail or collude to accept a fabricated claim. A quorum requires compromising that quorum, not every operator. Shared software flaws remain a common risk.
Separate captures can return different content. Their receipts must be checked against the actual request and response each authenticates, rather than counted as confirmations of identical bytes automatically. This is a possible deployment model: the current ArchiveBox plugin uses one verifier per capture and does not implement multi-verifier consensus. TLSNotary describes the underlying trust in an independent notary.
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.
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.