Ejecuta inferencia privada en Venice con modelos TEE y cifrado de extremo a extremo que mantienen tus prompts ilegibles para el host.
Venice ofrece modelos con privacidad mejorada que se ejecutan en entornos de ejecución confiables (TEE) y admiten cifrado de extremo a extremo (E2EE). Estos modelos proporcionan garantías criptográficas de que tus datos permanecen privados, incluso frente a Venice.
El modelo se ejecuta en un enclave protegido por hardware. Venice no puede acceder al cómputo. Puedes verificarlo mediante atestación.
E2EE
e2ee-*
Cifrado completo de extremo a extremo. Tus prompts se cifran del lado del cliente antes de enviarse. Solo el TEE puede descifrarlos.
Los modelos E2EE incluyen protección TEE más cifrado del lado del cliente. Los modelos TEE proporcionan seguridad de enclave sin requerir cifrado del lado del cliente.
Los modelos TEE se ejecutan dentro de enclaves protegidos por hardware (Intel TDX, NVIDIA Confidential Computing). Los pesos del modelo y tus datos están protegidos frente al sistema anfitrión, incluida la infraestructura de Venice.
Si la atestación pasó la verificación del lado del servidor
nonce
Tu nonce, que confirma la frescura
model
El ID del modelo atestado
tee_provider
Identificador del proveedor del TEE
intel_quote
Cita Intel TDX en bruto (base64) para verificación del lado del cliente
nvidia_payload
Datos de atestación de GPU NVIDIA (si aplica)
signing_key
Clave pública para verificar las firmas de respuesta (normalmente requerida en flujos E2EE; puede omitirse en algunos modelos TEE simples)
signing_address
Dirección de Ethereum derivada de la clave de firma
En entornos de producción, verifica la atestación del lado del cliente parseando la cita Intel TDX y comprobando la atestación de NVIDIA.
Para la verificación de un modelo TEE simple, signing_address y los campos de verificación del lado del servidor son suficientes para las comprobaciones básicas de atestación. Se requiere un signing_key cuando necesitas el acuerdo de claves E2EE del lado del cliente y comprobaciones estrictas de vinculación de claves.
Los modelos TEE pueden firmar sus respuestas, demostrando que la salida provino del enclave atestado:
# Tras obtener una completación, verifica la firmacurl "https://api.venice.ai/api/v1/tee/signature?model=tee-qwen3-5-122b-a10b&request_id=chatcmpl-abc123" \ -H "Authorization: Bearer $API_KEY_VENICE"
response = requests.get( f"https://api.venice.ai/api/v1/tee/signature", params={"model": "tee-qwen3-5-122b-a10b", "request_id": completion_id}, headers={"Authorization": f"Bearer {api_key}"})signature = response.json()# Verifica que la firma coincida con el signing_address de la atestación
Los modelos E2EE añaden cifrado del lado del cliente sobre la protección TEE. Tus prompts se cifran antes de salir de tu dispositivo, y solo el TEE puede descifrarlos.E2EE de Venice utiliza:
ECDH (Elliptic Curve Diffie-Hellman) sobre secp256k1 para el intercambio de claves
HKDF-SHA256 para la derivación de claves
AES-256-GCM para el cifrado simétrico
Atestación TEE para verificar que el modelo se ejecuta en un enclave seguro
E2EE requiere implementación del lado del cliente. Los ejemplos a continuación muestran el protocolo completo.
import requestsdef get_e2ee_models(api_key: str) -> list: """Get list of models that support E2EE.""" response = requests.get( 'https://api.venice.ai/api/v1/models', headers={'Authorization': f'Bearer {api_key}'} ) models = response.json()['data'] return [ model for model in models if model.get('model_spec', {}).get('capabilities', {}).get('supportsE2EE') ]# Ejemplo de usomodels = get_e2ee_models('your-api-key')print('E2EE Models:', [m['id'] for m in models])
Usa estas funciones auxiliares para validar las claves y el contenido cifrado antes de enviar las solicitudes.
function validateClientPubkey(pubkeyHex) { if (pubkeyHex.length !== 130 || !pubkeyHex.startsWith('04')) { throw new Error(`Client pubkey must be 130 hex chars starting with '04' (got ${pubkeyHex.length})`) }}function isValidEncrypted(s) { // Mínimo: ephemeral_pub (65) + nonce (12) + tag (16) = 93 bytes = 186 caracteres hex return s.length >= 186 && /^[0-9a-fA-F]+$/.test(s)}
def validate_client_pubkey(pubkey_hex: str) -> None: """Validate client public key format.""" if len(pubkey_hex) != 130 or not pubkey_hex.startswith('04'): raise ValueError(f"Client pubkey must be 130 hex chars starting with '04' (got {len(pubkey_hex)})")def is_valid_encrypted(s: str) -> bool: """Check if string is valid hex-encrypted content.""" # Mínimo: ephemeral_pub (65) + nonce (12) + tag (16) = 93 bytes = 186 caracteres hex return len(s) >= 186 and all(c in '0123456789abcdefABCDEF' for c in s)
La atestación demuestra que el modelo se está ejecutando en un TEE genuino. Verifica siempre la atestación antes de confiar en la clave pública del modelo.
Importante: longitud del nonce — El nonce del cliente debe ser de 32 bytes (64 caracteres hexadecimales). Algunos proveedores de TEE requieren exactamente 32 bytes y rechazarán nonces más cortos.
import crypto from 'crypto'async function fetchAndVerifyAttestation(modelId, apiKey) { // Genera un nonce de cliente para protección contra repetición (32 bytes = 64 caracteres hex) 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() // Verifica la atestación 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') } // Obtén la clave pública del modelo para cifrar 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, }}
import secretsimport requestsdef fetch_and_verify_attestation(model_id: str, api_key: str) -> dict: """Fetch and verify TEE attestation for a model.""" # Genera un nonce de cliente para protección contra repetición (32 bytes = 64 caracteres hex) client_nonce = secrets.token_hex(32) response = requests.get( f'https://api.venice.ai/api/v1/tee/attestation', params={'model': model_id, 'nonce': client_nonce}, headers={'Authorization': f'Bearer {api_key}'} ) attestation = response.json() # Verifica la atestación if attestation.get('verified') != True: raise ValueError('TEE attestation verification failed on server') if attestation.get('nonce') != client_nonce: raise ValueError('Attestation nonce mismatch - possible replay attack') # Obtén la clave pública del modelo para cifrar model_public_key = attestation.get('signing_key') or attestation.get('signing_public_key') if not model_public_key: raise ValueError('No signing key in attestation response') return { 'model_public_key': model_public_key, 'signing_address': attestation.get('signing_address'), 'attestation': attestation }
Cifra los mensajes de usuario y de sistema antes de enviarlos. Solo los mensajes con rol user y system necesitan cifrarse.
Cuando hay cabeceras E2EE presentes, todos los mensajes con rol user y system deben estar cifrados. Enviar contenido en texto plano en estos roles dará lugar a un error “Encrypted field is not valid hex”.
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') // Normaliza la clave pública (añade el prefijo 04 si es necesario) let normalizedKey = modelPublicKeyHex if (!normalizedKey.startsWith('04') && normalizedKey.length === 128) { normalizedKey = '04' + normalizedKey } const modelPublicKey = ec.keyFromPublic(normalizedKey, 'hex') // Genera un par de claves efímeras para este mensaje const ephemeralKeyPair = ec.genKeyPair() // Secreto compartido ECDH const sharedSecret = ephemeralKeyPair.derive(modelPublicKey.getPublic()) const sharedSecretBytes = new Uint8Array(sharedSecret.toArray('be', 32)) // Deriva la clave AES usando HKDF const aesKey = hkdf(sha256, sharedSecretBytes, undefined, HKDF_INFO, 32) // Genera un nonce aleatorio const nonce = crypto.randomBytes(12) // Cifra con AES-GCM const cipher = gcm(aesKey, nonce) const encrypted = cipher.encrypt(new TextEncoder().encode(plaintext)) // Obtén la clave pública efímera (no comprimida) const ephemeralPublic = new Uint8Array(ephemeralKeyPair.getPublic(false, 'array')) // Combina: 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 })}
from cryptography.hazmat.primitives.ciphers.aead import AESGCMfrom cryptography.hazmat.primitives.kdf.hkdf import HKDFfrom cryptography.hazmat.primitives import hashesfrom ecdsa import SECP256k1, VerifyingKey, SigningKeyimport osHKDF_INFO = b'ecdsa_encryption'def encrypt_message(plaintext: str, model_public_key_hex: str) -> str: """Encrypt a message using ECDH + HKDF + AES-GCM.""" # Normaliza la clave pública key_hex = model_public_key_hex if not key_hex.startswith('04') and len(key_hex) == 128: key_hex = '04' + key_hex model_public_key_bytes = bytes.fromhex(key_hex) # Parsea la clave pública del modelo (omite el prefijo 04) model_verifying_key = VerifyingKey.from_string( model_public_key_bytes[1:], curve=SECP256k1 ) # Genera un par de claves efímeras para este mensaje ephemeral_private = SigningKey.generate(curve=SECP256k1) ephemeral_public = ephemeral_private.get_verifying_key() # ECDH: calcula el secreto compartido shared_point = model_verifying_key.pubkey.point * ephemeral_private.privkey.secret_multiplier shared_secret = shared_point.x().to_bytes(32, 'big') # Deriva la clave AES usando HKDF hkdf = HKDF( algorithm=hashes.SHA256(), length=32, salt=None, info=HKDF_INFO, ) aes_key = hkdf.derive(shared_secret) # Genera un nonce aleatorio nonce = os.urandom(12) # Cifra con AES-GCM aesgcm = AESGCM(aes_key) ciphertext = aesgcm.encrypt(nonce, plaintext.encode('utf-8'), None) # Obtén la clave pública efímera (no comprimida: 04 || x || y) ephemeral_public_bytes = b'\x04' + ephemeral_public.to_string() # Combina: ephemeral_public (65 bytes) + nonce (12 bytes) + ciphertext result = ephemeral_public_bytes + nonce + ciphertext return result.hex()def encrypt_messages_for_e2ee(messages: list, model_public_key: str) -> list: """Encrypt user and system messages.""" encrypted_messages = [] for msg in messages: if msg['role'] in ('user', 'system'): encrypted_messages.append({ **msg, 'content': encrypt_message(msg['content'], model_public_key) }) else: encrypted_messages.append(msg) return encrypted_messages
No te limites a confiar en la respuesta verified: true. Parsea la cita Intel TDX en el cliente y verifica que las mediciones coinciden con los valores esperados. Para GPU de NVIDIA, verifica la atestación mediante el servicio de verificación de NVIDIA.
Usa nonces nuevos
Genera siempre un nuevo nonce aleatorio para cada solicitud de atestación. Esto evita ataques de repetición en los que un atacante podría servir una atestación obsoleta.
Verifica la vinculación de la clave
La clave de firma debe estar vinculada al campo TDX REPORTDATA. Esto demuestra que la clave se generó dentro del enclave.
Comprueba el modo de depuración
Verifica que la atestación TDX no tenga marcas de depuración activadas. Un enclave de depuración puede inspeccionarse y no debe considerarse confiable para producción.
Usa nuestros SDK para E2EE
E2EE requiere una implementación criptográfica cuidadosa. Usa nuestros SDK oficiales en lugar de implementar el protocolo por tu cuenta.
models = client.models.list()for model in models.data: caps = getattr(model, 'model_spec', {}).get('capabilities', {}) if caps.get('supportsTeeAttestation') or caps.get('supportsE2EE'): print(f"{model.id}: TEE={caps.get('supportsTeeAttestation')}, E2EE={caps.get('supportsE2EE')}")