Privacy-enhanced AI with Trusted Execution Environments and End-to-End Encryption
Venice offers privacy-enhanced models that run in Trusted Execution Environments (TEE) and support End-to-End Encryption (E2EE). These models provide cryptographic guarantees that your data remains private—even from Venice.
TEE models run inside hardware-secured enclaves (Intel TDX, NVIDIA Confidential Computing). The model weights and your data are protected from the host system—including Venice’s infrastructure.
You can cryptographically verify that a model is running in a genuine TEE by fetching its attestation report:
# Generate a random nonce (prevents replay attacks)NONCE=$(openssl rand -hex 16)# Fetch attestationcurl "https://api.venice.ai/api/v1/tee/attestation?model=tee-qwen3-5-122b-a10b&nonce=$NONCE" \ -H "Authorization: Bearer $API_KEY_VENICE"
The attestation response includes:
Field
Description
verified
Whether the attestation passed server-side verification
nonce
Your nonce, confirming freshness
model
The attested model ID
tee_provider
TEE provider identifier
intel_quote
Raw Intel TDX quote (base64) for client-side verification
nvidia_payload
NVIDIA GPU attestation data (if applicable)
signing_key
Public key for verifying response signatures (typically required for E2EE flows; may be omitted for some plain TEE models)
signing_address
Ethereum address derived from signing key
For production use, verify the attestation client-side by parsing the Intel TDX quote and checking the NVIDIA attestation.
For plain TEE model verification, signing_address and server-side verification fields are sufficient for baseline attestation checks. A signing_key is required when you need client-side E2EE key agreement and strict key-binding checks.
TEE models can sign their responses, proving the output came from the attested enclave:
# After getting a completion, verify the signaturecurl "https://api.venice.ai/api/v1/tee/signature?model=tee-qwen3-5-122b-a10b&request_id=chatcmpl-abc123" \ -H "Authorization: Bearer $API_KEY_VENICE"
E2EE models add client-side encryption on top of TEE protection. Your prompts are encrypted before leaving your device, and only the TEE can decrypt them.Venice E2EE uses:
ECDH (Elliptic Curve Diffie-Hellman) on secp256k1 for key exchange
HKDF-SHA256 for key derivation
AES-256-GCM for symmetric encryption
TEE attestation to verify the model runs in a secure enclave
E2EE requires client-side implementation. The examples below show the complete protocol.
The attestation proves the model is running in a genuine TEE. Always verify the attestation before trusting the model’s public key.
Important: Nonce Length - The client nonce must be 32 bytes (64 hex characters). Some TEE providers require exactly 32 bytes and will reject shorter nonces.
import crypto from 'crypto'async function fetchAndVerifyAttestation(modelId, apiKey) { // Generate client nonce for replay protection (32 bytes = 64 hex chars) const clientNonce = crypto.randomBytes(32).toString('hex') const response = await fetch( `https://api.venice.ai/api/v1/tee/attestation?model=${encodeURIComponent(modelId)}&nonce=${clientNonce}`, { headers: { Authorization: `Bearer ${apiKey}` } } ) const attestation = await response.json() // Verify attestation if (attestation.verified !== true) { throw new Error('TEE attestation verification failed on server') } if (attestation.nonce !== clientNonce) { throw new Error('Attestation nonce mismatch - possible replay attack') } // Get model's public key for encryption const modelPublicKey = attestation.signing_key || attestation.signing_public_key if (!modelPublicKey) { throw new Error('No signing key in attestation response') } return { modelPublicKey, signingAddress: attestation.signing_address, attestation, }}
Encrypt user and system messages before sending. Only user and system role messages need encryption.
When E2EE headers are present, alluser and system role messages must be encrypted. Sending any plaintext content in these roles will result in an “Encrypted field is not valid hex” error.
import { gcm } from '@noble/ciphers/aes.js'import { hkdf } from '@noble/hashes/hkdf.js'import { sha256 } from '@noble/hashes/sha2.js'import { ec as EC } from 'elliptic'import crypto from 'crypto'const HKDF_INFO = new TextEncoder().encode('ecdsa_encryption')function encryptMessage(plaintext, modelPublicKeyHex) { const ec = new EC('secp256k1') // Normalize public key (add 04 prefix if needed) let normalizedKey = modelPublicKeyHex if (!normalizedKey.startsWith('04') && normalizedKey.length === 128) { normalizedKey = '04' + normalizedKey } const modelPublicKey = ec.keyFromPublic(normalizedKey, 'hex') // Generate ephemeral key pair for this message const ephemeralKeyPair = ec.genKeyPair() // ECDH shared secret const sharedSecret = ephemeralKeyPair.derive(modelPublicKey.getPublic()) const sharedSecretBytes = new Uint8Array(sharedSecret.toArray('be', 32)) // Derive AES key using HKDF const aesKey = hkdf(sha256, sharedSecretBytes, undefined, HKDF_INFO, 32) // Generate random nonce const nonce = crypto.randomBytes(12) // Encrypt with AES-GCM const cipher = gcm(aesKey, nonce) const encrypted = cipher.encrypt(new TextEncoder().encode(plaintext)) // Get ephemeral public key (uncompressed) const ephemeralPublic = new Uint8Array(ephemeralKeyPair.getPublic(false, 'array')) // Combine: ephemeral_public (65 bytes) + nonce (12 bytes) + ciphertext const result = new Uint8Array(65 + 12 + encrypted.length) result.set(ephemeralPublic, 0) result.set(nonce, 65) result.set(encrypted, 65 + 12) return Buffer.from(result).toString('hex')}function encryptMessagesForE2EE(messages, modelPublicKey) { return messages.map(msg => { if (msg.role === 'user' || msg.role === 'system') { return { ...msg, content: encryptMessage(msg.content, modelPublicKey), } } return msg })}
Don’t just trust the verified: true response. Parse the Intel TDX quote client-side and verify the measurements match expected values. For NVIDIA GPUs, check the attestation via NVIDIA’s verification service.
Use fresh nonces
Always generate a new random nonce for each attestation request. This prevents replay attacks where an attacker could serve a stale attestation.
Verify key binding
The signing key should be bound to the TDX REPORTDATA field. This proves the key was generated inside the enclave.
Check for debug mode
Verify the TDX attestation doesn’t have debug flags set. A debug enclave can be inspected and should not be trusted for production.
Use our SDKs for E2EE
E2EE requires careful cryptographic implementation. Use our official SDKs rather than implementing the protocol yourself.