From bae7c1794f61263bb6f88e6736ea0a8357a0e332 Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Mon, 8 Jun 2026 18:00:57 +0200 Subject: [PATCH 1/3] blog: add post on what "publicly verifiable" means for zkTLS New post explaining that a zkTLS proof is a designated-verifier attestation, not trustless math: "publicly verifiable" means verifiable by anyone who trusts the verifier that witnessed the session. Covers why an in-session witness is unavoidable, the verifier vs. notary vs. attestation-verifier distinction, where zero-knowledge does and does not help, and how to minimize the trust you take on. Includes three light/dark diagrams (self-verify, delegated verifier, and a new witness-needed contrast) authored in draw.io and exported via convert_all.sh. --- .../convert_all.sh | 39 +++++ .../dark/delegated_verifier.svg | 2 + .../dark/self_verify.svg | 2 + .../dark/witness_needed.svg | 2 + .../delegated_verifier.drawio | 70 +++++++++ blog/2026-06-05-public-verifiability/index.md | 142 ++++++++++++++++++ .../light/delegated_verifier.svg | 2 + .../light/self_verify.svg | 2 + .../light/witness_needed.svg | 2 + .../self_verify.drawio | 34 +++++ .../witness_needed.drawio | 61 ++++++++ 11 files changed, 358 insertions(+) create mode 100755 blog/2026-06-05-public-verifiability/convert_all.sh create mode 100644 blog/2026-06-05-public-verifiability/dark/delegated_verifier.svg create mode 100644 blog/2026-06-05-public-verifiability/dark/self_verify.svg create mode 100644 blog/2026-06-05-public-verifiability/dark/witness_needed.svg create mode 100644 blog/2026-06-05-public-verifiability/delegated_verifier.drawio create mode 100644 blog/2026-06-05-public-verifiability/index.md create mode 100644 blog/2026-06-05-public-verifiability/light/delegated_verifier.svg create mode 100644 blog/2026-06-05-public-verifiability/light/self_verify.svg create mode 100644 blog/2026-06-05-public-verifiability/light/witness_needed.svg create mode 100644 blog/2026-06-05-public-verifiability/self_verify.drawio create mode 100644 blog/2026-06-05-public-verifiability/witness_needed.drawio diff --git a/blog/2026-06-05-public-verifiability/convert_all.sh b/blog/2026-06-05-public-verifiability/convert_all.sh new file mode 100755 index 0000000..c9d0ed8 --- /dev/null +++ b/blog/2026-06-05-public-verifiability/convert_all.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +FORMAT="svg" + +SOURCE_DIR=$(dirname "$0") +TARGET_DIR=$(realpath "$(dirname "$0")/") + +OS=$(uname) +case "$OS" in +"Darwin") # Mac + DRAW_IO="/Applications/draw.io.app/Contents/MacOS/draw.io" + ;; +"Linux") # Linux + DRAW_IO="drawio" + ;; +esac + +# Unset Electron env vars that interfere with draw.io when running from VSCode +unset ELECTRON_RUN_AS_NODE ELECTRON_NO_ATTACH_CONSOLE + +if ! command -v "$DRAW_IO" &>/dev/null; then + echo "Error: draw.io executable not found. Please install draw.io and make sure it's in your PATH." + exit 1 +fi + +for SOURCE in "$SOURCE_DIR"/*.drawio; do + BASENAME=$(basename "$SOURCE" .drawio) + + for theme in "dark" "light"; do + mkdir -p "${TARGET_DIR}/${theme}" + TARGET="${TARGET_DIR}/${theme}/${BASENAME}.${FORMAT}" + if [[ "$SOURCE" -nt "${TARGET}" ]]; then + echo "Exporting ${BASENAME} -> $theme/${BASENAME}.$FORMAT" + "$DRAW_IO" --export --format ${FORMAT} --scale 2.5 --svg-theme "${theme}" --no-sandbox -o "${TARGET}" "$SOURCE" + # Remove DOCTYPE to prevent SVGO entity count errors during build + sed -i '/ +
LIVE — must be online during the session
LATER — anyone, anytime
Prover
Notary
Server
MPC / proxy
TLS (MPC mode)
TLS (proxy mode)
a delegated verifier · verifies the session · blind to your data
Attestation
signed by the notary
signs
Attestation verifier
Attestation verifier
Attestation verifier
verify the attestation · trust the notary
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/dark/self_verify.svg b/blog/2026-06-05-public-verifiability/dark/self_verify.svg new file mode 100644 index 0000000..85a97d7 --- /dev/null +++ b/blog/2026-06-05-public-verifiability/dark/self_verify.svg @@ -0,0 +1,2 @@ + +
You're online — and the only one who needs convincing
Prover
You =
Verifier
Server
MPC / proxy
TLS (MPC mode)
TLS (proxy mode)
in the session · verifies the session — no notary · no attestation · trust no one
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/dark/witness_needed.svg b/blog/2026-06-05-public-verifiability/dark/witness_needed.svg new file mode 100644 index 0000000..7438bb0 --- /dev/null +++ b/blog/2026-06-05-public-verifiability/dark/witness_needed.svg @@ -0,0 +1,2 @@ + +
A session you ran alone
A session with a witness
You =
Client
Server
TLS · same key 🔑
Transcript
you can forge it
produces
you hold the server's key — nothing stops you rewriting it · proves nothing
You =
Prover
Server
Witness =
Verifier
TLS (MPC mode)
MPC / proxy
TLS (proxy mode)
a second party is in the session while it happens · now it can be proven ✓
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/delegated_verifier.drawio b/blog/2026-06-05-public-verifiability/delegated_verifier.drawio new file mode 100644 index 0000000..0d776be --- /dev/null +++ b/blog/2026-06-05-public-verifiability/delegated_verifier.drawio @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/blog/2026-06-05-public-verifiability/index.md b/blog/2026-06-05-public-verifiability/index.md new file mode 100644 index 0000000..3d5bd9d --- /dev/null +++ b/blog/2026-06-05-public-verifiability/index.md @@ -0,0 +1,142 @@ +--- +title: "Zero-knowledge ≠ trustless: what \"publicly verifiable\" means for zkTLS" +authors: [heeckhau] +description: "A zkTLS proof isn't trustless math anyone can check on their own. It's a notarized attestation, and \"publicly verifiable\" means verifiable by anyone who trusts the notary. Here is why a witness is unavoidable, and what the words actually mean." +--- + +import Figure from '@site/src/components/Figure'; + +There's a common misconception that a zkTLS proof works like a zkSNARK on a blockchain: a self-contained Zero Knowledge Proof that anyone, anywhere, can verify, with no trust in anyone. You generate it, you publish it, the world checks it. Forever. + +Unfortunately, that is **not** how zkTLS works, and it is a common source of confusion. This post is about what "publicly verifiable" actually means for a zkTLS proof, whom you're trusting when you check one, and why that turns out to be a feature rather than a flaw. + + + +The one line to keep in your head: + +> A zkTLS proof isn't checked by the world. It's checked by whoever trusts the verifier that witnessed it. + +## You can't prove a TLS session by yourself + +A screenshot of your bank balance proves nothing. You could have edited it, and everyone knows it, which is why no one accepts screenshots anymore as proof of anything that matters. + +TLS has the same problem, for a precise reason. In a TLS session the client and the server share the same symmetric key, and that key is what "authenticates" the data. TLS guarantees authenticity *only to the two parties in the connection*. As the client, you hold the very key the server used, so you can produce a transcript that says whatever you like, and the server never signed the bytes to prove otherwise. A TLS session you ran by yourself is exactly as convincing as a screenshot: not at all. + +So if you want to convince someone else that a website really told you something, you need a second party in the session **while it happens**: a witness. And here is the part that trips people up: you cannot add that witness after the fact. Once the session is over, there is nothing left to anchor a proof to. No amount of clever cryptography applied afterward can manufacture trust in a moment that no one witnessed. + +
+ +This is also why "serverless zkTLS, entirely in your browser, no third party" cannot convince anyone of anything. With no second party in the session, there is simply nothing for the rest of us to believe. + +Cryptographers have a precise name for this shape: zkTLS is a **designated-verifier** protocol. The proof convinces *only* the party that took part in the session. The reason is subtle but important: because the verifier participates, it *could* have collaborated with the prover to fabricate the entire exchange. If you are the verifier, you know you didn't, so the proof is ironclad to you. Anyone else has no way to rule out that collusion, so to them the proof is only as good as their trust that the verifier played fair. Every zkTLS protocol today is designated-verifier in this way. + +That one property drives everything below: to convince *yourself*, be the verifier; to convince *anyone else*, they have to trust whoever the verifier was. + +## So who is the witness? It depends on who needs convincing + +The witness, the party in the session, is called the **verifier**. In TLSNotary it's either an *MPC-TLS verifier* or a *proxy verifier* depending on the mode, but in both modes it has to be online during the session. The only real question is: who plays that role? + +| Who needs convincing, and can they be in the session? | Who is the verifier | What you trust | +|---|---|---| +| Just you, online during the session | you are the verifier | nobody | +| Anyone who can't be in the session: offline, asynchronous, or many at once | a delegated verifier (a **notary**) | the notary | + +If you are the one who needs convincing and you can be online, you're done. You run the verifier yourself, you participate in the session, and you trust no one: the cryptography guarantees the prover cannot lie to you. + +
+ +But a lot of real use cases are the other kind, where whoever needs convincing *can't* be in the session: + +- The party who needs convincing often isn't around when the session happens. A smart contract can't co-run a TLS handshake. A backend wants to check the result tomorrow. A reviewer looks at it next week. +- Or there are many parties who each want to check the same result. They can't all be in the session at once. + +In both cases someone has to play the verifier *during* the session on everyone else's behalf. That stand-in is a **notary**. + +## Most of the confusion is terminology + +Most of the confusion around zkTLS is really *terminology* confusion, and two words do most of the damage. If any of this tripped you up, that's on the words, not on you. + +The first word is **"proof."** What you walk away with is usually not a self-contained proof at all. It's an **attestation**: a statement *signed* by whoever witnessed the session. (Sometimes a genuine zero-knowledge proof is layered on top, which we get to below.) + +The second word is **"verifier,"** which gets stretched across two completely different jobs: + +| Role | What it checks | When | Who can do it | Trust cost | +|---|---|---|---|---| +| **Verifier** (MPC-TLS or proxy) | the live session | during | one party, online | nothing (you can trust yourself) | +| **Notary** | the live session | during | a delegated stand-in | trust the notary | +| **Attestation verifier** | the notary's attestation | afterward | anyone, anywhere, anytime | inherits the notary's trust | + +Two facts make this much clearer than the single word "verifier" ever does: + +1. **A notary is just a verifier you didn't run yourself.** It is not a special authority bolted onto the protocol. It is the same in-the-session role, performed by a third party because you couldn't be there (the wider zkTLS ecosystem often calls this role an **attestor**, same thing). And thanks to the multi-party computation, the notary does this **without ever seeing your data in the clear**: it vouches that the session was real with a particular server while staying blind to the contents. +2. **The notary's output is an attestation**, a signed statement along the lines of: *"I was in a genuine TLS session with server X; here are cryptographic commitments to what was exchanged."* Anyone who later receives that attestation can check it. We'll call them the **attestation verifier**, and there can be as many of them as you like. + +
+ +The chain is now unambiguous: a **notary** (a delegated verifier) produces an **attestation**, which any number of **attestation verifiers** check afterward. Notice the seat-swap against the first diagram: the in-session role that *you* filled when you verified for yourself is exactly the role the notary fills here. Nothing new was added to the protocol; the role was simply handed to someone else. + +## Where the zero-knowledge actually lives + +So where does the "zk" come in? It does real work, just not the work a lot of people assume. + +Zero-knowledge in zkTLS does **two** things. It proves that **whatever you do reveal faithfully matches what was committed during the session**: you can't disclose a doctored excerpt. And it lets the prover **reveal only part** of the data and keep the rest hidden: show the balance without the account number, prove you're over 18 without your birth date. Both are pure cryptography; neither needs trust. + +What zero-knowledge *cannot* do is convince a non-participant that the session it all hangs from was real in the first place. That the notary truly witnessed a genuine TLS connection with the claimed server, and didn't quietly collude with the prover to invent it, is not something math can prove to an outsider. That is the designated-verifier gap, and it rests on trusting the notary. + +So the honest split isn't "privacy vs. everything else." It's three layers: + +| What you're relying on | Provided by | Trust required | +|---|---|---| +| Only part of the data is revealed | zero-knowledge / selective disclosure | none (pure math) | +| What's revealed matches the witnessed session | zero-knowledge | none (pure math) | +| The session was genuinely witnessed at all | the verifier / notary in the session | the notary, if delegated | + +This inverts the usual intuition. In zkTLS your **privacy is cryptographic**, and so is the **integrity of what you disclose**: the notary stays mathematically blind, and the prover can't fake an excerpt. The one thing that *isn't* cryptographic, the one thing an outsider has to take on trust, is that the witness was honest. People expect the trust to live in the data; it actually lives in the witness. (It's also why a TEE-based attestor that *sees* your data and signs for it offers the same trust-in-the-witness but strictly weaker privacy: its confidentiality is contingent on a signature, not on math.) + +> Zero-knowledge keeps your data private and your disclosures honest. It still can't vouch for a session that no trustworthy party witnessed. + +## So, can anyone verify a zkTLS proof? + +Now we can answer it precisely: yes, and no; the gap between the two is the whole point. + +**Yes:** anyone can be an attestation verifier. Hand the attestation to a thousand people and all thousand can check it: produce once, show to anyone, indefinitely. That part is genuinely public. + +**No:** that check only means something if you trust the notary that made the attestation. For there to be an attestation at all, a verifier had to be in the session, and if that verifier wasn't you (it can't be; you weren't there), it was a notary you are trusting. + +So "publicly verifiable" and "trustless" pull in opposite directions. The very thing that makes a proof checkable by everyone (delegating the in-session role so the result becomes portable) is the thing that introduces the notary. You don't get public verifiability and zero trust at the same time; you get public verifiability *because* you accepted a notary. + +> **"But zkTLS proofs verify on-chain!"** A smart contract can't take part in a TLS session, and a designated-verifier proof means nothing to a non-participant, so on-chain there is always a **signature standing in for a proof**. Everything the contract does is *downstream of the notary's signature*: the chain verifies that signature, and any logic built on top of it, but it does not, and cannot, re-witness the session. The trust in the notary didn't go away; it's just expressed as a trusted public key. + +## Minimizing the trust you took on + +The honest move isn't to pretend the trust disappeared. It's to name it, and then shrink it. Once delegation is unavoidable, you have a dial: + +- **Run the verifier yourself.** No notary, no third-party trust. Best when you're the only one who needs convincing and you can be online. Not portable to anyone else. +- **One reputable notary.** Simple and portable. Everyone downstream trusts that one operator. +- **Multiple independent notaries (M-of-N).** Require separately signed attestations from several independent notaries and accept the result only if enough of them agree. Each notary signs on its own, which rules out collusion between the prover and any single notary: a malicious prover would have to corrupt a whole quorum. Note this is *not* the same as splitting the notary role *itself* across several parties with MPC, so that no single machine ever sees the data or can sign alone. That would be stronger still (there would be no single notary to trust), but a multi-party MPC notary is not yet practical. +- **On-chain, economically-secured notaries.** Notaries that stake collateral and can be slashed for misbehavior, turning "trust the operator" into "trust the incentives." This is the most trust-minimized end of the dial. It isn't something TLSNotary ships itself; it's what ecosystem projects build *on top of* zkTLS (for example Opacity Labs, via restaking). + +This is also why TLSNotary, by itself, does not solve the [oracle problem](/docs/faq#does-tlsnotary-solve-the-oracle-problem). A notary is a trusted party, and bringing data on-chain through a single trusted party inherits that trust. zkTLS doesn't dissolve the trusted party: it makes it explicit, swappable, and shrinkable. For high-stakes data, combine it with the trust-minimizing options above, or with a dedicated oracle protocol. + +## The bottom line + +A zkTLS proof is not trustless math that the whole world checks unconditionally. It's a notarized attestation. Anyone can be an attestation verifier, but the attestation only exists because a verifier was in the session, and unless that verifier was you, it was a notary you trust. + +So when you build with zkTLS, the real design question isn't "is it publicly verifiable?" It's **who needs convincing, and can they be in the session?** Are you the only one who needs convincing, and can you be online? Run the verifier yourself. Is the result for a contract, a backend, or the public? Then you're delegating to a notary, so decide how much you trust it and how many you require. That choice is your trust model. Make it on purpose. + +For the mechanics underneath all this, see [TLS verification with a general-purpose Notary](/docs/intro#tls-verification-with-a-general-purpose-notary) and the FAQ entries on [why TLSNotary needs an online verifier](/docs/faq#why-does-tlsnotary-need-an-online-verifier-cant-this-be-done-serverlessly-in-the-browser-with-zero-knowledge) and [why a verifier can trust a TLSNotary proof](/docs/faq#why-can-a-verifier-trust-a-tlsnotary-proof). For the trade-off in the in-session role itself, see the [proxy mode post](/blog/2026/04/22/proxy-mode). \ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/light/delegated_verifier.svg b/blog/2026-06-05-public-verifiability/light/delegated_verifier.svg new file mode 100644 index 0000000..901bcdf --- /dev/null +++ b/blog/2026-06-05-public-verifiability/light/delegated_verifier.svg @@ -0,0 +1,2 @@ + +
LIVE — must be online during the session
LATER — anyone, anytime
Prover
Notary
Server
MPC / proxy
TLS (MPC mode)
TLS (proxy mode)
a delegated verifier · verifies the session · blind to your data
Attestation
signed by the notary
signs
Attestation verifier
Attestation verifier
Attestation verifier
verify the attestation · trust the notary
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/light/self_verify.svg b/blog/2026-06-05-public-verifiability/light/self_verify.svg new file mode 100644 index 0000000..e08ae19 --- /dev/null +++ b/blog/2026-06-05-public-verifiability/light/self_verify.svg @@ -0,0 +1,2 @@ + +
You're online — and the only one who needs convincing
Prover
You =
Verifier
Server
MPC / proxy
TLS (MPC mode)
TLS (proxy mode)
in the session · verifies the session — no notary · no attestation · trust no one
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/light/witness_needed.svg b/blog/2026-06-05-public-verifiability/light/witness_needed.svg new file mode 100644 index 0000000..b5829c8 --- /dev/null +++ b/blog/2026-06-05-public-verifiability/light/witness_needed.svg @@ -0,0 +1,2 @@ + +
A session you ran alone
A session with a witness
You =
Client
Server
TLS · same key 🔑
Transcript
you can forge it
produces
you hold the server's key — nothing stops you rewriting it · proves nothing
You =
Prover
Server
Witness =
Verifier
TLS (MPC mode)
MPC / proxy
TLS (proxy mode)
a second party is in the session while it happens · now it can be proven ✓
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/self_verify.drawio b/blog/2026-06-05-public-verifiability/self_verify.drawio new file mode 100644 index 0000000..7b7c5de --- /dev/null +++ b/blog/2026-06-05-public-verifiability/self_verify.drawio @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/blog/2026-06-05-public-verifiability/witness_needed.drawio b/blog/2026-06-05-public-verifiability/witness_needed.drawio new file mode 100644 index 0000000..286d957 --- /dev/null +++ b/blog/2026-06-05-public-verifiability/witness_needed.drawio @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 7b6367056d5db9b32b191e96459b05dc8c51f7ec Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Tue, 16 Jun 2026 10:27:13 +0200 Subject: [PATCH 2/3] blog: update public-verifiability post date to June 17 --- .../dark/self_verify.svg | 2 -- .../dark/witness_needed.svg | 2 -- .../light/self_verify.svg | 2 -- .../light/witness_needed.svg | 2 -- .../convert_all.sh | 0 .../dark/delegated_verifier.svg | 0 .../dark/self_verify.svg | 3 +++ .../dark/witness_needed.svg | 3 +++ .../delegated_verifier.drawio | 0 .../index.md | 3 ++- .../light/delegated_verifier.svg | 0 .../light/self_verify.svg | 3 +++ .../light/witness_needed.svg | 3 +++ .../self_verify.drawio | 12 ++++++------ .../witness_needed.drawio | 10 +++++----- 15 files changed, 25 insertions(+), 20 deletions(-) delete mode 100644 blog/2026-06-05-public-verifiability/dark/self_verify.svg delete mode 100644 blog/2026-06-05-public-verifiability/dark/witness_needed.svg delete mode 100644 blog/2026-06-05-public-verifiability/light/self_verify.svg delete mode 100644 blog/2026-06-05-public-verifiability/light/witness_needed.svg rename blog/{2026-06-05-public-verifiability => 2026-06-17-public-verifiability}/convert_all.sh (100%) rename blog/{2026-06-05-public-verifiability => 2026-06-17-public-verifiability}/dark/delegated_verifier.svg (100%) create mode 100644 blog/2026-06-17-public-verifiability/dark/self_verify.svg create mode 100644 blog/2026-06-17-public-verifiability/dark/witness_needed.svg rename blog/{2026-06-05-public-verifiability => 2026-06-17-public-verifiability}/delegated_verifier.drawio (100%) rename blog/{2026-06-05-public-verifiability => 2026-06-17-public-verifiability}/index.md (98%) rename blog/{2026-06-05-public-verifiability => 2026-06-17-public-verifiability}/light/delegated_verifier.svg (100%) create mode 100644 blog/2026-06-17-public-verifiability/light/self_verify.svg create mode 100644 blog/2026-06-17-public-verifiability/light/witness_needed.svg rename blog/{2026-06-05-public-verifiability => 2026-06-17-public-verifiability}/self_verify.drawio (79%) rename blog/{2026-06-05-public-verifiability => 2026-06-17-public-verifiability}/witness_needed.drawio (91%) diff --git a/blog/2026-06-05-public-verifiability/dark/self_verify.svg b/blog/2026-06-05-public-verifiability/dark/self_verify.svg deleted file mode 100644 index 85a97d7..0000000 --- a/blog/2026-06-05-public-verifiability/dark/self_verify.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
You're online — and the only one who needs convincing
Prover
You =
Verifier
Server
MPC / proxy
TLS (MPC mode)
TLS (proxy mode)
in the session · verifies the session — no notary · no attestation · trust no one
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/dark/witness_needed.svg b/blog/2026-06-05-public-verifiability/dark/witness_needed.svg deleted file mode 100644 index 7438bb0..0000000 --- a/blog/2026-06-05-public-verifiability/dark/witness_needed.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
A session you ran alone
A session with a witness
You =
Client
Server
TLS · same key 🔑
Transcript
you can forge it
produces
you hold the server's key — nothing stops you rewriting it · proves nothing
You =
Prover
Server
Witness =
Verifier
TLS (MPC mode)
MPC / proxy
TLS (proxy mode)
a second party is in the session while it happens · now it can be proven ✓
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/light/self_verify.svg b/blog/2026-06-05-public-verifiability/light/self_verify.svg deleted file mode 100644 index e08ae19..0000000 --- a/blog/2026-06-05-public-verifiability/light/self_verify.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
You're online — and the only one who needs convincing
Prover
You =
Verifier
Server
MPC / proxy
TLS (MPC mode)
TLS (proxy mode)
in the session · verifies the session — no notary · no attestation · trust no one
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/light/witness_needed.svg b/blog/2026-06-05-public-verifiability/light/witness_needed.svg deleted file mode 100644 index b5829c8..0000000 --- a/blog/2026-06-05-public-verifiability/light/witness_needed.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
A session you ran alone
A session with a witness
You =
Client
Server
TLS · same key 🔑
Transcript
you can forge it
produces
you hold the server's key — nothing stops you rewriting it · proves nothing
You =
Prover
Server
Witness =
Verifier
TLS (MPC mode)
MPC / proxy
TLS (proxy mode)
a second party is in the session while it happens · now it can be proven ✓
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/convert_all.sh b/blog/2026-06-17-public-verifiability/convert_all.sh similarity index 100% rename from blog/2026-06-05-public-verifiability/convert_all.sh rename to blog/2026-06-17-public-verifiability/convert_all.sh diff --git a/blog/2026-06-05-public-verifiability/dark/delegated_verifier.svg b/blog/2026-06-17-public-verifiability/dark/delegated_verifier.svg similarity index 100% rename from blog/2026-06-05-public-verifiability/dark/delegated_verifier.svg rename to blog/2026-06-17-public-verifiability/dark/delegated_verifier.svg diff --git a/blog/2026-06-17-public-verifiability/dark/self_verify.svg b/blog/2026-06-17-public-verifiability/dark/self_verify.svg new file mode 100644 index 0000000..6d13cc7 --- /dev/null +++ b/blog/2026-06-17-public-verifiability/dark/self_verify.svg @@ -0,0 +1,3 @@ + + +
You're online — and the only one who needs convincing
Prover
You =
Verifier
Server
MPC / proxy
TLS (MPC mode)
TLS (proxy mode)
in the session · verifies the session — no notary · no attestation · trust no one
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-17-public-verifiability/dark/witness_needed.svg b/blog/2026-06-17-public-verifiability/dark/witness_needed.svg new file mode 100644 index 0000000..a013699 --- /dev/null +++ b/blog/2026-06-17-public-verifiability/dark/witness_needed.svg @@ -0,0 +1,3 @@ + + +
A session you ran alone
A session with a witness
You =
Client
Server
TLS · same key 🔑
Transcript
you can forge it
produces
you hold the server's key and nothing stops you rewriting it
proves nothing
You =
Prover
Server
Witness =
Verifier
TLS (MPC mode)
MPC / proxy
TLS (proxy mode)
a second party is in the session while it happens · now it can be proven ✓
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/delegated_verifier.drawio b/blog/2026-06-17-public-verifiability/delegated_verifier.drawio similarity index 100% rename from blog/2026-06-05-public-verifiability/delegated_verifier.drawio rename to blog/2026-06-17-public-verifiability/delegated_verifier.drawio diff --git a/blog/2026-06-05-public-verifiability/index.md b/blog/2026-06-17-public-verifiability/index.md similarity index 98% rename from blog/2026-06-05-public-verifiability/index.md rename to blog/2026-06-17-public-verifiability/index.md index 3d5bd9d..c08f0e8 100644 --- a/blog/2026-06-05-public-verifiability/index.md +++ b/blog/2026-06-17-public-verifiability/index.md @@ -128,7 +128,8 @@ The honest move isn't to pretend the trust disappeared. It's to name it, and the - **Run the verifier yourself.** No notary, no third-party trust. Best when you're the only one who needs convincing and you can be online. Not portable to anyone else. - **One reputable notary.** Simple and portable. Everyone downstream trusts that one operator. -- **Multiple independent notaries (M-of-N).** Require separately signed attestations from several independent notaries and accept the result only if enough of them agree. Each notary signs on its own, which rules out collusion between the prover and any single notary: a malicious prover would have to corrupt a whole quorum. Note this is *not* the same as splitting the notary role *itself* across several parties with MPC, so that no single machine ever sees the data or can sign alone. That would be stronger still (there would be no single notary to trust), but a multi-party MPC notary is not yet practical. +- **Multiple independent notaries (M-of-N).** Require separately signed attestations from several independent notaries and accept the result only if enough of them agree. Each notary signs on its own, which rules out collusion between the prover and any single notary: a malicious prover would have to corrupt a whole quorum. +Note this is *not* the same as splitting the notary role *itself* across several parties with MPC, so that no single machine ever sees the data or can sign alone. That would be stronger still (there would be no single notary to trust), but a multi-party MPC notary is not yet practical. - **On-chain, economically-secured notaries.** Notaries that stake collateral and can be slashed for misbehavior, turning "trust the operator" into "trust the incentives." This is the most trust-minimized end of the dial. It isn't something TLSNotary ships itself; it's what ecosystem projects build *on top of* zkTLS (for example Opacity Labs, via restaking). This is also why TLSNotary, by itself, does not solve the [oracle problem](/docs/faq#does-tlsnotary-solve-the-oracle-problem). A notary is a trusted party, and bringing data on-chain through a single trusted party inherits that trust. zkTLS doesn't dissolve the trusted party: it makes it explicit, swappable, and shrinkable. For high-stakes data, combine it with the trust-minimizing options above, or with a dedicated oracle protocol. diff --git a/blog/2026-06-05-public-verifiability/light/delegated_verifier.svg b/blog/2026-06-17-public-verifiability/light/delegated_verifier.svg similarity index 100% rename from blog/2026-06-05-public-verifiability/light/delegated_verifier.svg rename to blog/2026-06-17-public-verifiability/light/delegated_verifier.svg diff --git a/blog/2026-06-17-public-verifiability/light/self_verify.svg b/blog/2026-06-17-public-verifiability/light/self_verify.svg new file mode 100644 index 0000000..dc7b0b1 --- /dev/null +++ b/blog/2026-06-17-public-verifiability/light/self_verify.svg @@ -0,0 +1,3 @@ + + +
You're online — and the only one who needs convincing
Prover
You =
Verifier
Server
MPC / proxy
TLS (MPC mode)
TLS (proxy mode)
in the session · verifies the session — no notary · no attestation · trust no one
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-17-public-verifiability/light/witness_needed.svg b/blog/2026-06-17-public-verifiability/light/witness_needed.svg new file mode 100644 index 0000000..49ee506 --- /dev/null +++ b/blog/2026-06-17-public-verifiability/light/witness_needed.svg @@ -0,0 +1,3 @@ + + +
A session you ran alone
A session with a witness
You =
Client
Server
TLS · same key 🔑
Transcript
you can forge it
produces
you hold the server's key and nothing stops you rewriting it
proves nothing
You =
Prover
Server
Witness =
Verifier
TLS (MPC mode)
MPC / proxy
TLS (proxy mode)
a second party is in the session while it happens · now it can be proven ✓
Text is not SVG - cannot display
\ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/self_verify.drawio b/blog/2026-06-17-public-verifiability/self_verify.drawio similarity index 79% rename from blog/2026-06-05-public-verifiability/self_verify.drawio rename to blog/2026-06-17-public-verifiability/self_verify.drawio index 7b7c5de..7114c57 100644 --- a/blog/2026-06-05-public-verifiability/self_verify.drawio +++ b/blog/2026-06-17-public-verifiability/self_verify.drawio @@ -1,11 +1,11 @@ - + - + - - + + @@ -26,9 +26,9 @@ - + - + \ No newline at end of file diff --git a/blog/2026-06-05-public-verifiability/witness_needed.drawio b/blog/2026-06-17-public-verifiability/witness_needed.drawio similarity index 91% rename from blog/2026-06-05-public-verifiability/witness_needed.drawio rename to blog/2026-06-17-public-verifiability/witness_needed.drawio index 286d957..25a6d86 100644 --- a/blog/2026-06-05-public-verifiability/witness_needed.drawio +++ b/blog/2026-06-17-public-verifiability/witness_needed.drawio @@ -1,6 +1,6 @@ - + - + @@ -20,12 +20,12 @@ - + - + @@ -58,4 +58,4 @@ - + \ No newline at end of file From baa6540c7cdbbbd10226661f294a6c3ac63ef1fe Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Wed, 17 Jun 2026 10:02:33 +0200 Subject: [PATCH 3/3] blog: clarify proof vs attestation as a transferability distinction Address PR feedback by stating explicitly that an in-session proof convinces only the witness, while signing it into an attestation is what makes the claim portable. Keeps the colloquial "zkTLS proof" wording rather than renaming the concept. --- blog/2026-06-17-public-verifiability/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2026-06-17-public-verifiability/index.md b/blog/2026-06-17-public-verifiability/index.md index c08f0e8..ab6ec31 100644 --- a/blog/2026-06-17-public-verifiability/index.md +++ b/blog/2026-06-17-public-verifiability/index.md @@ -66,7 +66,7 @@ In both cases someone has to play the verifier *during* the session on everyone Most of the confusion around zkTLS is really *terminology* confusion, and two words do most of the damage. If any of this tripped you up, that's on the words, not on you. -The first word is **"proof."** What you walk away with is usually not a self-contained proof at all. It's an **attestation**: a statement *signed* by whoever witnessed the session. (Sometimes a genuine zero-knowledge proof is layered on top, which we get to below.) +The first word is **"proof."** What you walk away with is usually not a self-contained proof at all. It's an **attestation**: a statement *signed* by whoever witnessed the session. The distinction that matters is transferability: an in-session proof convinces only the witness, and signing it into an attestation is what makes that same claim portable, so anyone can check it later. (Sometimes a genuine zero-knowledge proof is layered on top, which we get to below.) The second word is **"verifier,"** which gets stretched across two completely different jobs: