Esegui inferenza privata su Venice con modelli Trusted Execution Environment (TEE) e crittografia end-to-end che rendono i prompt illeggibili all’host.
Venice offre modelli con privacy migliorata che vengono eseguiti in Trusted Execution Environments (TEE) e supportano l’End-to-End Encryption (E2EE). Questi modelli forniscono garanzie crittografiche che i tuoi dati rimangano privati, anche da Venice.
Il modello viene eseguito in un’enclave protetta hardware. Venice non può accedere al calcolo. Puoi verificarlo con l’attestation.
E2EE
e2ee-*
End-to-end encryption completa. I tuoi prompt vengono cifrati lato client prima di essere inviati. Solo il TEE può decifrarli.
I modelli E2EE includono la protezione TEE più la cifratura lato client. I modelli TEE forniscono la sicurezza dell’enclave senza richiedere la cifratura lato client.
I modelli TEE vengono eseguiti all’interno di enclavi protette hardware (Intel TDX, NVIDIA Confidential Computing). I pesi del modello e i tuoi dati sono protetti dal sistema host, inclusa l’infrastruttura di Venice.
Se l’attestation ha superato la verifica lato server
nonce
Il tuo nonce, a conferma della freschezza
model
L’ID del modello attestato
tee_provider
Identificatore del provider TEE
intel_quote
Quote Intel TDX raw (base64) per la verifica lato client
nvidia_payload
Dati di attestation NVIDIA GPU (se applicabile)
signing_key
Chiave pubblica per verificare le firme delle risposte (tipicamente richiesta per i flussi E2EE; può essere omessa per alcuni modelli TEE semplici)
signing_address
Indirizzo Ethereum derivato dalla chiave di firma
Per l’uso in produzione, verifica l’attestation lato client effettuando il parsing del quote Intel TDX e controllando l’attestation NVIDIA.
Per la verifica di un modello TEE semplice, signing_address e i campi di verifica lato server sono sufficienti per i controlli di attestation di base. Una signing_key è richiesta quando hai bisogno del key agreement E2EE lato client e di controlli rigorosi di key-binding.
I modelli TEE possono firmare le loro risposte, dimostrando che l’output proviene dall’enclave attestata:
# Dopo aver ottenuto un completion, 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 che la firma corrisponda al signing_address dall'attestation
I modelli E2EE aggiungono la cifratura lato client sopra la protezione TEE. I tuoi prompt vengono cifrati prima di lasciare il tuo dispositivo, e solo il TEE può decifrarli.Venice E2EE usa:
ECDH (Elliptic Curve Diffie-Hellman) su secp256k1 per lo scambio di chiavi
HKDF-SHA256 per la derivazione delle chiavi
AES-256-GCM per la cifratura simmetrica
TEE attestation per verificare che il modello sia in esecuzione in un’enclave sicura
E2EE richiede un’implementazione lato client. Gli esempi seguenti mostrano il protocollo 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') ]# Esempio d'usomodels = get_e2ee_models('your-api-key')print('E2EE Models:', [m['id'] for m in models])
Usa queste funzioni helper per validare le chiavi e i contenuti cifrati prima di inviare le richieste.
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) { // Minimo: ephemeral_pub (65) + nonce (12) + tag (16) = 93 byte = 186 caratteri 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.""" # Minimum: ephemeral_pub (65) + nonce (12) + tag (16) = 93 bytes = 186 hex chars return len(s) >= 186 and all(c in '0123456789abcdefABCDEF' for c in s)
L’attestation dimostra che il modello è in esecuzione in un TEE genuino. Verifica sempre l’attestation prima di fidarti della chiave pubblica del modello.
Importante: lunghezza del nonce - Il nonce del client deve essere di 32 byte (64 caratteri hex). Alcuni provider TEE richiedono esattamente 32 byte e rifiuteranno nonce più corti.
import crypto from 'crypto'async function fetchAndVerifyAttestation(modelId, apiKey) { // Genera nonce client per la protezione contro replay (32 byte = 64 caratteri 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 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') } // Ottieni la chiave pubblica del modello per la cifratura 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.""" # Generate client nonce for replay protection (32 bytes = 64 hex chars) 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() # Verify attestation 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') # Get model's public key for encryption 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 i messaggi user e system prima di inviarli. Solo i messaggi con ruolo user e system devono essere cifrati.
Quando gli header E2EE sono presenti, tutti i messaggi con ruolo user e system devono essere cifrati. L’invio di qualsiasi contenuto in chiaro in questi ruoli produrrà un errore “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') // Normalizza la chiave pubblica (aggiungi il prefisso 04 se necessario) let normalizedKey = modelPublicKeyHex if (!normalizedKey.startsWith('04') && normalizedKey.length === 128) { normalizedKey = '04' + normalizedKey } const modelPublicKey = ec.keyFromPublic(normalizedKey, 'hex') // Genera una coppia di chiavi effimere per questo messaggio const ephemeralKeyPair = ec.genKeyPair() // Shared secret ECDH const sharedSecret = ephemeralKeyPair.derive(modelPublicKey.getPublic()) const sharedSecretBytes = new Uint8Array(sharedSecret.toArray('be', 32)) // Deriva la chiave AES usando HKDF const aesKey = hkdf(sha256, sharedSecretBytes, undefined, HKDF_INFO, 32) // Genera un nonce casuale const nonce = crypto.randomBytes(12) // Cifra con AES-GCM const cipher = gcm(aesKey, nonce) const encrypted = cipher.encrypt(new TextEncoder().encode(plaintext)) // Ottieni la chiave pubblica effimera (non compressa) const ephemeralPublic = new Uint8Array(ephemeralKeyPair.getPublic(false, 'array')) // Combina: ephemeral_public (65 byte) + nonce (12 byte) + 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.""" # Normalize public key 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) # Parse model's public key (skip 04 prefix) model_verifying_key = VerifyingKey.from_string( model_public_key_bytes[1:], curve=SECP256k1 ) # Generate ephemeral key pair for this message ephemeral_private = SigningKey.generate(curve=SECP256k1) ephemeral_public = ephemeral_private.get_verifying_key() # ECDH: compute shared secret shared_point = model_verifying_key.pubkey.point * ephemeral_private.privkey.secret_multiplier shared_secret = shared_point.x().to_bytes(32, 'big') # Derive AES key using HKDF hkdf = HKDF( algorithm=hashes.SHA256(), length=32, salt=None, info=HKDF_INFO, ) aes_key = hkdf.derive(shared_secret) # Generate random nonce nonce = os.urandom(12) # Encrypt with AES-GCM aesgcm = AESGCM(aes_key) ciphertext = aesgcm.encrypt(nonce, plaintext.encode('utf-8'), None) # Get ephemeral public key (uncompressed: 04 || x || y) ephemeral_public_bytes = b'\x04' + ephemeral_public.to_string() # Combine: 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
Non fidarti solo della risposta verified: true. Effettua il parsing del quote Intel TDX lato client e verifica che le misurazioni corrispondano ai valori attesi. Per le GPU NVIDIA, controlla l’attestation tramite il servizio di verifica NVIDIA.
Usa nonce freschi
Genera sempre un nuovo nonce casuale per ogni richiesta di attestation. Questo previene attacchi replay in cui un attaccante potrebbe servire un’attestation obsoleta.
Verifica il key binding
La chiave di firma dovrebbe essere legata al campo TDX REPORTDATA. Questo dimostra che la chiave è stata generata all’interno dell’enclave.
Controlla la modalità debug
Verifica che l’attestation TDX non abbia flag di debug impostati. Un’enclave in debug può essere ispezionata e non dovrebbe essere ritenuta affidabile per la produzione.
Usa i nostri SDK per E2EE
E2EE richiede un’implementazione crittografica attenta. Usa i nostri SDK ufficiali invece di implementare il protocollo da solo.
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')}")