How to use TEE models on Obscurify
A TEE (trusted execution environment) model runs inside a confidential-computing enclave: the processor and GPU encrypt the memory the model works in, so the company operating the server can’t read your prompts or the model’s answers, even with full access to the machine. The hardware also signs a report (an attestation) proving which code is running inside the enclave, so the operator can’t quietly swap in a version that copies your data.
Obscurify offers TEE models in the web chat, the Android app and the API, with the same account and balance as every other model. Every one of them works in Encrypted mode, where your device encrypts the conversation so that only the enclave can read it.
Which models run in a TEE
| Model | API id | Price per 1M tokens (input / output) | Context |
|---|---|---|---|
| GLM 5.3 TEE | tee/glm-5.3 | $1.82 / $5.72 | 1M |
| GLM 5.3 Flash TEE | tee/glm-5.3-flash | $0.195 / $0.65 | 1M |
| GLM 5.2 TEE | tee/glm-5.2 | $1.638 / $3.90 | 1M |
| GLM 5.1 TEE | tee/glm-5.1 | $1.573 / $5.46 | 203K |
| Kimi K3.1 Pro TEE | tee/kimi-k3.1-pro | $2.60 / $13.00 | 1M |
| Kimi K3 TEE | tee/kimi-k3 | $3.90 / $19.50 | 1M |
| Kimi K2.6 TEE | tee/kimi-k2.6 | $1.417 / $5.98 | 262K |
| DeepSeek V4.1 Flash 1017 TEE | tee/deepseek-v4.1-flash-1017 | $0.975 / $2.08 | 1M |
| DeepSeek V3.2 TEE | tee/deepseek-v3.2 | $1.30 / $1.30 | 164K |
| Qwen3.8 27B TEE | tee/qwen3.8-27b | $0.26 / $3.25 | 1M |
| Qwen3.6 27B TEE | tee/qwen3.6-27b | $0.416 / $4.225 | 262K |
| Qwen3.6 35B A3B TEE | tee/qwen3.6-35b-a3b | $0.26 / $1.651 | 262K |
| Gemma 4 31B TEE | tee/gemma-4-31b-it | $0.195 / $0.598 | 262K |
| GPT-OSS 120B TEE | tee/gpt-oss-120b | $0.195 / $0.78 | 131K |
| Llama 3.3 70B TEE | tee/llama-3.3-70b | $2.60 / $2.60 | 131K |
| Qwen3.8 27B Uncensored TEE | tee/qwen3.8-27b-uncensored (:thinking for reasoning) | $0.39 / $1.95 | 262K |
| Gemma 4 26B A4B Uncensored TEE | tee/gemma-4-26b-a4b-uncensored | $0.195 / $0.91 | 262K |
All of them stream, work in Encrypted mode and run with zero data retention. All except GPT-OSS 120B take tools (function calling) in ordinary requests; Encrypted mode turns tools off. Prices change with the market: the live list is at obscurify.ai/v1/models, where each TEE model has "e2ee": true.
Claude, GPT, Gemini and Grok aren’t on the list. They run on their makers’ own servers, so there is no enclave to encrypt to.
What a TEE protects, and what it doesn’t
Without Encrypted mode, your request travels like this:
- From your device to Obscurify, encrypted (HTTPS, or Tor if you use our onion address). Obscurify doesn’t log it. To save you from re-sending a long chat with every message, the conversation is held in memory for up to an hour, then permanently deleted.
- From Obscurify to the enclave, encrypted.
- Inside the enclave, the model reads your prompt and writes the answer in encrypted memory. The server’s operator, its cloud host and anyone with access to the machine can’t see either.
The TEE closes the gap at the GPU server, where your text would otherwise sit in the clear. Obscurify’s own server still decrypts your text at step 1, and there you rely on our policy of not logging it.
Encrypted mode closes that gap too. Your device encrypts the conversation to a key that only the enclave holds, so Obscurify’s server only ever handles ciphertext.
For most people the useful combination is: no identity (an account is just a random number), payment in crypto or blind vouchers, and a model whose host can’t read what you send.
Encrypted mode
Every TEE model answers through the attested gateway run by RedPill and Phala, which sits inside its own Intel TDX enclave. With Encrypted mode on, a message goes like this:
- Before sending, your device picks a random nonce and fetches the gateway’s attestation report with it. It checks that the report is a genuine Intel TDX quote, that the gateway’s measured code is an approved release, and that the report binds the gateway’s keys to your nonce. If any of that fails, the app refuses to send.
- Your device takes the gateway’s encryption key from the report and makes a fresh key pair of its own. With them it encrypts every message in the conversation: yours, the system prompt and the earlier answers.
- Obscurify’s server passes the ciphertext to the gateway. The text is decrypted only inside the gateway’s enclave, which forwards it over an attested channel to the GPU enclave on the machine that runs the model.
- The answer comes back encrypted to your device’s key, chunk by chunk, and your device decrypts it.
- When the reply is done, your device checks the gateway’s signed receipt (the checks are below), including that the enclave received exactly the conversation you sent.
What Encrypted mode doesn’t hide
Obscurify still sees which model you use, when you chat and how long each message and answer is. It also sees your account (an anonymous number) and your balance and token counts, which billing needs.
The receipt carries a hash of the conversation the enclave decrypted, and Obscurify can see that hash. For a very short chat that someone could guess word for word, the guess could be confirmed against it. The whole conversation is hashed together, so this only matters for trivial chats.
What you give up
- No tools and no web search. The server can’t read the text, so it can’t run them.
- No images.
- The whole conversation is sent with each message. The server can’t hold or shorten a chat it can’t read, so long chats send more data each turn.
Background replies still work: if you leave the page, the reply keeps going and is waiting when you come back.
Turn it on in the web chat and the Android app
Sign in, then tap Encrypted in the quick controls (Temp, Local, Encrypted, Tor, Wipe). The model list then shows only TEE models. Each answer gets a small mark when its checks are done: Encrypted when every check passed, or Check failed with the check that didn’t. Tap it to see the checks and the receipt id. If the enclave’s attestation doesn’t verify before sending, nothing is sent and you see Not encrypted instead. Encrypted mode needs an account.
The checks
Your device runs these on every encrypted reply:
- The bytes you received hash to the value in the receipt.
- The receipt is signed by the gateway’s key.
- That key, and the random nonce your device picked a moment ago, are inside the hardware quote, so the quote is fresh and belongs to this gateway.
- The quote is from genuine Intel TDX hardware with up-to-date firmware (Intel’s certificate chain and revocation lists).
- The gateway’s measured code matches the configuration it publishes.
- That configuration is an approved release: the gateway’s contract on the Base blockchain allows it. If your device can’t reach Base, this one is shown as not checked.
- The gateway checked the attestation of the GPU machine that ran the model before sending it your prompt.
- The request hash in the receipt matches the conversation your device encrypted, so Obscurify couldn’t add, drop or change a message on the way.
Intel’s collateral for checking the quote is relayed at https://obscurify.ai/tee/pccs/. Intel signs it, so the relay can’t change it, and you can fetch it from any PCCS you like instead.
Encrypted mode through the API
The simplest way is our open-source verifier, github.com/Obscurify-ai/tee-verify. Its chat command checks the attestation, encrypts your prompt, sends it, decrypts the answer and checks the receipt:
cargo install --git https://github.com/Obscurify-ai/tee-verify --features cli
obscurify-tee-verify chat --api-key sk-obs1_AbCd... --model tee/glm-5.3 --prompt "Hello"
It is also a Rust library, and a WASM module, which is what the web chat runs.
To do it from your own code:
-
Pick 32 random bytes as a nonce and fetch the report with your API key:
curl -s -H 'Authorization: Bearer sk-obs1_AbCd...' \ 'https://obscurify.ai/v1/tee/attestation?model=tee/glm-5.3&nonce=<64 hex characters>' -
Verify the report (checks 3 to 6 above). Only then take the key from
attestation.workload_keyset.e2ee_public_keys[]: the entry whosealgoissecp256k1-aes-256-gcm-hkdf-sha256. It is an uncompressed public key in hex. -
Make a fresh secp256k1 key pair for the request. Derive the AES key from ECDH between your private key and the gateway’s key: HKDF-SHA256 over the 32-byte x-coordinate of the shared point, with an empty salt, info
ecdsa_encryptionand 32 bytes of output. -
Encrypt the
contentof every message (string contents only) with AES-256-GCM and a fresh 12-byte IV. Each encrypted string is the hex of your 65-byte uncompressed public key, then the IV, then the ciphertext with its tag. -
Send it to
/v1/chat/completionsas usual, with three extra headers:X-Client-Pub-Key(your public key in hex),X-Model-Pub-Key(the gateway’s key in hex) andX-Signing-Algo: ecdsa. When streaming, set"stream_options": {"include_usage": true}, because billing reads the plaintext token counts. Don’t sendtools,web_searchorthread. -
In the reply,
contentandreasoning_content(in each chunk, or in the message) are hex strings encrypted to your key. Each starts with a fresh 65-byte public key from the server: derive the AES key the same way, with ECDH between your private key and those 65 bytes, then decrypt the rest. Usage stays in plaintext. -
The reply has the header
X-Obscurify-TEE-Receipt. Fetch the receipt withGET https://obscurify.ai/v1/tee/receipts/{receipt id}?model=tee/glm-5.3(a 404 for the first few seconds means it isn’t ready yet), then run the checks against the same report and the plain request you encrypted.
The request reaches the enclave unchanged apart from the model id, so the server can’t add settings for you. On a model with a :thinking twin, send "reasoning_effort": "none" when you call the plain one.
The encryption itself takes a few lines of Python with the cryptography package:
import os
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
def aes_key(private_key, peer_public: bytes) -> bytes:
peer = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256K1(), peer_public)
shared_x = private_key.exchange(ec.ECDH(), peer)
return HKDF(hashes.SHA256(), 32, salt=None, info=b"ecdsa_encryption").derive(shared_x)
me = ec.generate_private_key(ec.SECP256K1())
my_public = me.public_key().public_bytes(
serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint)
def encrypt(gateway_public: bytes, text: str) -> str:
iv = os.urandom(12)
sealed = AESGCM(aes_key(me, gateway_public)).encrypt(iv, text.encode(), None)
return (my_public + iv + sealed).hex()
def decrypt(hex_text: str) -> str:
raw = bytes.fromhex(hex_text)
return AESGCM(aes_key(me, raw[:65])).decrypt(raw[65:77], raw[77:], None).decode()
Use a TEE model in the web chat
- Go to obscurify.ai and sign in, or create an account (no email: you get a 16-digit account number).
- Add credit on the account page.
- Open the Model dropdown and tap the TEE chip. Only TEE models are listed, each marked with a TEE label. All of them are also marked ZDR (zero data retention): the provider keeps nothing after it answers.
- Pick one and chat as usual, or turn on Encrypted first.
Use a TEE model through the API
The API is OpenAI-compatible: any OpenAI SDK or tool works with the base URL https://obscurify.ai/v1 and your Obscurify API key. Get the key on the account page, or from your account number as shown in the curl tutorial. Requests like these, without the encryption headers, still run inside the enclave, but they aren’t end-to-end encrypted: Obscurify’s server reads the text on its way through, as in the first list above. For end-to-end encryption, follow the Encrypted mode steps.
With curl:
curl https://obscurify.ai/v1/chat/completions \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer sk-obs1_AbCd...' \
-d '{"model": "tee/glm-5.3-flash",
"messages": [{"role": "user", "content": "Summarize this contract clause: ..."}]}'
With Python:
from openai import OpenAI
client = OpenAI(base_url="https://obscurify.ai/v1", api_key="sk-obs1_AbCd...")
reply = client.chat.completions.create(
model="tee/glm-5.3",
messages=[{"role": "user", "content": "Review this patient note for missing details: ..."}],
)
print(reply.choices[0].message.content)
To list the TEE models from code, read the categories of each model in the models list:
curl -s https://obscurify.ai/v1/models \
| jq -r '.data[] | select(.categories | index("TEE")) | .id'
Which one to pick
- GLM 5.3 TEE for the hardest work: long documents, coding, agents.
- GLM 5.3 Flash TEE for everyday chat and high volume at a low price.
- Kimi K3.1 Pro TEE when you want Moonshot’s large model. It costs less than Kimi K3.
- DeepSeek V4.1 Flash 1017 TEE for reasoning and code at a middle price.
- Qwen3.8 27B TEE for cheap input on large prompts, with a 1M context.
- Gemma 4 31B TEE for the lowest price on the list.
- Qwen3.8 27B Uncensored TEE and Gemma 4 26B A4B Uncensored TEE when you need fewer refusals as well as sealed hardware (Pro plan). Gemma is the cheaper of the two; Qwen writes longer, more careful answers.
If you work with sensitive material, such as client files, health records or source code under NDA, use Encrypted mode with one of these models and keep the conversation in it from start to finish: switching to a model outside the enclave mid-chat sends the earlier messages to that model too.