Our guarantee
Every claim in the Reclaim Protocol whitepaper is re-verified monthly against the open-source code that runs in production. The verdict and the source files are published per claim.
The threat model
How it’s enforced
How you verify
What you still trust

Reclaim Protocol Whitepaper
View on Google Drive
Today · Jun 24· 42 days ahead are placeholders for future runs
24/24 claims passed, 0 partial · 0 cached from previous run
Every statement we make in our whitepaper is re-verified monthly against the open-source code. For each claim below you can see the AI's reasoning and open the exact files it inspected on GitHub.
All sensitive data masked by the user is correctly reapplied when TEEA reconstructs the full request ciphertext, ensuring no sensitive bytes are exposed to either TEE
AI reasoning
Verified. TEE_T reconstructs the full request ciphertext by XORing the redacted ciphertext with the user-supplied redaction streams (one stream per masked range), operating entirely on ciphertext — no decryption keys ever reach TEE_T. The HMAC-SHA256 commitment scheme ensures the streams are authentic before application. TEE_K never sends kenc/kdec/IV to TEE_T; it only sends TagSecrets (EK(0^128) and EK(nonce||1) for AES-GCM, or the Poly1305 key for ChaCha20). Sensitive bytes are thus reconstructed in ciphertext space only, and neither TEE sees the plaintext of masked ranges. (negation-aware aggregation across 3 chunks)
The protocol monitors BGP announcements via RIPE RIS to detect traffic rerouting between the attestor and the website during proof creation
AI reasoning
Verified. The attestor opens a live WebSocket connection to RIPE RIS (`wss://ris-live.ripe.net/v1/ws/?client=reclaim-hijack-detector`), subscribes to BGP UPDATE announcements, and checks each announced prefix against registered target IPs using CIDR containment. When an overlap is detected, the active tunnel is closed with an `ERROR_BGP_ANNOUNCEMENT_OVERLAP` error. This listener is started for every new tunnel connection in the `createTunnel` handler. (standard aggregation across 2 chunks)
For AES-GCM, TagSecrets passed from TEEK to TEEA consists of EK(0^128) and EK(IV||0^31||1)
AI reasoning
Verified. For AES-GCM, the code computes TagSecrets as a 32-byte buffer: the first 16 bytes are E_K(0^128) (AES block encryption of an all-zero block, the GCM hash subkey H), and the last 16 bytes are E_K(IV||0^31||1) (AES block encryption of the 12-byte nonce padded to 16 bytes with the last byte set to 1, the J0 counter block). This matches the whitepaper claim exactly. (standard aggregation across 3 chunks)
User sends connection parameters (hostname, port, SNI, ALPN) to TEEK at the start of the TLS handshake phase
AI reasoning
Verified. Before any TLS bytes are exchanged, the client builds a connection request containing hostname, port, SNI, and ALPN (defaulting to 'http/1.1') and sends it to TEEK via the RequestConnection protobuf message. TEEK receives this in handleRequestConnection, stores it, and only then initiates the TLS handshake. There is no code path that starts the handshake before these parameters are received. (standard aggregation across 6 chunks)
TEEK produces signature sigma_K over the concatenation of Rred, StrDec,Red, and the website's SSL Certificate
AI reasoning
Verified. TEEK builds a KOutputPayload containing the redacted request (Rred), the consolidated response keystream (StrDec,Red), and the SSL certificate info, marshals it with proto.Marshal, then signs the resulting bytes using Ethereum-style ECDSA via SignData. All three fields are included in the same signed payload with no separate intermediate signature. (standard aggregation across 3 chunks)
The proof output Pi consists of the two signatures (sigma_K, sigma_A) and the session-related data that was signed
AI reasoning
Verified. The proof output consists of exactly two signed payloads: TEE_K produces a SignedMessage with BodyType BODY_TYPE_K_OUTPUT (sigma_K over KOutputPayload), and TEE_T produces a SignedMessage with BodyType BODY_TYPE_T_OUTPUT (sigma_A over TOutputPayload). The client collects both into a VerificationBundle (teek_signed + teet_signed fields) and submits it to the attestor. No third signature or extra payload exists in the flow. (standard aggregation across 4 chunks)
All sensitive portions of the request are masked by the user before being sent to TEEK, ensuring TEEK never sees any raw sensitive data
AI reasoning
Verified. The client generates random XOR streams per redaction range using crypto/rand, applies them to the plaintext (applyRedaction XORs each byte), and sends only the masked request to TEE_K via the RedactedRequest envelope (containing RedactedRequest, Commitments, RedactionRanges — no streams). The streams are sent separately to TEE_T. TEE_K's encryptAndSendRequest reads rawPlaintext directly from redactedRequest.RedactedRequest without any unmasking step, confirming it never sees the original sensitive bytes. (negation-aware aggregation across 6 chunks)
TEEK encrypts the redacted request as Rred,enc = Rred XOR Stream(kenc, nonce)
AI reasoning
Verified. TEEK receives the redacted request (Rred), derives the client application key (kenc) and IV, constructs the nonce as IV XOR sequence number, then calls EncryptWithoutTag which computes the keystream via AES-CTR or ChaCha20 and XORs it with the fragment data — exactly Rred,enc = Rred XOR Stream(kenc, nonce). The result is batched and forwarded to TEE_T. (standard aggregation across 3 chunks)
For ChaCha20-Poly1305, TagSecrets consists of the first 32 bytes of the encryption stream derived at counter value 0
AI reasoning
Verified. For ChaCha20-Poly1305, the code generates TagSecrets by creating a ChaCha20 cipher with the session key and nonce, setting the counter to 0, then XOR-ing 32 zero bytes to extract the first 32 bytes of the keystream — exactly the standard Poly1305 one-time key per RFC 7539. This is implemented in `generateChaChaTagSecrets` and used in `EncryptWithoutTag` for all ChaCha20-Poly1305 cipher suites. (standard aggregation across 3 chunks)
The user does not learn the TLS session encryption keys at any point before both TEEs switch to FINISHED phase
AI reasoning
Verified. TEE_K derives TLS session keys (kenc, kdec, IV) internally during the handshake and never returns them to the client. The HandshakeComplete message sent to the client contains only a success flag and cipher suite — no key fields. The SignedMessage (sent after FINISHED phase) includes the server application key in a non-signed metadata field for client-side decryption assistance, but this only occurs after both TEEs have completed their FINISHED-phase signing. The client never holds keys before the FINISHED phase. (negation-aware aggregation across 3 chunks)
TEEA computes authentication tag T = AuthTag(Renc, TagSecrets) and sends it to the user for forwarding to the website
AI reasoning
Verified. TEEA (TEE_T) computes the AEAD authentication tag using ComputeTagFromSecrets(), which implements the correct GCM GHASH computation for AES-GCM and Poly1305 for ChaCha20. The result is packaged as BatchedEncryptedDataResponse and routed back to the client via RouteToClient(). The client then frames the encrypted data plus auth tag into a TLS record and writes it to the TCP connection to the website. (standard aggregation across 3 chunks)
TEEK replaces bytes at user-specified SecretRanges in StrDec with '*' to produce StrDec,Red before signing
AI reasoning
Verified. TEEK iterates over user-supplied SecretRanges (ResponseRedactionSpec.Ranges), overwrites the corresponding bytes in the decryption keystream with cryptographically random bytes via rand.Read, stores the result as session.RedactedStreams, and includes the consolidated redacted keystream in the signed KOutputPayload. The verifier-side XOR then produces '*' at those positions. No unredacted stream is ever signed. (standard aggregation across 3 chunks)
The protocol uses exactly two separate TEEs: TEEK (holds TLS keys) and TEEA (computes auth tags without key access)
AI reasoning
Verified. The codebase contains exactly two TEE packages: tee_k/ (TEEK) handles TLS handshakes and holds encryption keys via DeriveHandshakeKeys/DeriveApplicationKeys, while tee_t/ (TEET) computes authentication tags from TagSecrets only via ComputeTagFromSecrets without access to the encryption keys. Each signs a distinct payload type (KOutputPayload vs TOutputPayload). No third TEE package exists. (negation-aware aggregation across 3 chunks)
TEEA produces signature sigma_A over the concatenation of Respenc, Tresp, and StrSP
AI reasoning
Verified. TEEA (TEE_T) signs a payload containing all three required fields: ConsolidatedResponseCiphertext (Respenc), RequestProofStreams (StrSP), and the response tag secrets verified earlier in session_handlers.go (Tresp). These are marshaled together via proto.Marshal into a single TOutputPayload body, then signed with SignData using the TEEA signing key, producing sigma_A. (standard aggregation across 3 chunks)
TEEK signs the SSL Certificate of the website received during the TLS handshake as part of its attestation commitment
AI reasoning
Verified. During the TLS handshake, TEEK extracts and stores certificate information from the server's certificate chain. When generating its attestation signature, TEEK sets `kPayload.CertificateInfo = session.CertificateInfo`, marshals the full `KOutputPayload` protobuf (which includes the cert chain), and signs the resulting bytes using an Ethereum-style secp256k1 signature. The SSL certificate is therefore cryptographically bound inside the signed payload. (standard aggregation across 3 chunks)
TEEK derives three session keys (kenc, kdec, IV) during the TLS handshake and does not share them with the user
AI reasoning
Verified. During the TLS handshake, TEEK derives clientAppKey (kenc), serverAppKey (kdec), and clientAppIV/serverAppIV (IV) via KeySchedule.DeriveHandshakeKeys and DeriveApplicationKeys in minitls/crypto.go. The HandshakeComplete envelope sent back to the client contains only a success flag and cipher suite — no key material. Keys remain inside the TLS client state within the enclave and are consumed internally by the split-AEAD encryption path. (negation-aware aggregation across 3 chunks)
TEEA verifies the website response authentication tag before any decryption material is released; the session aborts if verification fails
AI reasoning
Verified. TEEA (TEE_T) verifies the authentication tag for each encrypted response before releasing any decryption material. In handleBatchedTagSecrets, verifyTagForResponse calls ComputeTagFromSecrets and uses subtle.ConstantTimeCompare against the actual tag. If verification fails, allSuccessful is set to false, the failure result is sent to TEE_K, and terminateSessionWithError is called — aborting the session. TEE_K's decryption stream generation only proceeds after receiving a BatchedTagVerifications message with AllSuccessful=true. (standard aggregation across 3 chunks)
TEEK generates the decryption stream as StrDec = Stream(kdec, nonceresp, |Respenc|) only after receiving a success signal from TEEA
AI reasoning
Verified. TEE_T's handleBatchedTagSecrets calls verifyTagForResponse (which uses ComputeTagFromSecrets) and only sends BatchedTagVerifications with AllSuccessful=true to TEE_K on success. TEE_K's handleRedactionSpec calls generateAndSendRedactedDecryptionStreamResponse, which invokes GenerateDecryptionStreamWithNonce using the server app key (kdec), the response nonce, and response length — matching the claimed sequence exactly. No earlier handler produces the decryption stream. (standard aggregation across 3 chunks)
TEEK verifies the website's SSL certificate
AI reasoning
Verified. The TEE_K client performs full SSL certificate chain validation during the TLS handshake with the target website. The code parses the server's certificate chain, verifies signatures using ECDSA/RSA-PSS/RSA-PKCS1/Ed25519, checks hostname via RFC 6125, validates against system root CAs, and fetches missing intermediates via AIA. Both TLS 1.2 and TLS 1.3 paths include this verification. (standard aggregation across 2/3 chunks; dropped 1 chunk-not-found artifact)
Verifier reconstructs the revealed request by copying Rred and replacing bytes in non-proof redaction ranges (requestRedactionRanges without 'proof' type) with redaction characters for display
AI reasoning
Verified. The reconstructRequest function copies kOutputPayload.redactedRequest into revealedRequest, then makes a second copy (prettyRequest). It iterates requestRedactionRanges and, for any range whose type does NOT include 'proof', overwrites bytes in [start, start+length) with REDACTION_CHAR_CODE ('*'). Ranges with 'proof' in their type are skipped, leaving proof data visible. The function returns prettyRequest. (negation-aware aggregation across 2 chunks)
Attestor validates the website's SSL Certificate as a distinct step during proof verification
AI reasoning
Verified. The attestor validates the website's SSL certificate as a distinct step during proof verification. In `tee-verification.ts`, after both TEE signatures are verified, `parseKOutputPayload` explicitly checks that `certificateInfo` is present and throws if missing. In `claimTeeBundle.ts`, `validateTlsCertificate` is called as a separate step that checks the certificate's hostname (including wildcard support) and validity period against the claimed domain. (standard aggregation across 3 chunks)
If a potentially malicious BGP announcement is detected, the current connection and proof creation are dropped
AI reasoning
Verified. When a BGP announcement overlaps with a target IP, the system immediately closes the active tunnel with an ERROR_BGP_ANNOUNCEMENT_OVERLAP error, aborting proof creation. The BGP listener monitors RIPE RIS live data, and the tunnel handler registers an overlap callback that calls tunnel.close() with the specific error upon detection. (standard aggregation across 2 chunks)
Attestor reconstructs the revealed response as reconstructedResponse = consolidated_response_ciphertext (Respenc) XOR consolidated_response_keystream (StrDec,Red from TEEK) directly using redacted keystream (no full decryption keys)
AI reasoning
Verified. The attestor reconstructs the response by XOR-ing the consolidated keystream from TEE_K (consolidatedResponseKeystream, which is the redacted StrDec,Red) with the consolidated ciphertext from TEE_T (consolidatedResponseCiphertext, which is Respenc). The in-place XOR loop `reconstructedResponse[i] = consolidatedKeystream[i] ^ consolidatedCiphertext[i]` is exactly the described operation. No full decryption keys are passed — only the pre-computed redacted keystream from TEE_K is used. (standard aggregation across 2 chunks)
Proof verification checks both ECDSA signatures against the public keys of TEEK (pkK) and TEEA (pkT)
AI reasoning
Verified. The code parses both TEE_K and TEE_T signed payloads, extracts their public keys from attestation reports (Nitro or GCP), and verifies each ECDSA signature independently using the ETH signature provider. If either signature fails, the function throws an error — there is no success path that bypasses either check. (standard aggregation across 6 chunks)