Zero-knowledge password manager
Technical specifications of Passary's cryptography
This page provides detailed technical information about the cryptographic algorithms, parameters, and implementation details used in Passary. For a higher-level overview, see our Zero-Knowledge Architecture page.
| Component | Algorithm/Standard | Purpose |
|---|---|---|
| Key Derivation | Argon2id | Derive encryption key from master password |
| Symmetric Encryption | AES-256-GCM | Encrypt/decrypt vault data |
| Random Number Generation | Web Crypto API | Generate salts, IVs, and secure random values |
| Storage | IndexedDB | Store encrypted vault locally |
Argon2id is a memory-hard key derivation function (KDF) that won the Password Hashing Competition in 2015. It's designed to resist brute-force attacks even on specialized hardware.
memory64 MB (65536 KB)
Amount of memory required for computation. Higher values increase resistance to GPU/ASIC attacks.
iterations3
Number of iterations. Combined with memory parameter for tuned defense.
parallelism1
Degree of parallelism. Set to 1 for browser compatibility.
hash length32 bytes (256 bits)
Output length matching AES-256 key size.
salt16 bytes (128 bits)
Cryptographically random salt, unique per vault, stored alongside encrypted data.
We use the argon2-browser library, a WebAssembly implementation of Argon2 that runs efficiently in modern browsers:
import { hash } from 'argon2-browser';
const result = await hash({
pass: masterPassword,
salt: salt,
time: 3, // iterations
mem: 65536, // 64 MB
hashLen: 32, // 256 bits
parallelism: 1,
type: argon2.Type.Argon2id
});
const encryptionKey = result.hash;Advanced Encryption Standard (AES) with 256-bit keys in Galois/Counter Mode (GCM) is our symmetric encryption algorithm of choice.
AlgorithmAES-256-GCM
NIST FIPS 197 compliant, 256-bit key size
ModeGCM (Galois/Counter Mode)
Provides both confidentiality and authenticity (AEAD - Authenticated Encryption with Associated Data)
IV/Nonce12 bytes (96 bits)
Randomly generated for each encryption operation, stored with ciphertext
Tag Length16 bytes (128 bits)
Authentication tag to verify data integrity
We use the browser's native Web Crypto API for AES-GCM operations:
// Encryption
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{
name: 'AES-GCM',
iv: iv,
tagLength: 128
},
encryptionKey,
vaultData
);
// Decryption
const decrypted = await crypto.subtle.decrypt(
{
name: 'AES-GCM',
iv: iv,
tagLength: 128
},
encryptionKey,
ciphertext
);Your encrypted vault file contains the following components:
Random salt used for key derivation
Initialization vector for encryption
Your passwords and vault entries in encrypted form
GCM authentication tag for integrity verification
The Argon2 salt and AES IV are not secrets—they can be safely stored alongside the encrypted data. The salt ensures rainbow table attacks are ineffective, while the IV ensures semantic security (same plaintext encrypts to different ciphertext each time).
With AES-256, there are 2^256 possible keys (approximately 1.15 × 10^77). Even with all the world's computing power:
Grover's algorithm (quantum attack) reduces AES-256 security to effective 128-bit strength—still far beyond brute-force reach. Argon2id's memory-hard property also provides quantum resistance.
Web Crypto API implementations use constant-time operations to prevent timing attacks. Argon2id's design resists cache-timing and other side-channel attacks.
| Standard/Specification | Compliance |
|---|---|
| NIST FIPS 197 (AES) | ✓ Compliant |
| NIST SP 800-38D (GCM) | ✓ Compliant |
| RFC 9106 (Argon2) | ✓ Compliant |
| W3C Web Cryptography API | ✓ Used |
| OWASP Password Storage | ✓ Follows best practices |