From 682323cb5b332a2d6d94c104471d679c7105a12a Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Tue, 9 Jun 2026 17:53:36 +0200 Subject: [PATCH 1/6] blog: draft 'Where does your trust live?' post on cryptographic soundness vs TEEs A friendly, principle-first piece on Peer's zkTLS->TEE switch: same on-chain integrity, but privacy moves from a structural/cryptographic guarantee (plaintext never leaves the device) to one contingent on a signature. Includes the 'where the plaintext lives' and 'three anchors' diagrams (light/dark), and the 'you can have both' synthesis (zkTLS verifier inside a TEE). Cross-links the public-verifiability companion post (#62). --- .../dark/plaintext_boundary.svg | 65 ++++++++ .../dark/three_anchors.svg | 37 +++++ blog/2026-06-06-where-trust-lives/index.md | 140 ++++++++++++++++++ .../light/plaintext_boundary.svg | 65 ++++++++ .../light/three_anchors.svg | 37 +++++ 5 files changed, 344 insertions(+) create mode 100644 blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg create mode 100644 blog/2026-06-06-where-trust-lives/dark/three_anchors.svg create mode 100644 blog/2026-06-06-where-trust-lives/index.md create mode 100644 blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg create mode 100644 blog/2026-06-06-where-trust-lives/light/three_anchors.svg diff --git a/blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg b/blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg new file mode 100644 index 0000000..15cb9e1 --- /dev/null +++ b/blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + device boundary + + + zkTLS (proxy) + + + + YOUR DEVICE + + credential + response + decrypted on your device + + + + proof — only the bytes you reveal + + + + Attestor signs + sees only ciphertext + + Plaintext stays on your device + + + + + + TEE-TLS (enclave) + + + + YOUR DEVICE + + credential + encrypt → enclave key + + + + encrypted credential + + + + ENCLAVE · operator hardware + + your plaintext, decrypted (~1s) + + + + attestation + + Plaintext leaves your device + diff --git a/blog/2026-06-06-where-trust-lives/dark/three_anchors.svg b/blog/2026-06-06-where-trust-lives/dark/three_anchors.svg new file mode 100644 index 0000000..c77a015 --- /dev/null +++ b/blog/2026-06-06-where-trust-lives/dark/three_anchors.svg @@ -0,0 +1,37 @@ + + + + + + + + + + 1 + An operator is honest + trust: one operator's word + + + + + 2 + This exact code ran in isolated hardware + trust: a hardware vendor's signing key + + + + + 3 + Mathematically true, whoever ran it + trust: no one; the proof is public + + + + Same kind of trust + a secret someone else holds + + + + A different kind + no secret to hold + diff --git a/blog/2026-06-06-where-trust-lives/index.md b/blog/2026-06-06-where-trust-lives/index.md new file mode 100644 index 0000000..ae371bf --- /dev/null +++ b/blog/2026-06-06-where-trust-lives/index.md @@ -0,0 +1,140 @@ +--- +title: "Where does your trust live? Cryptographic soundness and the TEE trade" +# authors: [sinu, heeckhau] +description: "Moving a web proof from zkTLS to a TEE keeps the same on-chain result, and can even raise the integrity bar. The honest question is privacy: do you trust a guarantee rooted in mathematics, or one rooted in a signature from a chip?" +--- + +import Figure from '@site/src/components/Figure'; + +Web proofs opened up a whole class of applications: proving your bank balance, your income, a payment, or your identity to an app that otherwise has no way to trust it. And across all of them, the number one feature request is always the same, speed. As our recent posts on [proxy-mode benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode) and the [full-reveal fast path](https://tlsnotary.org/blog/2026/05/19/fast-reveal) keep showing, users do not want to wait for a proof. + +One application we are genuinely fans of is [Peer](https://docs.peer.xyz), a noncustodial fiat-to-crypto protocol. They just announced moving their payment verification from zkTLS to a TEE, running inside AWS Nitro Enclaves, and the reason is unsurprisingly "speed": from about thirty seconds down to under a second. That is a real win, so it is worth looking honestly at what the move buys and what it costs. + +None of this is an attack on Peer; we want them to win. The point is more general. Any system that proves "this web data is real" has to root that promise somewhere, and swapping the technology underneath rarely removes the trust. It relocates it. So the real question is never trust versus no trust. It is where the trust now lives, and whether you can still see it from there. That is what this post is about. + + + +Peer's Sachin wrote up the reasoning in a clear, public [post](https://x.com/0xSachinK/status/2062860592906731888). It is a thoughtful, well-engineered decision, and explaining the trade in public is the honest thing to do. So we are going to engage it on the merits. The argument here is not that the hardware can be broken; it is that even when the hardware works exactly as designed, the guarantee still comes down to a signature. + +## TL;DR + +- This is **not really a security or trust argument**. On-chain, both approaches end at the same signed attestation, and against a single attestor a TEE can even *raise* the integrity bar. +- It is a **privacy argument**, and a change of *basis*. With zkTLS your credential never leaves your device; only a proof does. With a TEE your credential leaves your device and is decrypted inside someone else's hardware, and the promise it stays private rests on a **signature**, not on mathematics. +- And the failure is **silent**. A forged attestation verifies exactly like a real one, so a user has **no way to detect foul play**. The guarantee can break without anyone noticing. +- That distinction is invisible when everything works and decisive when it does not. It is the whole reason not to treat the two as equivalent. + +## Both roads end at a signature + +Start with the thing that does not change. zkTLS, TLSNotary included, is a **designated-verifier** technology: the proof convinces only the party that took part in the session, and a smart contract cannot be that party. So on-chain there is always a trusted attestor that signs a statement in lieu of a proof, and the contract checks the signature. (We unpack why an in-session witness is unavoidable, and what "publicly verifiable" really means, in a [companion post](/blog/2026/06/05/public-verifiability).) + +The upshot for us is simple: if your funds release on an attestor's signature, you are trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. Which is exactly why Peer's integrity argument lands. Their prior production system was proxy-based zkTLS with a **single attestor**, and a single attestor that is compromised or colluding can sign off on a payment that never happened. Move the signing key inside a Nitro Enclave, wrap it under a KMS policy that only releases it to an enclave whose measured identity matches the published build, and now forging an attestation means breaking the hardware's isolation or subverting KMS, not just leaning on one server. As Sachin puts it, *"the trust anchor moves from 'an operator is honest' to 'this exact code ran in isolated hardware.'"* + +That is a real improvement over trusting an operator's word. We are not going to pretend otherwise. The integrity story is defensible. Hold onto that phrase, *the trust anchor moves*, because the rest of this post is about reading the fine print on where it moves to. + +## So what actually changed? Where the plaintext goes + +Here is the difference that matters, and it is almost geometric. + +In the proxy-zkTLS flow Peer used to run, the buyer's device holds the TLS session. The witness proxy sees only ciphertext. The buyer decrypts *on their own machine*, generates a proof that the response contained the right payment detail, and the attestor signs off on that proof. The sensitive bytes (the session token, the full bank response) **never leave the user's device** in the clear. What leaves is a proof, and the user chooses exactly which bytes it reveals. That last part has a name: selective disclosure. It is the core privacy primitive of this entire field. + +In the TEE flow, the PeerAuth extension reads your live session token and **encrypts it to the enclave's public key**. The enclave then makes the authenticated request itself, sees the full plaintext response, checks it, and emits the attestation. The credential and the response now exist, in the clear, inside a machine the operator runs. Selective disclosure is gone: the enclave sees everything, and you trust it to emit only the attestation and forget the rest. + +
+ +So the plaintext crossed a boundary it never used to cross. That is the whole ballgame. + +## Identical, until it is not + +This is where the honest disagreement lives, and both sides are describing the *same facts*. + +Peer's case is strong on its own terms: nothing is stored, the enclave boots from a read-only image, the credential lives in memory for about a second and is wiped, and the only thing that leaves is the attestation. Sachin's conclusion: *"the privacy guarantees are identical to zkTLS, with better UX."* In good faith, operationally, on a day when everything works exactly as designed, that is a fair description. + +Our objection is not to any of those facts. It is to the word *identical*, because it quietly swaps the **basis** of the guarantee: + +> With zkTLS, the confidentiality of your credential is **structural and cryptographic**: it is a fact about *where the computation happened* (your device) and *what mathematically left it* (a proof). With a TEE, the confidentiality is **contingent on a signature**: an attestation that says "the code that saw your plaintext was the published code, running in isolated hardware that promises not to leak it." Strictly speaking, that is weaker, even when the integrity is the same. + +A cryptographic guarantee holds whether or not the operator is honest, whether or not the hardware vendor was compelled, whether or not there is a bug you did not find. An attestation-backed guarantee holds *as long as the attestation means what you think it means*, as long as the measured code is bug-free, the isolation is real, the vendor's keys are clean, and the enclave actually does what its source says. Those are reasonable things to believe. They are not the same kind of thing as "the plaintext never left your phone." + +None of this says Peer's enclave does anything wrong; by all appearances it is careful work. The point is narrower: the *shape* of the guarantee changed, from one that cannot fail in these ways to one that, in principle, could. And that kind of difference tends to stay invisible right up until the day it matters. + +## Can you check it yourself? + +Peer deserves real credit here, because they did not hand-wave this. They ship an npm package, [`@zkp2p/zkp2p-attestation`](https://www.npmjs.com/package/@zkp2p/zkp2p-attestation), that lets a client fetch the enclave's attestation document, verify AWS's Nitro signature chain, and check the PCR measurements and signer. `GET /attestation` returns a fresh, AWS-signed document. That is genuinely more than most TEE deployments offer, and it is the right instinct. + +Crucially, the check happens *before* you hand over anything sensitive. The correct pattern, and the one a verifier/encrypter package is built for, is *attest, then encrypt*: the client asks the enclave for an attestation over a fresh nonce; that signed document binds the enclave's public key to its measurement; the client verifies the AWS chain, the measurement, and the nonce; and only *then* encrypts the credential to the key the attestation vouched for. Encrypting to that key is what makes the secret decryptable only inside an enclave running the measured code. It is worth being precise about why, because the intuition that "it is encrypted, so it is fine" is exactly wrong: the encryption alone guarantees nothing. A public key is just bytes, and an *unattested* one could have its private half sitting in ordinary server memory, decrypting your credential outside any enclave at all. The safety comes from verifying the binding first, not from the encryption. + +So yes, you can check beforehand. But notice what that check does and does not settle. It answers "am I talking to a genuine enclave running the expected measurement?" It does not answer the next three questions, and as an actual user on a phone this is where it bottoms out: + +1. **A measurement is a hash, not a meaning.** Verifying that the running enclave matches PCR `abc123` tells you the *expected* image is loaded. To know `abc123` is the *honest* code (the code that wipes your token and emits nothing else), you have to obtain the enclave source, build it reproducibly, and get the same hash. Peer says they *will* open-source the attestation service so anyone can do this. As of writing, that part has not shipped: the verifier is public, the reproducible enclave source is not yet. So today you can confirm "an enclave matching Peer's published measurement ran," but you are still trusting Peer's claim about what that measurement *is*. +2. **Someone has to actually run the check.** On mobile or in a browser, the thing fetching `/attestation` and comparing the measurement is the client Peer ships. A client can verify diligently, or skip it, and the user cannot tell from the outside. Independent verification means an independently built client pinning an independently audited measurement. +3. **AWS is the root, unconditionally.** The signature chains to AWS's attestation keys, and the "host cannot read enclave memory" property is AWS's design and AWS's word. That means you are trusting a single vendor that operates the hardware and holds the root key, and whoever holds that key can be compelled to use it: a lawful order could in principle require the vendor to vouch for a key the requester controls, with a gag order keeping it quiet. You would have no way to tell, because the signature would verify like any other. That is the same silent failure as before, reached through a courtroom rather than an exploit. + +None of these make the design bad. They locate it. The verifiable part is real; the part you still take on faith is real too. + +## Three anchors + +Sachin's framing is the right one, *the trust anchor moves*, so let's just finish the sentence. There are three places a web proof can anchor its trust, and they are not equivalent: + +1. **An operator is honest.** A single attestor signs. Simplest, weakest. This is what Peer moved *away* from, correctly. +2. **This exact code ran in isolated hardware.** A TEE binds the signature to an attested measurement. Stronger, but conditional on a hardware vendor, a measurement you can map to source, and isolation that holds. This is where Peer moved *to*. +3. **This is mathematically true, regardless of who ran it.** No operator to trust, no measurement to map, no vendor at the root. This is what cryptographic soundness buys, and it is why TLSNotary defaults to [MPC-TLS](/docs/protocol/mpc-tls/) and treats every step away from it, including our own [proxy mode](https://tlsnotary.org/blog/2026/04/22/proxy-mode), as a *named, legible* trade rather than a free lunch. + +
+ +But push on anchor 2 and it leans closer to anchor 1 than it first appears. Strip away the silicon and what a verifier actually checks is a *signature*: does this attestation chain to a key I trust? The hardware's real job is to keep that key secret, which means the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave's protection by construction. For Peer that custodian is AWS, which operates both the Nitro attestation root and the KMS that releases the signing key. An unbreakable enclave and an unforgeable attestation are not the same thing: anyone holding that signing key (the vendor, or the vendor compelled to use it) can mint a flawless attestation with no enclave behind it at all. + +In the encrypt-to-the-enclave model, that is not only an integrity problem; it is the entire privacy guarantee. Forge the attestation, bind a key *you* control to the expected measurement, and the victim's client encrypts its credential straight to you. The signature verifies, so nothing looks wrong: the attack is silent, targetable at individual users, and invisible to the victim. The credential was encrypted perfectly, to the wrong party. This is why "contingent on a signature" is not a figure of speech: the confidentiality of your data is exactly as good as the secrecy of a key you will never see. + +That is the difference anchor 3 makes. Mathematics has no key whose compromise hands over your data, because in a soundness-rooted design your plaintext never left your device, so there is nothing to redirect. Anchor 2 is a real upgrade over anchor 1: it moves the trust to a far better-resourced custodian. But it is the *same kind* of trust, a secret key kept by someone else, not the different kind that math provides. The honest pitch for a TEE is "stronger than trusting one operator's word," not "as good as math." + +## Where this is going + +The usual, fair rebuttal at this point is: *math is great, but it is too slow on a phone, which is the whole reason we reached for hardware.* That gap is the thing actually worth racing on, and it is closing from the cryptographic side. + +It is also a smaller gap than the headline suggests. The thirty-second figure comes from an older proxy implementation, not from where cryptographic zkTLS sits today: TLSNotary's current proxy mode already runs in low single-digit seconds (around 1.6s in our [latest benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode)). A sub-second enclave is still faster, but the distance is a long way from thirty-to-one, and it keeps shrinking. + +[SpeakUp](https://privacy-ethereum.github.io/speakup/) is a VOLE-based zkVM built specifically for proving on resource-constrained devices (phones and browsers), trading larger proofs for minimal work on the prover. It is privacy-first and post-quantum by construction. The point, for this discussion, is that it pushes general-purpose **selective disclosure back onto the user's own device**: prove an arbitrary property of your transcript, reveal nothing else, keep the plaintext where it started. That is the exact privacy property the TEE path gives up, recovered without sending your credential anywhere. + +We will not oversell it. SpeakUp is interactive, so it lives in the same designated-verifier world described above: it makes client-side privacy fast; it does not, by itself, make proofs publicly verifiable on-chain. The harder frontier is still open research: an attestor that does not even learn the server or the statement (the "blind notary"), and proofs small enough to verify on-chain. It is stalled mostly on performance and incentives rather than possibility. We are working on it. So is the field. + +## How fast is fast enough? + +The speed argument carries a hidden assumption: that faster is always better. It is not. Speed has a "good enough" point, and the question worth asking is not "how fast can we go" but "are we already fast enough, and what are we paying for the rest?" + +Thirty seconds was genuinely too long, and no one should defend it. But the cryptographic path is not at thirty seconds anymore; it is at a few. A few seconds is fine for most flows, and especially for the ones that matter: someone moving money, proving income for a loan, or settling a trade will gladly wait five seconds for a guarantee rooted in mathematics. The hunger for sub-second speed is sharpest in casual, high-frequency, low-stakes interactions, which is exactly where giving up privacy costs the least. So speed and privacy usually point the same way: when the stakes are high enough to want the stronger guarantee, they are high enough that a short wait is no objection. + +So the honest first question is not "TEE or cryptography," it is "do we even need to make this trade?" Increasingly, the answer is no. + +When raw latency really is the binding constraint and the stakes are genuinely low, a well-built TEE deployment like Peer's is a reasonable, even admirable call. We would only ask one thing of anyone making that trade: name it. Say "we relocated the privacy guarantee from your device to attested hardware, and here is the vendor, the measurement, and the verification tooling you can check." Peer, to their credit, did. The failure mode is not choosing a TEE; it is letting users believe "verified" means cryptography when it means a signature from a chip. + +## You can have both + +Notice what actually did the work in Peer's integrity win. It was not that the enclave saw your data. It was that the signing key was bound to attested code, so the operator could not sign a session that never happened. You can get that without giving up any privacy. + +Run the zkTLS verifier *inside* the enclave. It still sees only ciphertext, because the prover decrypts on-device and proves in zero-knowledge, so your plaintext never leaves your device and the privacy stays structural. The enclave's only job is to stop the operator from signing whatever it likes. That is a TEE used as an integrity bound on top of cryptographic privacy, rather than a replacement for it, and it is close to what TLSNotary already supports through a notary that carries a [TEE attestation of its own code](/docs/protocol/custom_extension). + +It does not make the result trustless. You still trust the vendor for the verifier's integrity, and on-chain it is still a signature. But it buys the integrity Peer is after without moving your credential into someone else's hardware. + +So when the privacy stakes rise, the cryptographic path is right there, for Peer too. TLSNotary is already one of the primitives in their stack. The deeper point is that this was never really speed versus soundness: a TEE can bound the attestor while the cryptography keeps your plaintext on your device. We are rooting for everyone shipping this. We just want the trust to live somewhere you can see it. + + diff --git a/blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg b/blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg new file mode 100644 index 0000000..4e4212f --- /dev/null +++ b/blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + device boundary + + + zkTLS (proxy) + + + + YOUR DEVICE + + credential + response + decrypted on your device + + + + proof — only the bytes you reveal + + + + Attestor signs + sees only ciphertext + + Plaintext stays on your device + + + + + + TEE-TLS (enclave) + + + + YOUR DEVICE + + credential + encrypt → enclave key + + + + encrypted credential + + + + ENCLAVE · operator hardware + + your plaintext, decrypted (~1s) + + + + attestation + + Plaintext leaves your device + diff --git a/blog/2026-06-06-where-trust-lives/light/three_anchors.svg b/blog/2026-06-06-where-trust-lives/light/three_anchors.svg new file mode 100644 index 0000000..66fc546 --- /dev/null +++ b/blog/2026-06-06-where-trust-lives/light/three_anchors.svg @@ -0,0 +1,37 @@ + + + + + + + + + + 1 + An operator is honest + trust: one operator's word + + + + + 2 + This exact code ran in isolated hardware + trust: a hardware vendor's signing key + + + + + 3 + Mathematically true, whoever ran it + trust: no one; the proof is public + + + + Same kind of trust + a secret someone else holds + + + + A different kind + no secret to hold + From 84180d27dd1b7120323505efa2ba7cb09a699433 Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Thu, 11 Jun 2026 14:56:53 +0200 Subject: [PATCH 2/6] =?UTF-8?q?blog:=20clarify=20trust-lives=20post=20?= =?UTF-8?q?=E2=80=94=20attribute=20speed=20figure,=20disambiguate=20the=20?= =?UTF-8?q?two=20attestation=20signatures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Attribute the thirty-second figure to Peer's own framing, since the post later notes it comes from an older proxy implementation - Separate the attestor's payment signature (shared, strengthened by the TEE) from the enclave attestation document the client trusts before handing over the credential (TEE-only) - Reframe the forgery scenario as a credential theft, not a forged payment, so the confidentiality stakes are explicit - Update figure SVGs --- .../dark/plaintext_boundary.svg | 19 ++++-- .../dark/three_anchors.svg | 65 +++++++++++------- blog/2026-06-06-where-trust-lives/index.md | 67 +++++++++---------- .../light/plaintext_boundary.svg | 19 ++++-- .../light/three_anchors.svg | 65 +++++++++++------- 5 files changed, 136 insertions(+), 99 deletions(-) diff --git a/blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg b/blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg index 15cb9e1..0dfa19d 100644 --- a/blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg +++ b/blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg @@ -24,18 +24,23 @@ decrypted on your device - - proof — only the bytes you reveal + + proof: only the bytes you reveal - - Attestor signs - sees only ciphertext + + Attestor signs + sees only ciphertext - Plaintext stays on your device + + + attestation + + Plaintext stays on your device - + + same attestation either way TEE-TLS (enclave) diff --git a/blog/2026-06-06-where-trust-lives/dark/three_anchors.svg b/blog/2026-06-06-where-trust-lives/dark/three_anchors.svg index c77a015..c93bc49 100644 --- a/blog/2026-06-06-where-trust-lives/dark/three_anchors.svg +++ b/blog/2026-06-06-where-trust-lives/dark/three_anchors.svg @@ -1,37 +1,54 @@ - + + + + + + + + + PEER'S MOVE + + + integrity: 1 → 2 + an upgrade + + + privacy: 3 → 2 + a downgrade + - - - 1 - An operator is honest - trust: one operator's word + + + 1 + An operator is honest + trust: one operator's word - - - 2 - This exact code ran in isolated hardware - trust: a hardware vendor's signing key - - - - - 3 - Mathematically true, whoever ran it - trust: no one; the proof is public + + + 2 + This exact code ran in isolated hardware + trust: a hardware vendor's signing key + + + + + 3 + It holds by construction, whoever ran it + trust: no one; there is no secret to hold - - Same kind of trust - a secret someone else holds + + Same kind of trust + a secret someone else holds - - A different kind - no secret to hold + + A different kind + no secret to hold diff --git a/blog/2026-06-06-where-trust-lives/index.md b/blog/2026-06-06-where-trust-lives/index.md index ae371bf..a694371 100644 --- a/blog/2026-06-06-where-trust-lives/index.md +++ b/blog/2026-06-06-where-trust-lives/index.md @@ -8,20 +8,19 @@ import Figure from '@site/src/components/Figure'; Web proofs opened up a whole class of applications: proving your bank balance, your income, a payment, or your identity to an app that otherwise has no way to trust it. And across all of them, the number one feature request is always the same, speed. As our recent posts on [proxy-mode benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode) and the [full-reveal fast path](https://tlsnotary.org/blog/2026/05/19/fast-reveal) keep showing, users do not want to wait for a proof. -One application we are genuinely fans of is [Peer](https://docs.peer.xyz), a noncustodial fiat-to-crypto protocol. They just announced moving their payment verification from zkTLS to a TEE, running inside AWS Nitro Enclaves, and the reason is unsurprisingly "speed": from about thirty seconds down to under a second. That is a real win, so it is worth looking honestly at what the move buys and what it costs. +One application we are genuinely fans of is [Peer](https://docs.peer.xyz), a noncustodial fiat-to-crypto protocol. They just announced moving their payment verification from zkTLS to a TEE, running inside AWS Nitro Enclaves, and the reason is unsurprisingly "speed": in their words, from about thirty seconds down to under a second. That is a real win, so it is worth looking honestly at what the move buys and what it costs. None of this is an attack on Peer; we want them to win. The point is more general. Any system that proves "this web data is real" has to root that promise somewhere, and swapping the technology underneath rarely removes the trust. It relocates it. So the real question is never trust versus no trust. It is where the trust now lives, and whether you can still see it from there. That is what this post is about. -Peer's Sachin wrote up the reasoning in a clear, public [post](https://x.com/0xSachinK/status/2062860592906731888). It is a thoughtful, well-engineered decision, and explaining the trade in public is the honest thing to do. So we are going to engage it on the merits. The argument here is not that the hardware can be broken; it is that even when the hardware works exactly as designed, the guarantee still comes down to a signature. +Peer's Sachin wrote up the reasoning in a clear, public [post](https://x.com/0xSachinK/status/2062860592906731888), and explaining the trade in public is the honest thing to do. So we will engage it on the merits. The argument here is not that the hardware can be broken; it is that even when the hardware works exactly as designed, the guarantee still comes down to a signature. ## TL;DR -- This is **not really a security or trust argument**. On-chain, both approaches end at the same signed attestation, and against a single attestor a TEE can even *raise* the integrity bar. +- This is **not an integrity argument**. On-chain, both approaches end at the same signed attestation, and against a single attestor a TEE can even *raise* the integrity bar. - It is a **privacy argument**, and a change of *basis*. With zkTLS your credential never leaves your device; only a proof does. With a TEE your credential leaves your device and is decrypted inside someone else's hardware, and the promise it stays private rests on a **signature**, not on mathematics. -- And the failure is **silent**. A forged attestation verifies exactly like a real one, so a user has **no way to detect foul play**. The guarantee can break without anyone noticing. -- That distinction is invisible when everything works and decisive when it does not. It is the whole reason not to treat the two as equivalent. +- And the failure is **silent**: a forged attestation verifies exactly like a real one, so the guarantee can break with **no way for a user to detect it**. That distinction is invisible when everything works and decisive when it does not. ## Both roads end at a signature @@ -29,7 +28,7 @@ Start with the thing that does not change. zkTLS, TLSNotary included, is a **des The upshot for us is simple: if your funds release on an attestor's signature, you are trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. Which is exactly why Peer's integrity argument lands. Their prior production system was proxy-based zkTLS with a **single attestor**, and a single attestor that is compromised or colluding can sign off on a payment that never happened. Move the signing key inside a Nitro Enclave, wrap it under a KMS policy that only releases it to an enclave whose measured identity matches the published build, and now forging an attestation means breaking the hardware's isolation or subverting KMS, not just leaning on one server. As Sachin puts it, *"the trust anchor moves from 'an operator is honest' to 'this exact code ran in isolated hardware.'"* -That is a real improvement over trusting an operator's word. We are not going to pretend otherwise. The integrity story is defensible. Hold onto that phrase, *the trust anchor moves*, because the rest of this post is about reading the fine print on where it moves to. +That is a real improvement over trusting an operator's word, and we are not going to pretend otherwise. Hold onto that phrase, *the trust anchor moves*, because the rest of this post is about reading the fine print on where it moves to. ## So what actually changed? Where the plaintext goes @@ -42,7 +41,7 @@ In the TEE flow, the PeerAuth extension reads your live session token and **encr
@@ -54,74 +53,68 @@ This is where the honest disagreement lives, and both sides are describing the * Peer's case is strong on its own terms: nothing is stored, the enclave boots from a read-only image, the credential lives in memory for about a second and is wiped, and the only thing that leaves is the attestation. Sachin's conclusion: *"the privacy guarantees are identical to zkTLS, with better UX."* In good faith, operationally, on a day when everything works exactly as designed, that is a fair description. -Our objection is not to any of those facts. It is to the word *identical*, because it quietly swaps the **basis** of the guarantee: +Our objection is not to any of those facts. It is to the word *identical*. This is not about the attestor's signature the contract checks — both designs share that one, and the TEE strengthens it. It is about a second signature only the TEE flow introduces, the one your client must trust *before handing over your credential*, and it quietly swaps the **basis** of the privacy guarantee: > With zkTLS, the confidentiality of your credential is **structural and cryptographic**: it is a fact about *where the computation happened* (your device) and *what mathematically left it* (a proof). With a TEE, the confidentiality is **contingent on a signature**: an attestation that says "the code that saw your plaintext was the published code, running in isolated hardware that promises not to leak it." Strictly speaking, that is weaker, even when the integrity is the same. A cryptographic guarantee holds whether or not the operator is honest, whether or not the hardware vendor was compelled, whether or not there is a bug you did not find. An attestation-backed guarantee holds *as long as the attestation means what you think it means*, as long as the measured code is bug-free, the isolation is real, the vendor's keys are clean, and the enclave actually does what its source says. Those are reasonable things to believe. They are not the same kind of thing as "the plaintext never left your phone." -None of this says Peer's enclave does anything wrong; by all appearances it is careful work. The point is narrower: the *shape* of the guarantee changed, from one that cannot fail in these ways to one that, in principle, could. And that kind of difference tends to stay invisible right up until the day it matters. +The point is narrower than wrongdoing: the *shape* of the guarantee changed, from one that cannot fail in these ways to one that, in principle, could. And that kind of difference stays invisible right up until the day it matters. + +What does that day look like? Not a forged payment — a stolen credential. The attestation document is what tells your client *which public key to encrypt your credential to*. Forge that document, binding a key *you* control to the expected measurement, and the victim's client encrypts its credential straight to you. The signature verifies, so nothing looks wrong: the attack is silent, targetable at individual users, and invisible to the victim. The credential was encrypted perfectly, to the wrong party. This is why "contingent on a signature" is not a figure of speech: the confidentiality of your data is exactly as good as the secrecy of a key you will never see. ## Can you check it yourself? -Peer deserves real credit here, because they did not hand-wave this. They ship an npm package, [`@zkp2p/zkp2p-attestation`](https://www.npmjs.com/package/@zkp2p/zkp2p-attestation), that lets a client fetch the enclave's attestation document, verify AWS's Nitro signature chain, and check the PCR measurements and signer. `GET /attestation` returns a fresh, AWS-signed document. That is genuinely more than most TEE deployments offer, and it is the right instinct. +Peer deserves real credit here, because they did not hand-wave this. They ship an npm package, [`@zkp2p/zkp2p-attestation`](https://www.npmjs.com/package/@zkp2p/zkp2p-attestation), that lets a client fetch the enclave's attestation document, verify AWS's Nitro signature chain, and check the PCR measurements and signer. That is genuinely more than most TEE deployments offer, and it is the right instinct. -Crucially, the check happens *before* you hand over anything sensitive. The correct pattern, and the one a verifier/encrypter package is built for, is *attest, then encrypt*: the client asks the enclave for an attestation over a fresh nonce; that signed document binds the enclave's public key to its measurement; the client verifies the AWS chain, the measurement, and the nonce; and only *then* encrypts the credential to the key the attestation vouched for. Encrypting to that key is what makes the secret decryptable only inside an enclave running the measured code. It is worth being precise about why, because the intuition that "it is encrypted, so it is fine" is exactly wrong: the encryption alone guarantees nothing. A public key is just bytes, and an *unattested* one could have its private half sitting in ordinary server memory, decrypting your credential outside any enclave at all. The safety comes from verifying the binding first, not from the encryption. +Crucially, the check happens *before* you hand over anything sensitive. The correct pattern is *attest, then encrypt*: the client asks the enclave for an attestation over a fresh nonce; that signed document binds the enclave's public key to its measurement; the client verifies the AWS chain, the measurement, and the nonce; and only *then* encrypts the credential to the key the attestation vouched for. The intuition that "it is encrypted, so it is fine" is exactly wrong: a public key is just bytes, and an *unattested* one could have its private half sitting in ordinary server memory, decrypting your credential outside any enclave at all. The safety comes from verifying the binding first, not from the encryption. -So yes, you can check beforehand. But notice what that check does and does not settle. It answers "am I talking to a genuine enclave running the expected measurement?" It does not answer the next three questions, and as an actual user on a phone this is where it bottoms out: +So yes, you can check beforehand. But notice what that check does and does not settle. It answers "am I talking to a genuine enclave running the expected measurement?" It does not answer the next three questions, and on an actual phone this is where it bottoms out: -1. **A measurement is a hash, not a meaning.** Verifying that the running enclave matches PCR `abc123` tells you the *expected* image is loaded. To know `abc123` is the *honest* code (the code that wipes your token and emits nothing else), you have to obtain the enclave source, build it reproducibly, and get the same hash. Peer says they *will* open-source the attestation service so anyone can do this. As of writing, that part has not shipped: the verifier is public, the reproducible enclave source is not yet. So today you can confirm "an enclave matching Peer's published measurement ran," but you are still trusting Peer's claim about what that measurement *is*. -2. **Someone has to actually run the check.** On mobile or in a browser, the thing fetching `/attestation` and comparing the measurement is the client Peer ships. A client can verify diligently, or skip it, and the user cannot tell from the outside. Independent verification means an independently built client pinning an independently audited measurement. -3. **AWS is the root, unconditionally.** The signature chains to AWS's attestation keys, and the "host cannot read enclave memory" property is AWS's design and AWS's word. That means you are trusting a single vendor that operates the hardware and holds the root key, and whoever holds that key can be compelled to use it: a lawful order could in principle require the vendor to vouch for a key the requester controls, with a gag order keeping it quiet. You would have no way to tell, because the signature would verify like any other. That is the same silent failure as before, reached through a courtroom rather than an exploit. +1. **A measurement is a hash, not a meaning.** Verifying that the running enclave matches PCR `abc123` tells you the *expected* image is loaded. To know `abc123` is the *honest* code (the code that wipes your token and emits nothing else), you have to obtain the enclave source, build it reproducibly, and get the same hash. Peer says they *will* open-source the attestation service so anyone can do this; as of writing, that has not shipped. So today you can confirm "an enclave matching Peer's published measurement ran," but you are still trusting Peer's claim about what that measurement *is*. +2. **Someone has to actually run the check.** On mobile or in a browser, the thing fetching the attestation and comparing the measurement is the client Peer ships. A client can verify diligently or skip it, and the user cannot tell from the outside. Independent verification means an independently built client pinning an independently audited measurement. +3. **AWS is the root, unconditionally.** The signature chains to AWS's attestation keys, and the "host cannot read enclave memory" property is AWS's design and AWS's word. You are trusting a single vendor that operates the hardware and holds the root key, and whoever holds that key can be compelled to use it: a lawful order could require the vendor to vouch for a key the requester controls, with a gag order keeping it quiet. You would have no way to tell, because the signature would verify like any other, the same silent failure as before, reached through a courtroom rather than an exploit. None of these make the design bad. They locate it. The verifiable part is real; the part you still take on faith is real too. ## Three anchors -Sachin's framing is the right one, *the trust anchor moves*, so let's just finish the sentence. There are three places a web proof can anchor its trust, and they are not equivalent: +Sachin's framing is the right one, *the trust anchor moves*, so let's just finish the sentence. There are three places a guarantee can anchor, and they are not equivalent: -1. **An operator is honest.** A single attestor signs. Simplest, weakest. This is what Peer moved *away* from, correctly. -2. **This exact code ran in isolated hardware.** A TEE binds the signature to an attested measurement. Stronger, but conditional on a hardware vendor, a measurement you can map to source, and isolation that holds. This is where Peer moved *to*. -3. **This is mathematically true, regardless of who ran it.** No operator to trust, no measurement to map, no vendor at the root. This is what cryptographic soundness buys, and it is why TLSNotary defaults to [MPC-TLS](/docs/protocol/mpc-tls/) and treats every step away from it, including our own [proxy mode](https://tlsnotary.org/blog/2026/04/22/proxy-mode), as a *named, legible* trade rather than a free lunch. +1. **Someone's word.** An operator promises. Simplest, weakest. +2. **Someone's hardware.** A TEE binds the promise to an attested measurement. Stronger, but conditional on a hardware vendor, a measurement you can map to source, and isolation that holds. +3. **The structure itself.** The property holds by construction, whoever ran what: there is no operator to trust, no measurement to map, no vendor at the root.
-But push on anchor 2 and it leans closer to anchor 1 than it first appears. Strip away the silicon and what a verifier actually checks is a *signature*: does this attestation chain to a key I trust? The hardware's real job is to keep that key secret, which means the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave's protection by construction. For Peer that custodian is AWS, which operates both the Nitro attestation root and the KMS that releases the signing key. An unbreakable enclave and an unforgeable attestation are not the same thing: anyone holding that signing key (the vendor, or the vendor compelled to use it) can mint a flawless attestation with no enclave behind it at all. +The catch, and the reason this post exists, is that a web proof is not one guarantee. It is two, and they anchor independently. On **integrity** (did this payment really happen?), everything on-chain anchors at 1 or 2 today, our own proofs included: zkTLS is designated-verifier, so the contract checks an attestor's signature either way. On that axis Peer's move is a clean upgrade, from 1 to 2. But on **privacy** (who saw your credential?), the move ran the other direction: from 3, plaintext that structurally never left your device, down to 2, an enclave you trust to forget it. Up the ladder on integrity, down it on privacy. That asymmetry is why TLSNotary defaults to [MPC-TLS](/docs/protocol/mpc-tls/) and treats every step away from it, including our own [proxy mode](https://tlsnotary.org/blog/2026/04/22/proxy-mode), as a *named, legible* trade rather than a free lunch. -In the encrypt-to-the-enclave model, that is not only an integrity problem; it is the entire privacy guarantee. Forge the attestation, bind a key *you* control to the expected measurement, and the victim's client encrypts its credential straight to you. The signature verifies, so nothing looks wrong: the attack is silent, targetable at individual users, and invisible to the victim. The credential was encrypted perfectly, to the wrong party. This is why "contingent on a signature" is not a figure of speech: the confidentiality of your data is exactly as good as the secrecy of a key you will never see. +But push on anchor 2 and it leans closer to anchor 1 than it first appears. Strip away the silicon and what a verifier actually checks is a *signature*: does this attestation chain to a key I trust? The hardware's real job is to keep that key secret, so the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave's protection by construction. For Peer that custodian is AWS, which operates both the Nitro attestation root and the KMS that releases the signing key. An unbreakable enclave and an unforgeable attestation are not the same thing. That is the difference anchor 3 makes. Mathematics has no key whose compromise hands over your data, because in a soundness-rooted design your plaintext never left your device, so there is nothing to redirect. Anchor 2 is a real upgrade over anchor 1: it moves the trust to a far better-resourced custodian. But it is the *same kind* of trust, a secret key kept by someone else, not the different kind that math provides. The honest pitch for a TEE is "stronger than trusting one operator's word," not "as good as math." -## Where this is going - -The usual, fair rebuttal at this point is: *math is great, but it is too slow on a phone, which is the whole reason we reached for hardware.* That gap is the thing actually worth racing on, and it is closing from the cryptographic side. - -It is also a smaller gap than the headline suggests. The thirty-second figure comes from an older proxy implementation, not from where cryptographic zkTLS sits today: TLSNotary's current proxy mode already runs in low single-digit seconds (around 1.6s in our [latest benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode)). A sub-second enclave is still faster, but the distance is a long way from thirty-to-one, and it keeps shrinking. - -[SpeakUp](https://privacy-ethereum.github.io/speakup/) is a VOLE-based zkVM built specifically for proving on resource-constrained devices (phones and browsers), trading larger proofs for minimal work on the prover. It is privacy-first and post-quantum by construction. The point, for this discussion, is that it pushes general-purpose **selective disclosure back onto the user's own device**: prove an arbitrary property of your transcript, reveal nothing else, keep the plaintext where it started. That is the exact privacy property the TEE path gives up, recovered without sending your credential anywhere. - -We will not oversell it. SpeakUp is interactive, so it lives in the same designated-verifier world described above: it makes client-side privacy fast; it does not, by itself, make proofs publicly verifiable on-chain. The harder frontier is still open research: an attestor that does not even learn the server or the statement (the "blind notary"), and proofs small enough to verify on-chain. It is stalled mostly on performance and incentives rather than possibility. We are working on it. So is the field. - ## How fast is fast enough? -The speed argument carries a hidden assumption: that faster is always better. It is not. Speed has a "good enough" point, and the question worth asking is not "how fast can we go" but "are we already fast enough, and what are we paying for the rest?" +The usual, fair rebuttal at this point is: *math is great, but it is too slow on a phone, which is the whole reason we reached for hardware.* But that carries a hidden assumption, that faster is always better. Speed has a "good enough" point, and the question worth asking is not "how fast can we go" but "are we already fast enough, and what are we paying for the rest?" + +Thirty seconds was genuinely too long, and no one should defend it. But that figure comes from an older proxy implementation, not from where cryptographic zkTLS sits today: TLSNotary's current proxy mode already runs in low single-digit seconds (around 1.6s in our [latest benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode)). A sub-second enclave is still faster, but the distance is a long way from thirty-to-one. And a few seconds is fine for most flows, especially the ones that matter: someone moving money, proving income for a loan, or settling a trade will gladly wait five seconds for a guarantee rooted in mathematics. The hunger for sub-second speed is sharpest in casual, high-frequency, low-stakes interactions, which is exactly where giving up privacy costs the least. So speed and privacy usually point the same way: when the stakes are high enough to want the stronger guarantee, they are high enough that a short wait is no objection. -Thirty seconds was genuinely too long, and no one should defend it. But the cryptographic path is not at thirty seconds anymore; it is at a few. A few seconds is fine for most flows, and especially for the ones that matter: someone moving money, proving income for a loan, or settling a trade will gladly wait five seconds for a guarantee rooted in mathematics. The hunger for sub-second speed is sharpest in casual, high-frequency, low-stakes interactions, which is exactly where giving up privacy costs the least. So speed and privacy usually point the same way: when the stakes are high enough to want the stronger guarantee, they are high enough that a short wait is no objection. +And the gap keeps closing from the cryptographic side. [SpeakUp](https://privacy-ethereum.github.io/speakup/) is a VOLE-based zkVM built specifically for proving on resource-constrained devices (phones and browsers), trading larger proofs for minimal work on the prover. It is privacy-first and post-quantum by construction. The point, for this discussion, is that it pushes general-purpose **selective disclosure back onto the user's own device**: prove an arbitrary property of your transcript, reveal nothing else, keep the plaintext where it started. That is the exact privacy property the TEE path gives up, recovered without sending your credential anywhere. We will not oversell it: SpeakUp is interactive, so it lives in the same designated-verifier world described above. It makes client-side privacy fast; making proofs publicly verifiable on-chain is the harder frontier, still open research, and we are working on it. So the honest first question is not "TEE or cryptography," it is "do we even need to make this trade?" Increasingly, the answer is no. -When raw latency really is the binding constraint and the stakes are genuinely low, a well-built TEE deployment like Peer's is a reasonable, even admirable call. We would only ask one thing of anyone making that trade: name it. Say "we relocated the privacy guarantee from your device to attested hardware, and here is the vendor, the measurement, and the verification tooling you can check." Peer, to their credit, did. The failure mode is not choosing a TEE; it is letting users believe "verified" means cryptography when it means a signature from a chip. +When raw latency really is the binding constraint and the stakes are genuinely low, a well-built TEE deployment like Peer's might be a reasonable call. We would only ask one thing of anyone making that trade: name it. Say "we relocated the privacy guarantee from your device to attested hardware, and here is the vendor, the measurement, and the verification tooling you can check." Peer, to their credit, did. The failure mode is not choosing a TEE; it is letting users believe "verified" means cryptography when it means a signature from a chip. ## You can have both Notice what actually did the work in Peer's integrity win. It was not that the enclave saw your data. It was that the signing key was bound to attested code, so the operator could not sign a session that never happened. You can get that without giving up any privacy. -Run the zkTLS verifier *inside* the enclave. It still sees only ciphertext, because the prover decrypts on-device and proves in zero-knowledge, so your plaintext never leaves your device and the privacy stays structural. The enclave's only job is to stop the operator from signing whatever it likes. That is a TEE used as an integrity bound on top of cryptographic privacy, rather than a replacement for it, and it is close to what TLSNotary already supports through a notary that carries a [TEE attestation of its own code](/docs/protocol/custom_extension). +Run the zkTLS verifier *inside* the enclave. It still sees only ciphertext, because the prover decrypts on-device and proves in zero-knowledge, so your plaintext never leaves your device and the privacy stays structural. The enclave's only job is to stop the operator from signing whatever it likes. That is a TEE used as an integrity bound on top of cryptographic privacy, rather than a replacement for it: integrity anchored at 2, privacy at 3. It is close to what TLSNotary already supports through a notary that carries a [TEE attestation of its own code](/docs/protocol/custom_extension). It does not make the result trustless. You still trust the vendor for the verifier's integrity, and on-chain it is still a signature. But it buys the integrity Peer is after without moving your credential into someone else's hardware. diff --git a/blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg b/blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg index 4e4212f..21370c2 100644 --- a/blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg +++ b/blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg @@ -24,18 +24,23 @@ decrypted on your device - - proof — only the bytes you reveal + + proof: only the bytes you reveal - - Attestor signs - sees only ciphertext + + Attestor signs + sees only ciphertext - Plaintext stays on your device + + + attestation + + Plaintext stays on your device - + + same attestation either way TEE-TLS (enclave) diff --git a/blog/2026-06-06-where-trust-lives/light/three_anchors.svg b/blog/2026-06-06-where-trust-lives/light/three_anchors.svg index 66fc546..0aa3d67 100644 --- a/blog/2026-06-06-where-trust-lives/light/three_anchors.svg +++ b/blog/2026-06-06-where-trust-lives/light/three_anchors.svg @@ -1,37 +1,54 @@ - + + + + + + + + + PEER'S MOVE + + + integrity: 1 → 2 + an upgrade + + + privacy: 3 → 2 + a downgrade + - - - 1 - An operator is honest - trust: one operator's word + + + 1 + An operator is honest + trust: one operator's word - - - 2 - This exact code ran in isolated hardware - trust: a hardware vendor's signing key - - - - - 3 - Mathematically true, whoever ran it - trust: no one; the proof is public + + + 2 + This exact code ran in isolated hardware + trust: a hardware vendor's signing key + + + + + 3 + It holds by construction, whoever ran it + trust: no one; there is no secret to hold - - Same kind of trust - a secret someone else holds + + Same kind of trust + a secret someone else holds - - A different kind - no secret to hold + + A different kind + no secret to hold From 374ccad52722b387695b7f65bbbc4e6e80bb8271 Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Wed, 17 Jun 2026 11:26:43 +0200 Subject: [PATCH 3/6] blog: set trust-lives date to 2026-06-19 and fix public-verifiability cross-link - Rename folder to 2026-06-19 (publishes after the merged companion post) - Update companion-post link to its merged slug /blog/2026/06/17/public-verifiability --- .../dark/plaintext_boundary.svg | 0 .../dark/three_anchors.svg | 0 .../index.md | 4 ++-- .../light/plaintext_boundary.svg | 0 .../light/three_anchors.svg | 0 5 files changed, 2 insertions(+), 2 deletions(-) rename blog/{2026-06-06-where-trust-lives => 2026-06-19-where-trust-lives}/dark/plaintext_boundary.svg (100%) rename blog/{2026-06-06-where-trust-lives => 2026-06-19-where-trust-lives}/dark/three_anchors.svg (100%) rename blog/{2026-06-06-where-trust-lives => 2026-06-19-where-trust-lives}/index.md (98%) rename blog/{2026-06-06-where-trust-lives => 2026-06-19-where-trust-lives}/light/plaintext_boundary.svg (100%) rename blog/{2026-06-06-where-trust-lives => 2026-06-19-where-trust-lives}/light/three_anchors.svg (100%) diff --git a/blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg b/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg similarity index 100% rename from blog/2026-06-06-where-trust-lives/dark/plaintext_boundary.svg rename to blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg diff --git a/blog/2026-06-06-where-trust-lives/dark/three_anchors.svg b/blog/2026-06-19-where-trust-lives/dark/three_anchors.svg similarity index 100% rename from blog/2026-06-06-where-trust-lives/dark/three_anchors.svg rename to blog/2026-06-19-where-trust-lives/dark/three_anchors.svg diff --git a/blog/2026-06-06-where-trust-lives/index.md b/blog/2026-06-19-where-trust-lives/index.md similarity index 98% rename from blog/2026-06-06-where-trust-lives/index.md rename to blog/2026-06-19-where-trust-lives/index.md index a694371..da4dbc2 100644 --- a/blog/2026-06-06-where-trust-lives/index.md +++ b/blog/2026-06-19-where-trust-lives/index.md @@ -24,7 +24,7 @@ Peer's Sachin wrote up the reasoning in a clear, public [post](https://x.com/0xS ## Both roads end at a signature -Start with the thing that does not change. zkTLS, TLSNotary included, is a **designated-verifier** technology: the proof convinces only the party that took part in the session, and a smart contract cannot be that party. So on-chain there is always a trusted attestor that signs a statement in lieu of a proof, and the contract checks the signature. (We unpack why an in-session witness is unavoidable, and what "publicly verifiable" really means, in a [companion post](/blog/2026/06/05/public-verifiability).) +Start with the thing that does not change. zkTLS, TLSNotary included, is a **designated-verifier** technology: the proof convinces only the party that took part in the session, and a smart contract cannot be that party. So on-chain there is always a trusted attestor that signs a statement in lieu of a proof, and the contract checks the signature. (We unpack why an in-session witness is unavoidable, and what "publicly verifiable" really means, in a [companion post](/blog/2026/06/17/public-verifiability).) The upshot for us is simple: if your funds release on an attestor's signature, you are trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. Which is exactly why Peer's integrity argument lands. Their prior production system was proxy-based zkTLS with a **single attestor**, and a single attestor that is compromised or colluding can sign off on a payment that never happened. Move the signing key inside a Nitro Enclave, wrap it under a KMS policy that only releases it to an enclave whose measured identity matches the published build, and now forging an attestation means breaking the hardware's isolation or subverting KMS, not just leaning on one server. As Sachin puts it, *"the trust anchor moves from 'an operator is honest' to 'this exact code ran in isolated hardware.'"* @@ -124,7 +124,7 @@ So when the privacy stakes rise, the cryptographic path is right there, for Peer DRAFT NOTES (remove before publishing) - BYLINE: currently commented out / undecided. Sibling post #62 (public-verifiability) is authored by heeckhau. - STYLE: em-dash-free, to match the public-verifiability post's house style. -- COORDINATION: the designated-verifier explainer is compressed and cross-links the companion post (/blog/2026/06/05/public-verifiability, PR #62). Confirm that post's final slug/date before publishing; #62 is dated 2026-06-05 so it should publish first. +- COORDINATION: the designated-verifier explainer is compressed and cross-links the companion post (/blog/2026/06/17/public-verifiability, PR #62, merged to master and dated 2026-06-17). It publishes first; this post is dated 2026-06-19. - FIGURES: plaintext_boundary (where the plaintext lives) + three_anchors. Both hand-authored light/dark SVGs. - VERIFIED: ~30s -> <300ms / "100x" (Sachin article + @peerxyz, Jun 3 2026). npm @zkp2p/zkp2p-attestation v1.4.0 live (2026-06-05). zkp2p org has NO public Nitro enclave-source repo yet (only legacy proxy/witness forks); re-check before publish in case they push it. - DROPPED: the unverified "$35M+ volume" figure (not in Sachin's article). Legal/liability angle explored then dropped at author's request. diff --git a/blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg b/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg similarity index 100% rename from blog/2026-06-06-where-trust-lives/light/plaintext_boundary.svg rename to blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg diff --git a/blog/2026-06-06-where-trust-lives/light/three_anchors.svg b/blog/2026-06-19-where-trust-lives/light/three_anchors.svg similarity index 100% rename from blog/2026-06-06-where-trust-lives/light/three_anchors.svg rename to blog/2026-06-19-where-trust-lives/light/three_anchors.svg From 9ff1b88eb729adafbc1558a3671b4c8dd8950ad4 Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Fri, 19 Jun 2026 10:59:05 +0200 Subject: [PATCH 4/6] blog: reframe trust-lives around the integrity/privacy axes - Add an upfront "two promises" framing box and label the two key sections "Integrity:" and "Privacy:" so the reader gets the map first. - Open on the trust question rather than speed; recast the intro stance ("we are not neutral") and drop the "attack" framing. - Call Peer the poster child for production zkTLS. - Accuracy fixes: credential reaches only the server it logs into (not "never leaves the device"); forging an attestation also means the vendor's signing keys, not just breaking hardware; "Which TEE you pick" instead of "the brand on the chip"; drop the bug-immunity overclaim; scope the speed claim to Peer's payment case instead of asserting user behavior. - Rework selective disclosure structurally ("reveal only what is necessary"); distinguish forged payment (integrity) from stolen credential (privacy) without dismissing either. - Close "You can have both" on the synthesis; rhetorical-question lead-in. - Add the "why not both?" image; update plaintext_boundary diagram label to match the prose; remove the arm-wrestle figure. --- .../dark/plaintext_boundary.svg | 2 +- blog/2026-06-19-where-trust-lives/index.md | 119 ++++++------------ .../light/plaintext_boundary.svg | 2 +- .../why_not_both.jpg | Bin 0 -> 73780 bytes 4 files changed, 43 insertions(+), 80 deletions(-) create mode 100644 blog/2026-06-19-where-trust-lives/why_not_both.jpg diff --git a/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg b/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg index 0dfa19d..0a75da8 100644 --- a/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg +++ b/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg @@ -25,7 +25,7 @@ - proof: only the bytes you reveal + proof: only what is necessary diff --git a/blog/2026-06-19-where-trust-lives/index.md b/blog/2026-06-19-where-trust-lives/index.md index da4dbc2..e7e500c 100644 --- a/blog/2026-06-19-where-trust-lives/index.md +++ b/blog/2026-06-19-where-trust-lives/index.md @@ -1,133 +1,96 @@ --- title: "Where does your trust live? Cryptographic soundness and the TEE trade" # authors: [sinu, heeckhau] -description: "Moving a web proof from zkTLS to a TEE keeps the same on-chain result, and can even raise the integrity bar. The honest question is privacy: do you trust a guarantee rooted in mathematics, or one rooted in a signature from a chip?" +description: "Moving a web proof from zkTLS to a TEE keeps the same on-chain result and can even raise the integrity bar. The honest question is privacy: do you trust a guarantee rooted in mathematics, or one rooted in a signature from a chip?" --- import Figure from '@site/src/components/Figure'; -Web proofs opened up a whole class of applications: proving your bank balance, your income, a payment, or your identity to an app that otherwise has no way to trust it. And across all of them, the number one feature request is always the same, speed. As our recent posts on [proxy-mode benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode) and the [full-reveal fast path](https://tlsnotary.org/blog/2026/05/19/fast-reveal) keep showing, users do not want to wait for a proof. +Web proofs let you prove a real-world fact (your bank balance, a payment, your identity) to an app that otherwise has no way to trust it. Each one rests on a guarantee: that the data is genuine, and that whatever handled it kept your secrets. The question worth asking is where that guarantee comes from. -One application we are genuinely fans of is [Peer](https://docs.peer.xyz), a noncustodial fiat-to-crypto protocol. They just announced moving their payment verification from zkTLS to a TEE, running inside AWS Nitro Enclaves, and the reason is unsurprisingly "speed": in their words, from about thirty seconds down to under a second. That is a real win, so it is worth looking honestly at what the move buys and what it costs. +[Peer](https://docs.peer.xyz), a noncustodial fiat-to-crypto protocol and arguably the flagship production zkTLS app, just moved its payment verification to a TEE running in AWS Nitro Enclaves. The reason is speed: in their words, from about thirty seconds down to under a second. That is a real win, and [Sachin's public write-up](https://x.com/0xSachinK/status/2062860592906731888) explains the trade honestly, so we will engage it on the merits. -None of this is an attack on Peer; we want them to win. The point is more general. Any system that proves "this web data is real" has to root that promise somewhere, and swapping the technology underneath rarely removes the trust. It relocates it. So the real question is never trust versus no trust. It is where the trust now lives, and whether you can still see it from there. That is what this post is about. +We will not pretend to be neutral: we think zkTLS is the stronger approach, and we want Peer to win. So this post is a good-faith argument for why we believe users will want the cryptographic guarantee back, and how Peer can keep it without giving up the speed that drove the move. The point is also general. Any system that proves "this web data is real" has to root that promise somewhere, and swapping the technology underneath rarely removes the trust. It relocates it. The real question is never trust versus no trust. It is where the trust now lives, and whether you can still see it. -Peer's Sachin wrote up the reasoning in a clear, public [post](https://x.com/0xSachinK/status/2062860592906731888), and explaining the trade in public is the honest thing to do. So we will engage it on the merits. The argument here is not that the hardware can be broken; it is that even when the hardware works exactly as designed, the guarantee still comes down to a signature. +A web proof makes **two** promises, not one, and they come apart the moment you swap zkTLS for a TEE: -## TL;DR +- **Integrity** (*did this payment really happen?*): both designs end at a delegated attestor's signature that a smart contract checks, and a TEE can make that signature *harder* to forge. This is **not** where the disagreement is. +- **Privacy** (*who gets to see your secrets?*): with zkTLS your credential only ever reaches the server it logs into, kept confidential by **mathematics**; with a TEE it is decrypted inside someone else's hardware, kept confidential by a second **signature**, the enclave's attestation. -- This is **not an integrity argument**. On-chain, both approaches end at the same signed attestation, and against a single attestor a TEE can even *raise* the integrity bar. -- It is a **privacy argument**, and a change of *basis*. With zkTLS your credential never leaves your device; only a proof does. With a TEE your credential leaves your device and is decrypted inside someone else's hardware, and the promise it stays private rests on a **signature**, not on mathematics. -- And the failure is **silent**: a forged attestation verifies exactly like a real one, so the guarantee can break with **no way for a user to detect it**. That distinction is invisible when everything works and decisive when it does not. +Switching to a TEE moves the two in opposite directions: integrity **up**, privacy **down**. The rest of this post is about that asymmetry, and how you can avoid having to choose. -## Both roads end at a signature +## Integrity: both roads end at a signature -Start with the thing that does not change. zkTLS, TLSNotary included, is a **designated-verifier** technology: the proof convinces only the party that took part in the session, and a smart contract cannot be that party. So on-chain there is always a trusted attestor that signs a statement in lieu of a proof, and the contract checks the signature. (We unpack why an in-session witness is unavoidable, and what "publicly verifiable" really means, in a [companion post](/blog/2026/06/17/public-verifiability).) +Start with what does not change. zkTLS, TLSNotary included, is **designated-verifier**: a proof convinces only the party that took part in the session, and a smart contract cannot be that party. So on-chain there is always a trusted attestor that signs a statement in lieu of a proof, and the contract checks the signature. (We unpack why an in-session witness is unavoidable in a [companion post](/blog/2026/06/17/public-verifiability).) -The upshot for us is simple: if your funds release on an attestor's signature, you are trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. Which is exactly why Peer's integrity argument lands. Their prior production system was proxy-based zkTLS with a **single attestor**, and a single attestor that is compromised or colluding can sign off on a payment that never happened. Move the signing key inside a Nitro Enclave, wrap it under a KMS policy that only releases it to an enclave whose measured identity matches the published build, and now forging an attestation means breaking the hardware's isolation or subverting KMS, not just leaning on one server. As Sachin puts it, *"the trust anchor moves from 'an operator is honest' to 'this exact code ran in isolated hardware.'"* +So if your funds release on a signature, you are trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. That is why Peer's integrity argument is convincing. Their old system was proxy zkTLS with a **single attestor**, and one compromised attestor can sign off on a payment that never happened. Move the signing key inside an enclave and release it only to code whose measured identity matches the published build, and forging an attestation now means breaking the enclave's isolation or compromising the hardware vendor's signing keys, not just relying on one server. As Sachin puts it, *"the trust anchor moves from 'an operator is honest' to 'this exact code ran in isolated hardware.'"* On **integrity**, that is a clean upgrade. -That is a real improvement over trusting an operator's word, and we are not going to pretend otherwise. Hold onto that phrase, *the trust anchor moves*, because the rest of this post is about reading the fine print on where it moves to. +The cost is on the other axis. -## So what actually changed? Where the plaintext goes +## Privacy: where your plaintext goes -Here is the difference that matters, and it is almost geometric. +In the proxy-zkTLS flow Peer used to run, your device holds the TLS session. Your credential goes only where it always would, to the server it logs into, and the attestor sees only ciphertext. Your device decrypts the response locally and proves it held the right payment detail. Only that proof crosses to the verifier, revealing only what is necessary while the rest of the response never leaves your device. That is **selective disclosure**, the core privacy primitive of this field. -In the proxy-zkTLS flow Peer used to run, the buyer's device holds the TLS session. The witness proxy sees only ciphertext. The buyer decrypts *on their own machine*, generates a proof that the response contained the right payment detail, and the attestor signs off on that proof. The sensitive bytes (the session token, the full bank response) **never leave the user's device** in the clear. What leaves is a proof, and the user chooses exactly which bytes it reveals. That last part has a name: selective disclosure. It is the core privacy primitive of this entire field. - -In the TEE flow, the PeerAuth extension reads your live session token and **encrypts it to the enclave's public key**. The enclave then makes the authenticated request itself, sees the full plaintext response, checks it, and emits the attestation. The credential and the response now exist, in the clear, inside a machine the operator runs. Selective disclosure is gone: the enclave sees everything, and you trust it to emit only the attestation and forget the rest. +In the TEE flow, the PeerAuth extension reads your live session token and **encrypts it to the enclave's public key**. The enclave makes the request itself, sees the full plaintext response, and emits the attestation. Your credential and the response now exist, in the clear, inside a machine the operator runs. Selective disclosure is gone: the enclave sees everything, and you trust it to emit only the attestation and forget the rest.
-So the plaintext crossed a boundary it never used to cross. That is the whole ballgame. - -## Identical, until it is not - -This is where the honest disagreement lives, and both sides are describing the *same facts*. - -Peer's case is strong on its own terms: nothing is stored, the enclave boots from a read-only image, the credential lives in memory for about a second and is wiped, and the only thing that leaves is the attestation. Sachin's conclusion: *"the privacy guarantees are identical to zkTLS, with better UX."* In good faith, operationally, on a day when everything works exactly as designed, that is a fair description. +Peer's own description is fair: nothing is stored, the credential lives in memory for about a second, and only the attestation leaves. Their conclusion is that *"the privacy guarantees are identical to zkTLS, with better UX."* On a day when everything works exactly as designed, that is true. Our objection is to the word *identical*, because the **basis** of the guarantee changed: -Our objection is not to any of those facts. It is to the word *identical*. This is not about the attestor's signature the contract checks — both designs share that one, and the TEE strengthens it. It is about a second signature only the TEE flow introduces, the one your client must trust *before handing over your credential*, and it quietly swaps the **basis** of the privacy guarantee: +> With zkTLS, the confidentiality of your credential is **structural**: a fact about *where the computation happened* (your device) and *what left it* (a proof). With a TEE it is **contingent on a signature**: an attestation saying the code that saw your plaintext was the published code, running in hardware that promises not to leak it. Even when the integrity is identical, that is a weaker kind of guarantee. -> With zkTLS, the confidentiality of your credential is **structural and cryptographic**: it is a fact about *where the computation happened* (your device) and *what mathematically left it* (a proof). With a TEE, the confidentiality is **contingent on a signature**: an attestation that says "the code that saw your plaintext was the published code, running in isolated hardware that promises not to leak it." Strictly speaking, that is weaker, even when the integrity is the same. +A cryptographic guarantee holds regardless of whether the operator is honest or the vendor was compelled. An attestation-backed one holds *as long as the attestation means what you think it means*. Those are reasonable things to believe. They are not the same kind of thing as "no third party ever saw your credential." -A cryptographic guarantee holds whether or not the operator is honest, whether or not the hardware vendor was compelled, whether or not there is a bug you did not find. An attestation-backed guarantee holds *as long as the attestation means what you think it means*, as long as the measured code is bug-free, the isolation is real, the vendor's keys are clean, and the enclave actually does what its source says. Those are reasonable things to believe. They are not the same kind of thing as "the plaintext never left your phone." - -The point is narrower than wrongdoing: the *shape* of the guarantee changed, from one that cannot fail in these ways to one that, in principle, could. And that kind of difference stays invisible right up until the day it matters. - -What does that day look like? Not a forged payment — a stolen credential. The attestation document is what tells your client *which public key to encrypt your credential to*. Forge that document, binding a key *you* control to the expected measurement, and the victim's client encrypts its credential straight to you. The signature verifies, so nothing looks wrong: the attack is silent, targetable at individual users, and invisible to the victim. The credential was encrypted perfectly, to the wrong party. This is why "contingent on a signature" is not a figure of speech: the confidentiality of your data is exactly as good as the secrecy of a key you will never see. +And the difference stays invisible until it doesn't. A forged payment would be bad, but that is the integrity failure everyone guards against, and the TEE makes it harder. The privacy downgrade opens a quieter one: a **stolen credential**. The attestation document tells your client which key to encrypt your credential to. Forge that document, binding a key *you* control to the expected measurement, and the victim's client encrypts straight to you. The signature verifies, so nothing looks wrong: the attack is silent, targetable at one user, and invisible to the victim. The credential was encrypted perfectly, to the wrong party. ## Can you check it yourself? -Peer deserves real credit here, because they did not hand-wave this. They ship an npm package, [`@zkp2p/zkp2p-attestation`](https://www.npmjs.com/package/@zkp2p/zkp2p-attestation), that lets a client fetch the enclave's attestation document, verify AWS's Nitro signature chain, and check the PCR measurements and signer. That is genuinely more than most TEE deployments offer, and it is the right instinct. - -Crucially, the check happens *before* you hand over anything sensitive. The correct pattern is *attest, then encrypt*: the client asks the enclave for an attestation over a fresh nonce; that signed document binds the enclave's public key to its measurement; the client verifies the AWS chain, the measurement, and the nonce; and only *then* encrypts the credential to the key the attestation vouched for. The intuition that "it is encrypted, so it is fine" is exactly wrong: a public key is just bytes, and an *unattested* one could have its private half sitting in ordinary server memory, decrypting your credential outside any enclave at all. The safety comes from verifying the binding first, not from the encryption. - -So yes, you can check beforehand. But notice what that check does and does not settle. It answers "am I talking to a genuine enclave running the expected measurement?" It does not answer the next three questions, and on an actual phone this is where it bottoms out: +To their credit, Peer ships an npm package, [`@zkp2p/zkp2p-attestation`](https://www.npmjs.com/package/@zkp2p/zkp2p-attestation), that lets a client fetch the attestation, verify AWS's Nitro signature chain, and check the measurement *before* handing over anything sensitive. The correct pattern is **attest, then encrypt**: verify the binding first, because a public key is just bytes, and an *unattested* one could be decrypting your credential outside any enclave at all. -1. **A measurement is a hash, not a meaning.** Verifying that the running enclave matches PCR `abc123` tells you the *expected* image is loaded. To know `abc123` is the *honest* code (the code that wipes your token and emits nothing else), you have to obtain the enclave source, build it reproducibly, and get the same hash. Peer says they *will* open-source the attestation service so anyone can do this; as of writing, that has not shipped. So today you can confirm "an enclave matching Peer's published measurement ran," but you are still trusting Peer's claim about what that measurement *is*. -2. **Someone has to actually run the check.** On mobile or in a browser, the thing fetching the attestation and comparing the measurement is the client Peer ships. A client can verify diligently or skip it, and the user cannot tell from the outside. Independent verification means an independently built client pinning an independently audited measurement. -3. **AWS is the root, unconditionally.** The signature chains to AWS's attestation keys, and the "host cannot read enclave memory" property is AWS's design and AWS's word. You are trusting a single vendor that operates the hardware and holds the root key, and whoever holds that key can be compelled to use it: a lawful order could require the vendor to vouch for a key the requester controls, with a gag order keeping it quiet. You would have no way to tell, because the signature would verify like any other, the same silent failure as before, reached through a courtroom rather than an exploit. +But notice the limits of that check. It answers "am I talking to a genuine enclave running the expected measurement?" It does not answer: -None of these make the design bad. They locate it. The verifiable part is real; the part you still take on faith is real too. +1. **A measurement is a hash, not a meaning.** Matching PCR `abc123` tells you the *expected* image loaded, not that `abc123` is the *honest* code. To know that, you need the source, a reproducible build, and the same hash. Peer says they will open-source it; as of writing, that has not shipped. +2. **Someone has to run the check.** On a phone, the thing verifying the attestation is the client Peer ships. It can verify diligently or skip, and the user cannot tell from the outside. +3. **AWS is the root, unconditionally.** The chain ends at AWS's keys, and "the host cannot read enclave memory" is AWS's word. Whoever holds that key can be compelled to use it and legally barred from disclosing it, and you would have no way to tell, because the signature would verify like any other. -## Three anchors +None of these make the design bad. They show where the trust actually lives. -Sachin's framing is the right one, *the trust anchor moves*, so let's just finish the sentence. There are three places a guarantee can anchor, and they are not equivalent: +## The hardware is not the point -1. **Someone's word.** An operator promises. Simplest, weakest. -2. **Someone's hardware.** A TEE binds the promise to an attested measurement. Stronger, but conditional on a hardware vendor, a measurement you can map to source, and isolation that holds. -3. **The structure itself.** The property holds by construction, whoever ran what: there is no operator to trust, no measurement to map, no vendor at the root. +It is tempting to argue about whether the enclave can be broken. That is the wrong axis. Even when the silicon works perfectly, what a verifier actually checks is a **signature**: does this attestation chain to a key I trust? The hardware's only job is to keep that key secret, so the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave by construction. Which TEE you pick, Intel SGX or AWS Nitro, does not change this. You have not removed your trust in the zkTLS verifier operator; you have moved it to Intel or Amazon. It is the **same kind** of trust, a secret key held by someone else, just relocated to a better-resourced custodian.
-The catch, and the reason this post exists, is that a web proof is not one guarantee. It is two, and they anchor independently. On **integrity** (did this payment really happen?), everything on-chain anchors at 1 or 2 today, our own proofs included: zkTLS is designated-verifier, so the contract checks an attestor's signature either way. On that axis Peer's move is a clean upgrade, from 1 to 2. But on **privacy** (who saw your credential?), the move ran the other direction: from 3, plaintext that structurally never left your device, down to 2, an enclave you trust to forget it. Up the ladder on integrity, down it on privacy. That asymmetry is why TLSNotary defaults to [MPC-TLS](/docs/protocol/mpc-tls/) and treats every step away from it, including our own [proxy mode](https://tlsnotary.org/blog/2026/04/22/proxy-mode), as a *named, legible* trade rather than a free lunch. +That is the difference mathematics makes. In a soundness-rooted design your plaintext never left your device, so there is no key whose compromise hands over your data, because there is nothing to redirect: no operator to trust, no measurement to map to source, no vendor at the root. The honest pitch for a TEE is "stronger than trusting one operator's word," not "as good as math." -But push on anchor 2 and it leans closer to anchor 1 than it first appears. Strip away the silicon and what a verifier actually checks is a *signature*: does this attestation chain to a key I trust? The hardware's real job is to keep that key secret, so the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave's protection by construction. For Peer that custodian is AWS, which operates both the Nitro attestation root and the KMS that releases the signing key. An unbreakable enclave and an unforgeable attestation are not the same thing. +## Do we even need the trade? -That is the difference anchor 3 makes. Mathematics has no key whose compromise hands over your data, because in a soundness-rooted design your plaintext never left your device, so there is nothing to redirect. Anchor 2 is a real upgrade over anchor 1: it moves the trust to a far better-resourced custodian. But it is the *same kind* of trust, a secret key kept by someone else, not the different kind that math provides. The honest pitch for a TEE is "stronger than trusting one operator's word," not "as good as math." +The obvious rebuttal is that math is too slow. But thirty seconds came from an older proxy implementation, not from where zkTLS sits today: TLSNotary's proxy mode already runs in under two seconds ([latest benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode)). A sub-second enclave is still faster, but that is nothing like thirty to one, and for the case Peer is built around, verifying a payment, a second or two is a small price for a guarantee rooted in mathematics rather than a signature. -## How fast is fast enough? +And the gap keeps closing: [SpeakUp](https://privacy-ethereum.github.io/speakup/), a VOLE-based zkVM built for phones and browsers, makes selective disclosure fast and flexible: it proves arbitrary logic, much like a program running in a TEE, but keeps your secrets on the prover's side, the very thing a TEE gives up. -The usual, fair rebuttal at this point is: *math is great, but it is too slow on a phone, which is the whole reason we reached for hardware.* But that carries a hidden assumption, that faster is always better. Speed has a "good enough" point, and the question worth asking is not "how fast can we go" but "are we already fast enough, and what are we paying for the rest?" - -Thirty seconds was genuinely too long, and no one should defend it. But that figure comes from an older proxy implementation, not from where cryptographic zkTLS sits today: TLSNotary's current proxy mode already runs in low single-digit seconds (around 1.6s in our [latest benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode)). A sub-second enclave is still faster, but the distance is a long way from thirty-to-one. And a few seconds is fine for most flows, especially the ones that matter: someone moving money, proving income for a loan, or settling a trade will gladly wait five seconds for a guarantee rooted in mathematics. The hunger for sub-second speed is sharpest in casual, high-frequency, low-stakes interactions, which is exactly where giving up privacy costs the least. So speed and privacy usually point the same way: when the stakes are high enough to want the stronger guarantee, they are high enough that a short wait is no objection. - -And the gap keeps closing from the cryptographic side. [SpeakUp](https://privacy-ethereum.github.io/speakup/) is a VOLE-based zkVM built specifically for proving on resource-constrained devices (phones and browsers), trading larger proofs for minimal work on the prover. It is privacy-first and post-quantum by construction. The point, for this discussion, is that it pushes general-purpose **selective disclosure back onto the user's own device**: prove an arbitrary property of your transcript, reveal nothing else, keep the plaintext where it started. That is the exact privacy property the TEE path gives up, recovered without sending your credential anywhere. We will not oversell it: SpeakUp is interactive, so it lives in the same designated-verifier world described above. It makes client-side privacy fast; making proofs publicly verifiable on-chain is the harder frontier, still open research, and we are working on it. - -So the honest first question is not "TEE or cryptography," it is "do we even need to make this trade?" Increasingly, the answer is no. - -When raw latency really is the binding constraint and the stakes are genuinely low, a well-built TEE deployment like Peer's might be a reasonable call. We would only ask one thing of anyone making that trade: name it. Say "we relocated the privacy guarantee from your device to attested hardware, and here is the vendor, the measurement, and the verification tooling you can check." Peer, to their credit, did. The failure mode is not choosing a TEE; it is letting users believe "verified" means cryptography when it means a signature from a chip. +So the first question is not "TEE or cryptography," it is whether you need the trade at all. When latency genuinely is the binding constraint and the stakes are low, a well-built TEE like Peer's can be a reasonable call. ## You can have both -Notice what actually did the work in Peer's integrity win. It was not that the enclave saw your data. It was that the signing key was bound to attested code, so the operator could not sign a session that never happened. You can get that without giving up any privacy. - -Run the zkTLS verifier *inside* the enclave. It still sees only ciphertext, because the prover decrypts on-device and proves in zero-knowledge, so your plaintext never leaves your device and the privacy stays structural. The enclave's only job is to stop the operator from signing whatever it likes. That is a TEE used as an integrity bound on top of cryptographic privacy, rather than a replacement for it: integrity anchored at 2, privacy at 3. It is close to what TLSNotary already supports through a notary that carries a [TEE attestation of its own code](/docs/protocol/custom_extension). - -It does not make the result trustless. You still trust the vendor for the verifier's integrity, and on-chain it is still a signature. But it buys the integrity Peer is after without moving your credential into someone else's hardware. +
-So when the privacy stakes rise, the cryptographic path is right there, for Peer too. TLSNotary is already one of the primitives in their stack. The deeper point is that this was never really speed versus soundness: a TEE can bound the attestor while the cryptography keeps your plaintext on your device. We are rooting for everyone shipping this. We just want the trust to live somewhere you can see it. +What actually did the work in Peer's integrity win? The signing key was bound to attested code, so the operator could not unilaterally sign a session that never happened. You can get that without giving up any privacy: run the zkTLS verifier *inside* the enclave. It still sees only ciphertext, because the prover decrypts on-device and proves in zero-knowledge. Integrity anchored in hardware, privacy still on your device. - +This was never really speed versus soundness: a TEE can bound the attestor while the cryptography keeps your plaintext on your device. The two compose, so when the privacy stakes rise, the cryptographic path is right there, ready when you need it. We are rooting for everyone shipping this. diff --git a/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg b/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg index 21370c2..2def78a 100644 --- a/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg +++ b/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg @@ -25,7 +25,7 @@ - proof: only the bytes you reveal + proof: only what is necessary diff --git a/blog/2026-06-19-where-trust-lives/why_not_both.jpg b/blog/2026-06-19-where-trust-lives/why_not_both.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ccff6284b57629d1e4275f30792d285cde4835c3 GIT binary patch literal 73780 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
#xd{wr(E$ADznf@LHCy5#kkkJ1GftCt# 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 Date: Mon, 22 Jun 2026 14:56:45 +0200 Subject: [PATCH 5/6] blog: refine 'Where does your trust live?' post wording and framing --- .../dark/plaintext_boundary.svg | 16 ++--- blog/2026-06-19-where-trust-lives/index.md | 64 +++++++++---------- .../light/plaintext_boundary.svg | 16 ++--- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg b/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg index 0a75da8..6618b2a 100644 --- a/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg +++ b/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg @@ -16,12 +16,12 @@ zkTLS (proxy) - + - YOUR DEVICE + USER'S DEVICE credential + response - decrypted on your device + decrypted locally @@ -36,7 +36,7 @@ attestation - Plaintext stays on your device + Plaintext stays on the user's device @@ -45,9 +45,9 @@ TEE-TLS (enclave) - + - YOUR DEVICE + USER'S DEVICE credential encrypt → enclave key @@ -60,11 +60,11 @@ ENCLAVE · operator hardware - your plaintext, decrypted (~1s) + plaintext, decrypted (~1s) attestation - Plaintext leaves your device + Plaintext leaves the user's device diff --git a/blog/2026-06-19-where-trust-lives/index.md b/blog/2026-06-19-where-trust-lives/index.md index e7e500c..d4e32b3 100644 --- a/blog/2026-06-19-where-trust-lives/index.md +++ b/blog/2026-06-19-where-trust-lives/index.md @@ -1,70 +1,70 @@ --- title: "Where does your trust live? Cryptographic soundness and the TEE trade" -# authors: [sinu, heeckhau] -description: "Moving a web proof from zkTLS to a TEE keeps the same on-chain result and can even raise the integrity bar. The honest question is privacy: do you trust a guarantee rooted in mathematics, or one rooted in a signature from a chip?" +authors: [heeckhau] +description: "Moving a web proof from zkTLS to a TEE keeps the same on-chain result and can even raise the integrity bar. The honest question is privacy: is the guarantee rooted in cryptographic soundness, or in a signature from a chip?" --- import Figure from '@site/src/components/Figure'; -Web proofs let you prove a real-world fact (your bank balance, a payment, your identity) to an app that otherwise has no way to trust it. Each one rests on a guarantee: that the data is genuine, and that whatever handled it kept your secrets. The question worth asking is where that guarantee comes from. +Web proofs let a user prove a real-world fact (a bank balance, a payment, an identity) to an app that otherwise has no way to trust it. Each one rests on a guarantee: that the data is genuine, and that the user's secrets stayed private. That guarantee can be rooted in very different places. -[Peer](https://docs.peer.xyz), a noncustodial fiat-to-crypto protocol and arguably the flagship production zkTLS app, just moved its payment verification to a TEE running in AWS Nitro Enclaves. The reason is speed: in their words, from about thirty seconds down to under a second. That is a real win, and [Sachin's public write-up](https://x.com/0xSachinK/status/2062860592906731888) explains the trade honestly, so we will engage it on the merits. +[Peer](https://docs.peer.xyz), a noncustodial fiat-to-crypto protocol and a prominent production zkTLS application, just moved its payment verification to a TEE running in AWS Nitro Enclaves. The reason is speed: in their words, from about thirty seconds down to under a second. That is a real win, and [Sachin's public write-up](https://x.com/0xSachinK/status/2062860592906731888) is candid about the reasoning behind it. -We will not pretend to be neutral: we think zkTLS is the stronger approach, and we want Peer to win. So this post is a good-faith argument for why we believe users will want the cryptographic guarantee back, and how Peer can keep it without giving up the speed that drove the move. The point is also general. Any system that proves "this web data is real" has to root that promise somewhere, and swapping the technology underneath rarely removes the trust. It relocates it. The real question is never trust versus no trust. It is where the trust now lives, and whether you can still see it. +To be clear, we are not neutral: we think zkTLS is the stronger approach and would like to see Peer keep it. For some applications the TEE trade is a defensible call. Either way, web proofs never remove trust; they relocate it. A TEE moves it onto a chip and the vendor that attests to it, but the user's privacy now rests on that attestation rather than on cryptography. -A web proof makes **two** promises, not one, and they come apart the moment you swap zkTLS for a TEE: +A web proof makes **two** promises, not one, and they come apart the moment zkTLS is swapped for a TEE: - **Integrity** (*did this payment really happen?*): both designs end at a delegated attestor's signature that a smart contract checks, and a TEE can make that signature *harder* to forge. This is **not** where the disagreement is. -- **Privacy** (*who gets to see your secrets?*): with zkTLS your credential only ever reaches the server it logs into, kept confidential by **mathematics**; with a TEE it is decrypted inside someone else's hardware, kept confidential by a second **signature**, the enclave's attestation. +- **Privacy** (*who gets to see the user's secrets?*): with zkTLS the user's credential only ever reaches the server it logs into, kept confidential by **cryptography**; with a TEE it is decrypted inside someone else's hardware, kept confidential by a second **signature**, the enclave's attestation. -Switching to a TEE moves the two in opposite directions: integrity **up**, privacy **down**. The rest of this post is about that asymmetry, and how you can avoid having to choose. +Switching to a TEE improves integrity while replacing a cryptographic privacy guarantee with an attestation-based one. ## Integrity: both roads end at a signature Start with what does not change. zkTLS, TLSNotary included, is **designated-verifier**: a proof convinces only the party that took part in the session, and a smart contract cannot be that party. So on-chain there is always a trusted attestor that signs a statement in lieu of a proof, and the contract checks the signature. (We unpack why an in-session witness is unavoidable in a [companion post](/blog/2026/06/17/public-verifiability).) -So if your funds release on a signature, you are trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. That is why Peer's integrity argument is convincing. Their old system was proxy zkTLS with a **single attestor**, and one compromised attestor can sign off on a payment that never happened. Move the signing key inside an enclave and release it only to code whose measured identity matches the published build, and forging an attestation now means breaking the enclave's isolation or compromising the hardware vendor's signing keys, not just relying on one server. As Sachin puts it, *"the trust anchor moves from 'an operator is honest' to 'this exact code ran in isolated hardware.'"* On **integrity**, that is a clean upgrade. +So if a payment releases funds on a signature, the user is trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. That is why Peer's integrity argument is convincing. Their old system was proxy zkTLS with a **single attestor**: Peer alone held the signing key, and one compromised operator could sign off on a payment that never happened. Inside an enclave, the key is released only to code AWS attests, so forging an attestation now means subverting AWS itself, its keys or its isolation, not just compromising one operator. Sachin describes this as the anchor moving *"from 'an operator is honest' to 'this exact code ran in isolated hardware.'"* We would put it more plainly: it moves from Peer to AWS, a far better-resourced and more accountable custodian. On **integrity**, that is a real upgrade. -The cost is on the other axis. +The tradeoff appears on the other axis. -## Privacy: where your plaintext goes +## Privacy: where the plaintext goes -In the proxy-zkTLS flow Peer used to run, your device holds the TLS session. Your credential goes only where it always would, to the server it logs into, and the attestor sees only ciphertext. Your device decrypts the response locally and proves it held the right payment detail. Only that proof crosses to the verifier, revealing only what is necessary while the rest of the response never leaves your device. That is **selective disclosure**, the core privacy primitive of this field. +In the proxy-zkTLS flow Peer used to run, the user's device holds the TLS session. The credential goes only where it always would, to the server it logs into, and the attestor sees only ciphertext. The device decrypts the response locally and proves it held the right payment detail. Only that proof crosses to the verifier, revealing only what is necessary while the rest of the response never leaves the user's device. That is **selective disclosure**, the core privacy primitive of this field. -In the TEE flow, the PeerAuth extension reads your live session token and **encrypts it to the enclave's public key**. The enclave makes the request itself, sees the full plaintext response, and emits the attestation. Your credential and the response now exist, in the clear, inside a machine the operator runs. Selective disclosure is gone: the enclave sees everything, and you trust it to emit only the attestation and forget the rest. +In the TEE flow, the PeerAuth extension reads the user's live session token and **encrypts it to the enclave's public key**. The enclave makes the request itself, sees the full plaintext response, and emits the attestation. The credential and the response now exist in the clear inside a machine the operator runs. In that flow, selective disclosure is gone: the enclave sees everything, and the user trusts it to emit only the attestation and forget the rest.
-Peer's own description is fair: nothing is stored, the credential lives in memory for about a second, and only the attestation leaves. Their conclusion is that *"the privacy guarantees are identical to zkTLS, with better UX."* On a day when everything works exactly as designed, that is true. Our objection is to the word *identical*, because the **basis** of the guarantee changed: +Peer's own description is fair: nothing is stored, the credential lives in memory for about a second, and only the attestation leaves. Their conclusion is that *"the privacy guarantees are identical to zkTLS, with better UX."* On a day when everything works exactly as designed, that may be true. Our objection is to the word *identical*, because the **basis** of the guarantee changed: -> With zkTLS, the confidentiality of your credential is **structural**: a fact about *where the computation happened* (your device) and *what left it* (a proof). With a TEE it is **contingent on a signature**: an attestation saying the code that saw your plaintext was the published code, running in hardware that promises not to leak it. Even when the integrity is identical, that is a weaker kind of guarantee. +> With zkTLS, the confidentiality of the user's credential is **structural**: a fact about *where the computation happened* (the user's device) and *what left it* (a proof). With a TEE it is **contingent on a signature**: an attestation saying the code that saw the plaintext was the published code, running in hardware that promises not to leak it. Even when the integrity is identical, that is a weaker kind of guarantee. -A cryptographic guarantee holds regardless of whether the operator is honest or the vendor was compelled. An attestation-backed one holds *as long as the attestation means what you think it means*. Those are reasonable things to believe. They are not the same kind of thing as "no third party ever saw your credential." +A cryptographic guarantee holds regardless of whether the operator is honest or the vendor was compelled. An attestation-backed one holds *as long as the attestation means what it appears to mean*. Those are reasonable things to believe. They are not the same kind of thing as "no third party ever saw the user's credential." -And the difference stays invisible until it doesn't. A forged payment would be bad, but that is the integrity failure everyone guards against, and the TEE makes it harder. The privacy downgrade opens a quieter one: a **stolen credential**. The attestation document tells your client which key to encrypt your credential to. Forge that document, binding a key *you* control to the expected measurement, and the victim's client encrypts straight to you. The signature verifies, so nothing looks wrong: the attack is silent, targetable at one user, and invisible to the victim. The credential was encrypted perfectly, to the wrong party. +And the difference stays invisible until it doesn't. A forged payment would be bad, but that is the integrity failure everyone guards against, and the TEE makes it harder. The privacy downgrade opens a quieter one: a **stolen credential**. The attestation document tells the user's client which key to encrypt the credential to. If an attacker can forge that document, binding a key *the attacker* controls to the expected measurement, the victim's client encrypts straight to the attacker. The signature verifies, so nothing looks wrong: the attack is silent, targetable at one user, and invisible to the victim. The credential was encrypted perfectly, to the wrong party. ## Can you check it yourself? -To their credit, Peer ships an npm package, [`@zkp2p/zkp2p-attestation`](https://www.npmjs.com/package/@zkp2p/zkp2p-attestation), that lets a client fetch the attestation, verify AWS's Nitro signature chain, and check the measurement *before* handing over anything sensitive. The correct pattern is **attest, then encrypt**: verify the binding first, because a public key is just bytes, and an *unattested* one could be decrypting your credential outside any enclave at all. +To their credit, Peer ships an npm package, [`@zkp2p/zkp2p-attestation`](https://www.npmjs.com/package/@zkp2p/zkp2p-attestation), that lets a client fetch the attestation, verify AWS's Nitro signature chain, and check the measurement *before* handing over anything sensitive. The correct pattern is **attest, then encrypt**: verify the binding first, because a public key is just bytes, and an *unattested* one could be decrypting the credential outside any enclave at all. But notice the limits of that check. It answers "am I talking to a genuine enclave running the expected measurement?" It does not answer: -1. **A measurement is a hash, not a meaning.** Matching PCR `abc123` tells you the *expected* image loaded, not that `abc123` is the *honest* code. To know that, you need the source, a reproducible build, and the same hash. Peer says they will open-source it; as of writing, that has not shipped. -2. **Someone has to run the check.** On a phone, the thing verifying the attestation is the client Peer ships. It can verify diligently or skip, and the user cannot tell from the outside. -3. **AWS is the root, unconditionally.** The chain ends at AWS's keys, and "the host cannot read enclave memory" is AWS's word. Whoever holds that key can be compelled to use it and legally barred from disclosing it, and you would have no way to tell, because the signature would verify like any other. +1. **A measurement is a hash, not a meaning.** Matching PCR `abc123` tells a verifier the *expected* image loaded, not that `abc123` is the *honest* code. Establishing that requires the source, a reproducible build, and a matching hash. Peer says they will open-source it; as of writing, that has not shipped. +2. **Someone has to run the check.** On a phone, the thing verifying the attestation is the client Peer ships. It can verify diligently or skip verification, and the user cannot tell from the outside. +3. **AWS is the root, unconditionally.** The chain ends at AWS's keys, and "the host cannot read enclave memory" is AWS's word. Whoever holds that key can be compelled to use it and legally barred from disclosing it, and there would be no way to tell, because the signature would verify like any other. None of these make the design bad. They show where the trust actually lives. -## The hardware is not the point +## The upgrade was not the hardware -It is tempting to argue about whether the enclave can be broken. That is the wrong axis. Even when the silicon works perfectly, what a verifier actually checks is a **signature**: does this attestation chain to a key I trust? The hardware's only job is to keep that key secret, so the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave by construction. Which TEE you pick, Intel SGX or AWS Nitro, does not change this. You have not removed your trust in the zkTLS verifier operator; you have moved it to Intel or Amazon. It is the **same kind** of trust, a secret key held by someone else, just relocated to a better-resourced custodian. +The upgrade is real, but it is worth being precise about what produced it, because it was not the silicon. It is tempting to argue about whether the enclave can be broken, but the strength of the design does not turn on that. Even if the hardware is perfect, what a verifier checks is still a **signature**: does this attestation chain to a key it trusts? The enclave's only job is to keep that key secret, so the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave by construction. Which TEE, Intel SGX or AWS Nitro, makes no difference to that basic structure. The trust in Peer has not vanished; it moved to AWS, which is the **same kind** of trust: a secret key held by someone else, just in more capable hands.
-That is the difference mathematics makes. In a soundness-rooted design your plaintext never left your device, so there is no key whose compromise hands over your data, because there is nothing to redirect: no operator to trust, no measurement to map to source, no vendor at the root. The honest pitch for a TEE is "stronger than trusting one operator's word," not "as good as math." +That is the difference cryptography makes. In a soundness-rooted design the user's plaintext never left their device, so there is no key whose compromise hands over their data, because there is nothing to redirect: no operator to trust, no measurement to map to source, no vendor at the root. The accurate pitch for a TEE is "stronger than trusting one operator's word," not "as good as cryptographic soundness." -## Do we even need the trade? +## The trade may not be necessary -The obvious rebuttal is that math is too slow. But thirty seconds came from an older proxy implementation, not from where zkTLS sits today: TLSNotary's proxy mode already runs in under two seconds ([latest benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode)). A sub-second enclave is still faster, but that is nothing like thirty to one, and for the case Peer is built around, verifying a payment, a second or two is a small price for a guarantee rooted in mathematics rather than a signature. +The obvious rebuttal is that cryptography is too slow. But thirty seconds came from an older proxy implementation, not from where zkTLS sits today: TLSNotary's proxy mode already runs in under two seconds ([latest benchmarks](https://tlsnotary.org/blog/2026/05/10/blog-proxy-mode)). A sub-second enclave is still faster, but that is nothing like thirty to one, and for the use case Peer is built around, payment verification, a second or two is a small price for a guarantee rooted in cryptographic soundness rather than a signature. -And the gap keeps closing: [SpeakUp](https://privacy-ethereum.github.io/speakup/), a VOLE-based zkVM built for phones and browsers, makes selective disclosure fast and flexible: it proves arbitrary logic, much like a program running in a TEE, but keeps your secrets on the prover's side, the very thing a TEE gives up. +And the gap keeps closing: [SpeakUp](https://privacy-ethereum.github.io/speakup/), a VOLE-based zkVM built for phones and browsers, makes selective disclosure fast and flexible: it proves arbitrary logic, much like a program running in a TEE, but keeps the secrets on the prover's side, the very thing a TEE gives up. -So the first question is not "TEE or cryptography," it is whether you need the trade at all. When latency genuinely is the binding constraint and the stakes are low, a well-built TEE like Peer's can be a reasonable call. +So the choice is rarely "TEE or cryptography" in the first place. When latency genuinely is the binding constraint and the stakes are low, a well-built TEE like Peer's can be a reasonable call. ## You can have both
-What actually did the work in Peer's integrity win? The signing key was bound to attested code, so the operator could not unilaterally sign a session that never happened. You can get that without giving up any privacy: run the zkTLS verifier *inside* the enclave. It still sees only ciphertext, because the prover decrypts on-device and proves in zero-knowledge. Integrity anchored in hardware, privacy still on your device. +What actually did the work in Peer's integrity win? The signing key was bound to attested code, so the operator could not unilaterally sign a session that never happened. That works without giving up any privacy: run the zkTLS verifier *inside* the enclave. It still sees only ciphertext, because the prover decrypts on-device and proves in zero-knowledge. Integrity anchored in a TEE, privacy still on the user's device. -This was never really speed versus soundness: a TEE can bound the attestor while the cryptography keeps your plaintext on your device. The two compose, so when the privacy stakes rise, the cryptographic path is right there, ready when you need it. We are rooting for everyone shipping this. +This was never really speed versus soundness: a TEE can bound the attestor while the cryptography keeps the user's plaintext on their device. The two compose, so when the privacy stakes rise, the cryptographic path is right there when it is needed. That combination is what we hope more teams will ship. diff --git a/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg b/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg index 2def78a..8392b3e 100644 --- a/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg +++ b/blog/2026-06-19-where-trust-lives/light/plaintext_boundary.svg @@ -16,12 +16,12 @@ zkTLS (proxy) - + - YOUR DEVICE + USER'S DEVICE credential + response - decrypted on your device + decrypted locally @@ -36,7 +36,7 @@ attestation - Plaintext stays on your device + Plaintext stays on the user's device @@ -45,9 +45,9 @@ TEE-TLS (enclave) - + - YOUR DEVICE + USER'S DEVICE credential encrypt → enclave key @@ -60,11 +60,11 @@ ENCLAVE · operator hardware - your plaintext, decrypted (~1s) + plaintext, decrypted (~1s) attestation - Plaintext leaves your device + Plaintext leaves the user's device From 71b891bc4269d7c66ec77effb55a43880914a32b Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Tue, 23 Jun 2026 10:39:48 +0200 Subject: [PATCH 6/6] blog: revise trust-lives per Sachin feedback, plus terminology and emphasis cleanup - credit Peer's 30s as a real production figure (not a benchmark) from an older proxy implementation - state Nitro isolation plainly (Peer cannot read enclave memory); the critique is the shifted basis of privacy, not that Peer sees credentials - frame the forged-attestation case as an AWS signature-chain break, not a unilateral operator move; refocus the closer on 'no secret to leak' - note the enclave validates the response before signing - split terminology: 'attestor's signature' (integrity output) vs 'attestation' (TEE self-attestation), post-wide - tighten bold to labels and coined terms only; move conceptual contrasts to italic; de-italicize quoted text - set post date to 2026-06-23 --- .../dark/plaintext_boundary.svg | 0 .../dark/three_anchors.svg | 0 .../index.md | 22 +++++++++--------- .../light/plaintext_boundary.svg | 0 .../light/three_anchors.svg | 0 .../why_not_both.jpg | Bin 6 files changed, 11 insertions(+), 11 deletions(-) rename blog/{2026-06-19-where-trust-lives => 2026-06-23-where-trust-lives}/dark/plaintext_boundary.svg (100%) rename blog/{2026-06-19-where-trust-lives => 2026-06-23-where-trust-lives}/dark/three_anchors.svg (100%) rename blog/{2026-06-19-where-trust-lives => 2026-06-23-where-trust-lives}/index.md (67%) rename blog/{2026-06-19-where-trust-lives => 2026-06-23-where-trust-lives}/light/plaintext_boundary.svg (100%) rename blog/{2026-06-19-where-trust-lives => 2026-06-23-where-trust-lives}/light/three_anchors.svg (100%) rename blog/{2026-06-19-where-trust-lives => 2026-06-23-where-trust-lives}/why_not_both.jpg (100%) diff --git a/blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg b/blog/2026-06-23-where-trust-lives/dark/plaintext_boundary.svg similarity index 100% rename from blog/2026-06-19-where-trust-lives/dark/plaintext_boundary.svg rename to blog/2026-06-23-where-trust-lives/dark/plaintext_boundary.svg diff --git a/blog/2026-06-19-where-trust-lives/dark/three_anchors.svg b/blog/2026-06-23-where-trust-lives/dark/three_anchors.svg similarity index 100% rename from blog/2026-06-19-where-trust-lives/dark/three_anchors.svg rename to blog/2026-06-23-where-trust-lives/dark/three_anchors.svg diff --git a/blog/2026-06-19-where-trust-lives/index.md b/blog/2026-06-23-where-trust-lives/index.md similarity index 67% rename from blog/2026-06-19-where-trust-lives/index.md rename to blog/2026-06-23-where-trust-lives/index.md index d4e32b3..b73978e 100644 --- a/blog/2026-06-19-where-trust-lives/index.md +++ b/blog/2026-06-23-where-trust-lives/index.md @@ -14,10 +14,10 @@ To be clear, we are not neutral: we think zkTLS is the stronger approach and wou -A web proof makes **two** promises, not one, and they come apart the moment zkTLS is swapped for a TEE: +A web proof makes two promises, not one, and they come apart the moment zkTLS is swapped for a TEE: -- **Integrity** (*did this payment really happen?*): both designs end at a delegated attestor's signature that a smart contract checks, and a TEE can make that signature *harder* to forge. This is **not** where the disagreement is. -- **Privacy** (*who gets to see the user's secrets?*): with zkTLS the user's credential only ever reaches the server it logs into, kept confidential by **cryptography**; with a TEE it is decrypted inside someone else's hardware, kept confidential by a second **signature**, the enclave's attestation. +- **Integrity** (*did this payment really happen?*): both designs end at a delegated attestor's signature that a smart contract checks, and a TEE can make that signature *harder* to forge. This is *not* where the disagreement is. +- **Privacy** (*who gets to see the user's secrets?*): with zkTLS the user's credential only ever reaches the server it logs into, kept confidential by *cryptography*; with a TEE it is decrypted inside someone else's hardware, kept confidential by a second *signature*, the enclave's attestation. Switching to a TEE improves integrity while replacing a cryptographic privacy guarantee with an attestation-based one. @@ -25,7 +25,7 @@ Switching to a TEE improves integrity while replacing a cryptographic privacy gu Start with what does not change. zkTLS, TLSNotary included, is **designated-verifier**: a proof convinces only the party that took part in the session, and a smart contract cannot be that party. So on-chain there is always a trusted attestor that signs a statement in lieu of a proof, and the contract checks the signature. (We unpack why an in-session witness is unavoidable in a [companion post](/blog/2026/06/17/public-verifiability).) -So if a payment releases funds on a signature, the user is trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. That is why Peer's integrity argument is convincing. Their old system was proxy zkTLS with a **single attestor**: Peer alone held the signing key, and one compromised operator could sign off on a payment that never happened. Inside an enclave, the key is released only to code AWS attests, so forging an attestation now means subverting AWS itself, its keys or its isolation, not just compromising one operator. Sachin describes this as the anchor moving *"from 'an operator is honest' to 'this exact code ran in isolated hardware.'"* We would put it more plainly: it moves from Peer to AWS, a far better-resourced and more accountable custodian. On **integrity**, that is a real upgrade. +So if a payment releases funds on a signature, the user is trusting that attestor, whether the box behind it runs MPC, a proxy, or an enclave. That is why Peer's integrity argument is convincing. Their old system was proxy zkTLS with a single attestor: Peer alone held the signing key, and one compromised operator could sign off on a payment that never happened. Inside an enclave, the key is released only to code AWS attests, so forging the attestor's signature now means subverting AWS itself, its keys or its isolation, not just compromising one operator. Sachin describes this as the anchor moving "from 'an operator is honest' to 'this exact code ran in isolated hardware.'" We would put it more plainly: it moves from Peer to AWS, a far better-resourced and more accountable custodian. On integrity, that is a real upgrade. The tradeoff appears on the other axis. @@ -33,22 +33,22 @@ The tradeoff appears on the other axis. In the proxy-zkTLS flow Peer used to run, the user's device holds the TLS session. The credential goes only where it always would, to the server it logs into, and the attestor sees only ciphertext. The device decrypts the response locally and proves it held the right payment detail. Only that proof crosses to the verifier, revealing only what is necessary while the rest of the response never leaves the user's device. That is **selective disclosure**, the core privacy primitive of this field. -In the TEE flow, the PeerAuth extension reads the user's live session token and **encrypts it to the enclave's public key**. The enclave makes the request itself, sees the full plaintext response, and emits the attestation. The credential and the response now exist in the clear inside a machine the operator runs. In that flow, selective disclosure is gone: the enclave sees everything, and the user trusts it to emit only the attestation and forget the rest. +In the TEE flow, the PeerAuth extension reads the user's live session token and encrypts it to the enclave's public key. The enclave makes the request itself, sees the full plaintext response, checks it against the expected payment details, and emits the attestor's signature. The credential and the response now exist in the clear inside the enclave. Under the Nitro security assumptions, Peer cannot read that memory, but the enclave sees everything, and the user trusts that the isolation holds and that the enclave emits only that signature and forgets the rest.
-Peer's own description is fair: nothing is stored, the credential lives in memory for about a second, and only the attestation leaves. Their conclusion is that *"the privacy guarantees are identical to zkTLS, with better UX."* On a day when everything works exactly as designed, that may be true. Our objection is to the word *identical*, because the **basis** of the guarantee changed: +Peer's own description is fair: nothing is stored, the credential lives in memory for about a second, and only the attestor's signature leaves. Their conclusion is that "the privacy guarantees are identical to zkTLS, with better UX." On a day when everything works exactly as designed, that may be true. Our objection is to the word *identical*, because the *basis* of the guarantee changed: -> With zkTLS, the confidentiality of the user's credential is **structural**: a fact about *where the computation happened* (the user's device) and *what left it* (a proof). With a TEE it is **contingent on a signature**: an attestation saying the code that saw the plaintext was the published code, running in hardware that promises not to leak it. Even when the integrity is identical, that is a weaker kind of guarantee. +> With zkTLS, the confidentiality of the user's credential is *structural*: a fact about *where the computation happened* (the user's device) and *what left it* (a proof). With a TEE it is *contingent on a signature*: an attestation saying the code that saw the plaintext was the published code, running in hardware that promises not to leak it. Even when the integrity is identical, that is a weaker kind of guarantee. A cryptographic guarantee holds regardless of whether the operator is honest or the vendor was compelled. An attestation-backed one holds *as long as the attestation means what it appears to mean*. Those are reasonable things to believe. They are not the same kind of thing as "no third party ever saw the user's credential." -And the difference stays invisible until it doesn't. A forged payment would be bad, but that is the integrity failure everyone guards against, and the TEE makes it harder. The privacy downgrade opens a quieter one: a **stolen credential**. The attestation document tells the user's client which key to encrypt the credential to. If an attacker can forge that document, binding a key *the attacker* controls to the expected measurement, the victim's client encrypts straight to the attacker. The signature verifies, so nothing looks wrong: the attack is silent, targetable at one user, and invisible to the victim. The credential was encrypted perfectly, to the wrong party. +And the difference stays invisible until it doesn't. A forged payment would be bad, but that is the integrity failure everyone guards against, and the TEE makes it harder. The privacy downgrade opens a quieter one: a stolen credential. The attestation document tells the user's client which key to encrypt the credential to. Redirecting it would mean forging that document to bind a key *the attacker* controls, which takes subverting AWS's Nitro signature chain itself. But if that root gives way, the credential is encrypted straight to the attacker and every signature still verifies, so nothing looks wrong. This is the catastrophic case, not the everyday one, and that is the point: with cryptographic soundness the credential never leaves the device, so there is no secret to leak. ## Can you check it yourself? @@ -64,7 +64,7 @@ None of these make the design bad. They show where the trust actually lives. ## The upgrade was not the hardware -The upgrade is real, but it is worth being precise about what produced it, because it was not the silicon. It is tempting to argue about whether the enclave can be broken, but the strength of the design does not turn on that. Even if the hardware is perfect, what a verifier checks is still a **signature**: does this attestation chain to a key it trusts? The enclave's only job is to keep that key secret, so the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave by construction. Which TEE, Intel SGX or AWS Nitro, makes no difference to that basic structure. The trust in Peer has not vanished; it moved to AWS, which is the **same kind** of trust: a secret key held by someone else, just in more capable hands. +The upgrade is real, but it is worth being precise about what produced it, because it was not the silicon. It is tempting to argue about whether the enclave can be broken, but the strength of the design does not turn on that. Even if the hardware is perfect, what a verifier checks is still a signature: does it chain to a key it trusts? The enclave's only job is to keep that key secret, so the guarantee is only ever as strong as the key's custody, and the custodian sits *outside* the enclave by construction. Which TEE, Intel SGX or AWS Nitro, makes no difference to that basic structure. The trust in Peer has not vanished; it moved to AWS, which is the same kind of trust: a secret key held by someone else, just in more capable hands.