Encryption

All secrets are encrypted client-side before transmission. The server never sees plaintext values. This page explains the cryptographic primitives and key derivation process used by the Secrets system.

Encryption Flow

1
  • User enters their vault password
  • 2
  • Password is processed through PBKDF2 with 100,000 iterations to derive a 256-bit key
  • 3
  • A random 12-byte IV is generated for each encryption operation
  • 4
  • Secret value is encrypted with AES-256-GCM using the derived key and IV
  • 5
  • The encrypted blob (IV + ciphertext + auth tag) is sent to the server
  • Cryptographic Primitives

    ComponentAlgorithmParameters
    Key DerivationPBKDF2-SHA256100,000 iterations, 32-byte output
    EncryptionAES-256-GCM12-byte IV, 128-bit auth tag
    Password HashingSHA-256Used for vault password verification

    Implementation

    The encryption is implemented using the Web Crypto API, which delegates to the browser's native cryptographic library. No JavaScript crypto libraries are used.

    Key derivation
    typescript
    async function deriveKey(password: string, salt: Uint8Array): Promise<CryptoKey> {
    const keyMaterial = await crypto.subtle.importKey(
    "raw",
    new TextEncoder().encode(password),
    "PBKDF2",
    false,
    ["deriveKey"]
    );
    return crypto.subtle.deriveKey(
    { name: "PBKDF2", salt, iterations: 100000, hash: "SHA-256" },
    keyMaterial,
    { name: "AES-GCM", length: 256 },
    false,
    ["encrypt", "decrypt"]
    );
    }
    iNote
    The salt is stored alongside the encrypted blob. Each vault uses a consistent salt derived from the vault ID, so the same password always produces the same key for a given vault.
    PreviousTeam SharingNextMCP Integration