Skip to main content

Encryption Guide

Complete guide for using encryption features in Strata Storage.

Overview

Strata Storage provides built-in authenticated encryption using the Web Crypto API (globalThis.crypto.subtle) — the same code path on web, Capacitor webviews, and Node.js / SSR (Node 20+). Two algorithms are available:

  • AES-GCM (default) — authenticated encryption (AEAD).
  • AES-CBC — authenticated via Encrypt-then-MAC (HMAC-SHA256 over iv ‖ ciphertext, with a separate domain-separated key, verified before decrypt).

Quick Start

import { Strata } from 'strata-storage';

// Enable encryption globally
const storage = new Strata({
encryption: {
enabled: true,
password: 'your-secure-password'
}
});

// Or per operation
await storage.set('sensitive', data, {
encrypt: true,
encryptionPassword: 'specific-password'
});

Encryption Configuration

interface EncryptionConfig {
enabled?: boolean; // Enable encryption by default (storage-level)
password?: string; // Default password (storage-level)
algorithm?: 'AES-GCM' | 'AES-CBC'; // Encryption algorithm (default: 'AES-GCM')
keyLength?: 128 | 192 | 256; // AES key length in bits (default: 256)
keyDerivation?: 'PBKDF2'; // Key derivation function (only PBKDF2)
iterations?: number; // PBKDF2 iterations (default: 600000)
saltLength?: number; // Salt length in bytes (default: 16)
}

PBKDF2 iterations default to 600,000 (OWASP guidance for PBKDF2-HMAC-SHA256). The per-record iteration count is stored with each ciphertext and used on decrypt, so raising the default never breaks older data.

Usage Examples

Basic Encryption

// Encrypt specific data
await storage.set('api_key', secretKey, {
encrypt: true
});

// Retrieve and auto-decrypt
const key = await storage.get('api_key');

Custom Password

// Use different passwords for different data
await storage.set('user_data', userData, {
encrypt: true,
encryptionPassword: userPassword
});

await storage.set('admin_data', adminData, {
encrypt: true,
encryptionPassword: adminPassword
});

Handling Decryption

// Skip decryption
const encrypted = await storage.get('secret', {
skipDecryption: true
});
console.log(encrypted); // Raw encrypted data

// Ignore decryption errors
const data = await storage.get('secret', {
ignoreDecryptionErrors: true
});
// Returns null if decryption fails

Security Best Practices

1. Password Management

class SecurePasswordManager {
// Generate strong passwords
generatePassword(): string {
return storage.generatePassword(32);
}

// Derive from user input
async derivePassword(userInput: string, salt: string) {
const hash = await storage.hash(userInput + salt);
return hash;
}
}

2. Key Rotation

class KeyRotation {
async rotateEncryptionKey(oldPassword: string, newPassword: string) {
// Get all encrypted items
const keys = await storage.keys();

for (const key of keys) {
// Decrypt with old password
const value = await storage.get(key, {
encryptionPassword: oldPassword
});

if (value !== null) {
// Re-encrypt with new password
await storage.set(key, value, {
encrypt: true,
encryptionPassword: newPassword
});
}
}
}
}

3. Secure Storage Combination

// Combine encryption with secure storage on mobile
await storage.set('highly_sensitive', data, {
storage: 'secure', // Use Keychain/Keystore
encrypt: true // Additional encryption layer
});

Platform Considerations

Web Platform

  • Uses Web Crypto API
  • Requires HTTPS in production
  • SubtleCrypto not available in insecure contexts

iOS Platform

  • Can combine with Keychain for key storage
  • Hardware encryption available
  • Biometric protection possible

Android Platform

  • Android Keystore integration
  • Hardware-backed keys on supported devices
  • Fingerprint/PIN protection

Error Handling

import { EncryptionError } from 'strata-storage';

try {
await storage.get('encrypted_data');
} catch (error) {
if (error instanceof EncryptionError) {
console.error('Decryption failed:', error.message);
// Handle wrong password, corrupted data, etc.
}
}

Performance Impact

  • Encryption adds ~5-10ms for small data
  • Scales linearly with data size
  • Consider compression before encryption
  • Use selective encryption for optimal performance

Advanced Usage

Custom Encryption

// Implement custom encryption adapter
class CustomEncryption {
async encrypt(data: string, password: string): Promise<EncryptedData> {
// Custom implementation
}

async decrypt(encrypted: EncryptedData, password: string): Promise<string> {
// Custom implementation
}
}

Encrypted Queries

// Query encrypted data (requires decryption)
const results = await storage.query({
'value.type': 'user'
}, {
encryptionPassword: password
});

See Also