Encryption API Reference
API documentation for the encryption feature in Strata Storage.
Runtime support: Encryption uses the Web Crypto API (
crypto.subtle). It works in browsers and in modern Node.js / SSR runtimes — Node 20+ exposesglobalThis.crypto.subtle, so encryption works server-side without any polyfill.
Classes
EncryptionManager
Manages encryption/decryption operations using Web Crypto API.
class EncryptionManager {
constructor(config?: EncryptionConfig)
isAvailable(): boolean
encrypt(data: unknown, password: string): Promise<EncryptedData>
decrypt<T = unknown>(encrypted: EncryptedData, password: string): Promise<T>
generatePassword(length?: number): string
hash(data: string): Promise<string>
clearCache(): void
}
encryptaccepts any JSON-serializable value (itJSON.stringifys the input), anddecryptreturns the original deserialized value (Promise<T>), not a raw string. Key/salt/IV derivation is internal — there is no publicgenerateKey/generateSalt/generateIV.
Interfaces
EncryptionConfig
The options accepted by EncryptionManager (the algorithm/KDF parameters):
interface EncryptionConfig {
algorithm?: 'AES-GCM' | 'AES-CBC'; // default: 'AES-GCM'
keyLength?: 128 | 192 | 256; // AES key length in bits (default: 256)
iterations?: number; // PBKDF2 iterations (default: 600000)
saltLength?: number; // Salt length in bytes (default: 16)
keyDerivation?: 'PBKDF2'; // Only PBKDF2 is supported
}
enabledandpasswordare storage-level options — you set them on theStrataconstructor'sencryptionblock (see Usage with Strata), not insideEncryptionManager'sEncryptionConfig.
Algorithms:
AES-GCM(default) — authenticated encryption (AEAD); the GCM auth tag is appended to the ciphertext.AES-CBC— CBC mode is authenticated via Encrypt-then-MAC: a separate HMAC-SHA256 key is derived (domain-separated) from the same password and an HMAC tag overiv ‖ ciphertextis stored inmacand verified before decryption. This closes CBC's malleability / padding-oracle gap.
EncryptedData
interface EncryptedData {
data: string; // Base64 encoded ciphertext
salt: string; // Base64 encoded salt
iv: string; // Base64 encoded initialization vector
algorithm: string; // Algorithm used ('AES-GCM' | 'AES-CBC')
iterations: number; // PBKDF2 iterations actually used (used on decrypt)
mac?: string; // Base64 HMAC-SHA256 over (iv || ciphertext) — AES-CBC only
}
Breaking for legacy AES-CBC data: AES-CBC ciphertexts written before authentication was added have no
macand now fail closed with a clear "re-encrypt" error on read. Re-encrypt those values (read with an older build, write with this one) or switch them toAES-GCM.AES-GCMdata — the default — is unaffected.
Methods
encrypt
Encrypts any JSON-serializable value using the configured algorithm (AES-GCM by
default, or authenticated AES-CBC) with PBKDF2 key derivation. The value is
JSON.stringifyd internally; the salt and IV are generated per call.
async encrypt(data: unknown, password: string): Promise<EncryptedData>
Parameters:
data: The value to encrypt (any JSON-serializable value)password: The password for encryption
Returns: Promise resolving to the encrypted data structure
Example:
const encrypted = await encryptionManager.encrypt(
{ token: 'sensitive data' },
'strong-password'
);
decrypt
Decrypts data produced by encrypt, returning the original deserialized value.
async decrypt<T = unknown>(encrypted: EncryptedData, password: string): Promise<T>
Parameters:
encrypted: The encrypted data structurepassword: The password for decryption
Returns: Promise resolving to the original (JSON-deserialized) value
Throws: EncryptionError if the MAC/auth check fails or the password is wrong
Example:
try {
const decrypted = await encryptionManager.decrypt<{ token: string }>(
encrypted,
'strong-password'
);
} catch (error) {
console.error('Wrong password or corrupted/tampered data');
}
generatePassword
Generates a cryptographically-random password (unbiased rejection sampling).
generatePassword(length?: number): string
hash
Returns a hex SHA-256 hash of the input string.
async hash(data: string): Promise<string>
Usage with Strata
Global Encryption
const storage = new Strata({
encryption: {
enabled: true,
password: 'global-password',
algorithm: 'AES-GCM', // or 'AES-CBC' (authenticated via Encrypt-then-MAC)
iterations: 600000
}
});
// All operations are encrypted
await storage.set('key', 'value');
Per-Operation Encryption
await storage.set('key', 'value', {
encrypt: true,
encryptionPassword: 'specific-password'
});
Security Considerations
- Password Strength: Use strong, unique passwords
- Key Derivation: Higher iterations = more secure but slower
- Salt: Always use random salts (handled automatically)
- IV: Always use random IVs (handled automatically)
- HTTPS: Required for Web Crypto API in browsers
Platform Support
The encryption feature uses the Web Crypto API (globalThis.crypto.subtle)
on every platform — there is no native CryptoKit/Keystore code path here. (Native
Keychain/Keystore is the separate Secure adapter,
which is about where keys live, not this content-encryption feature.)
| Platform | Support | Implementation |
|---|---|---|
| Web (browser / Web Worker) | ✅ | crypto.subtle |
| Capacitor (iOS/Android webview) | ✅ | crypto.subtle |
| Node.js / SSR (Node 20+) | ✅ | globalThis.crypto.subtle |
Error Handling
import { EncryptionError } from 'strata-storage';
try {
await storage.get('encrypted-key');
} catch (error) {
if (error instanceof EncryptionError) {
// Handle encryption/decryption errors
console.error('Encryption error:', error.message);
}
}