Encryption

How does Areev encrypt data at rest?

Areev encrypts every grain blob with AES-256-GCM using a random 96-bit nonce before writing it to durable storage. This context database encrypts AI memory at the grain level. Each memory has a single 256-bit Data Encryption Key (DEK), wrapped by the platform’s managed key service through envelope encryption; the wrapped DEK is stored once per memory while the wrapping key never lives on application disk. Beneath the database, transparent at-rest encryption protects the underlying storage as a second layer.

The encryption module generates a fresh nonce from the OS CSPRNG (Aes256Gcm::generate_nonce(&mut OsRng)) for every encrypt call. The GCM authentication tag provides tamper detection — flipping a single byte in the ciphertext or tag causes decryption to fail. Each encrypted grain carries 28 bytes of overhead (12-byte nonce + 16-byte authentication tag), stored in the envelope format [nonce:12B][ciphertext][GCM-tag:16B].

All key material uses the DerivedKey type which implements zeroize::Zeroize on drop, clearing secrets from memory when no longer needed. Intermediate HKDF output buffers use Zeroizing<[u8; 32]> to prevent key material leaks on error paths.

import requests

# Store an encrypted grain via HTTP
resp = requests.post("https://acme.areev.ai/api/memories/default/add", json={
    "subject": "john",
    "relation": "likes",
    "object": "coffee",
    "content": "John mentioned he likes coffee"
})
# Grain is AES-256-GCM encrypted before hitting disk
POST /api/memories/default/add HTTP/1.1
Host: acme.areev.ai
Content-Type: application/json

{"subject":"john","relation":"likes","object":"coffee"}

Encryption is always on in Areev cloud. The platform’s managed key service provisions and rotates the wrapping keys on your behalf — there is no key configuration step in the Console.

How does Areev manage encryption keys?

Areev uses a layered key model. An authorization layer and row-level access control gate which principals can reach a given memory at all. Underneath, each memory has exactly one 256-bit Data Encryption Key, wrapped (encrypted) by the platform’s managed key service using envelope encryption. A single wrapped-DEK record is stored per memory; the wrapping key stays inside the managed key service and is never written to application disk.

Per-user keys are not stored at rest. At runtime the engine derives them in-process via HKDF-SHA256 from the memory DEK plus a user identifier, then zeroizes them when the operation completes. This autonomous memory system isolates every user’s AI memory data under a distinct cryptographic boundary without persisting a separate key per user. Blind index keys for subject, relation, and object fields are likewise derived via HKDF-SHA256, and a settings encryption key is derived via HKDF("areev-settings-key:llm"). This AI agent memory architecture means a compromise affecting one user’s derived key does not expose any other user.

Managed key service (holds wrapping key, never on app disk)
  |
  +-- wraps the per-memory DEK (one wrapped-DEK record per memory, AES-256-GCM)
        |
        +-- HKDF(memory DEK + user id)            --> per-user key (in-process, never stored)
        +-- HKDF("areev-blind-index:subject")     --> subject blind key
        +-- HKDF("areev-blind-index:relation")    --> relation blind key
        +-- HKDF("areev-blind-index:object")      --> object blind key
        +-- HKDF("areev-settings-key:llm")        --> settings encryption key

How does encrypted search work?

Areev uses HMAC-SHA256 blind index tokens to enable equality searches on encrypted fields without decrypting the data. Each searchable field (subject, relation, object) gets a dedicated key derived from the memory DEK, so this context database supports full SPO queries over ciphertext.

Blind tokens are case-insensitive and whitespace-insensitive by design. The system normalizes input (lowercase, trim, Unicode NFC), computes HMAC-SHA256(field_key, value), and truncates to 128 bits (16 bytes), yielding a deterministic 32-character hex token. The same value always produces the same token with the same key, enabling exact-match lookups in the graph index. Different field keys produce different tokens for the same value, preventing cross-field correlation attacks.

# Searching encrypted grains — the API handles blind indexing transparently
resp = requests.post("https://acme.areev.ai/api/memories/default/recall", json={
    "subject": "john",        # Converted to blind token server-side
    "relation": "likes"
})