Technical Overview

Security Architecture

keyhold.io uses a zero-knowledge architecture. We've designed the system so that we mathematically cannot decrypt your secrets — not "we promise not to", but we literally can't.

Cryptographic Primitives

All client-side cryptography uses the Web Crypto API. We use industry-standard algorithms with conservative parameters.

Purpose Algorithm Parameters
Secret encryption AES-256-GCM 256-bit key, 96-bit IV
Key wrapping RSA-OAEP 2048-bit, SHA-256
Key derivation PBKDF2 SHA-256, 100,000 iterations
Server-side key protection AWS KMS Hardware-backed, AES-256-GCM

Split-Key Architecture

Every secret is encrypted with an ephemeral AES key that is immediately split into two shares. Neither share is useful on its own.

Client Share

Encrypted with RSA and stored in our database. Can only be decrypted by authorised users who hold the corresponding private key.

Server Share

Encrypted with AWS KMS and stored in our database. We can decrypt this share, but it's useless without the client share.

The key insight

The two shares are combined using XOR to reconstruct the original encryption key. Given only the server share, the original key is computationally indistinguishable from random noise. We hold one share; you hold the other. Neither works alone.

Key Hierarchy

User Keys

Each user has an RSA keypair generated during account setup. The public key is stored in plaintext. The private key is encrypted using a key derived from the user's password (via PBKDF2) and stored encrypted. We never see your password or your private key.

Client Keys

Each client (project) has its own RSA keypair. The private key is encrypted separately for each authorised team member using their public key. This allows access to be granted or revoked per-user without re-encrypting secrets.

Secret Keys

Each secret gets a fresh random AES-256 key. This key encrypts the secret data, then is immediately split and discarded. The encrypted secret and the two encrypted shares are stored; the original key never persists anywhere.

Encryption & Decryption

When a secret is submitted

All encryption happens in the submitter's browser before any data leaves their device. The browser generates a random key, encrypts the secret with AES-256-GCM, splits the key into two shares, encrypts each share separately, and only then transmits the encrypted components to our servers.

We receive ciphertext. We never see plaintext.

When a secret is revealed

The server verifies authorisation, decrypts the server share via KMS, and returns both encrypted shares plus the ciphertext. The user's browser decrypts the client share using their private key, XORs the two shares to recover the original AES key, and decrypts the secret locally.

Decryption happens entirely in your browser.

AWS KMS

The server share is protected by AWS Key Management Service, which provides hardware-backed key storage and comprehensive audit logging.

Encryption context — Each encrypted share is bound to a specific organisation. Attempting to decrypt with a mismatched context fails.

IAM policies — Strict permissions limit which services can perform encrypt/decrypt operations.

CloudTrail — Every KMS operation is logged for audit and compliance purposes.

Device Trust

Users can optionally "remember" a device for faster access. When enabled, a session key is derived from the user's password using PBKDF2 and stored encrypted in the browser's localStorage.

This allows the browser to unlock the user's private key without re-entering their password each time, but only on that specific device and only with the correct password. The session key never leaves the browser and is scoped to the individual user.

Security Properties

Zero-knowledge

We never see plaintext secrets. All encryption and decryption happens client-side. Our servers store only ciphertext and encrypted key shares.

Server compromise resistance

If our database is breached, attackers obtain encrypted blobs. Without users' private keys — which never leave their browsers — decryption is computationally infeasible.

Forward secrecy

Each secret uses a fresh ephemeral key. Compromising one secret's key material has no effect on any other secret.

Authenticated encryption

AES-256-GCM provides both confidentiality and integrity. Any tampering with ciphertext is detected during decryption.

Questions?

We're happy to discuss the details of our security architecture.

Get started free