@devinc3/secure-storage
v2.0.0
Published
A comprehensive client-side encryption solution with secure wrappers for localStorage, sessionStorage, and cookies
Downloads
318
Maintainers
Readme
Secure Storage
A comprehensive, production-ready client-side encryption solution with secure wrappers for localStorage, sessionStorage, and cookies. Built with modern cryptographic standards and best practices.
Features
- 🔒 Strong Encryption: AES-256-GCM encryption with PBKDF2 key derivation
- 🛡️ Tamper Resistant: Authenticated encryption prevents data tampering
- 🔑 Secure Key Derivation: PBKDF2 with 100,000+ iterations (OWASP recommended)
- 📦 Multiple Storage Backends: localStorage, sessionStorage, cookies, and in-memory storage
- 🎯 TypeScript Support: Full TypeScript definitions included
- ⚡ Performance Optimized: Efficient encryption/decryption operations
- 🧪 Production Ready: Comprehensive error handling and validation
- 📚 Well Documented: Extensive documentation and examples
Installation
npm install @devinc3/secure-storageQuick Start
Basic Usage
import { SecureLocalStorage } from "@devinc3/secure-storage";
// Initialize with a master key
const secureStorage = new SecureLocalStorage("your-secret-master-key");
// Store encrypted data
await secureStorage.setItem("user", {
name: "John Doe",
email: "[email protected]",
token: "sensitive-token",
});
// Retrieve and decrypt data
const user = await secureStorage.getItem("user");
console.log(user); // { name: 'John Doe', email: '[email protected]', token: 'sensitive-token' }API Reference
SecureLocalStorage
Persistent storage that survives page reloads and browser restarts.
import { SecureLocalStorage } from '@devinc3/secure-storage';
const storage = new SecureLocalStorage(masterKey: string, options?: SecureStorageOptions);
// Methods
await storage.setItem<T>(key: string, value: T): Promise<void>
await storage.getItem<T>(key: string): Promise<T | null>
storage.removeItem(key: string): void
storage.clear(): void
storage.getAllKeys(): string[]
storage.hasItem(key: string): boolean
storage.getLength(): numberSecureSessionStorage
Temporary storage that persists only for the current browser session.
import { SecureSessionStorage } from '@devinc3/secure-storage';
const storage = new SecureSessionStorage(masterKey: string, options?: SecureStorageOptions);
// Same API as SecureLocalStorageSecureCookies
Encrypted cookie storage for data that needs to be accessible server-side.
import { SecureCookies } from '@devinc3/secure-storage';
const cookies = new SecureCookies(
masterKey: string,
options?: SecureStorageOptions,
defaultCookieOptions?: CookieOptions
);
// Methods
await cookies.setItem<T>(key: string, value: T, cookieOptions?: CookieOptions): Promise<void>
await cookies.getItem<T>(key: string): Promise<T | null>
cookies.removeItem(key: string, cookieOptions?: CookieOptions): void
cookies.clear(): void
cookies.getAllKeys(): string[]
cookies.hasItem(key: string): boolean
cookies.getLength(): numberSecureMemoryStorage
In-memory storage that doesn't persist across page reloads.
import { SecureMemoryStorage } from '@devinc3/secure-storage';
const memory = new SecureMemoryStorage(masterKey: string, options?: SecureStorageOptions);
// Same API as SecureLocalStorageCore Encryption Functions
For advanced use cases, you can use the encryption functions directly:
import { encrypt, decrypt, validateMasterKey } from "@devinc3/secure-storage";
// Encrypt data
const encrypted = await encrypt("sensitive data", "master-key", {
iterations: 100000,
saltLength: 16,
ivLength: 12,
keyLength: 256,
});
// Decrypt data
const decrypted = await decrypt(encrypted, "master-key");
// Validate master key
const validation = validateMasterKey("my-key");
if (!validation.valid) {
console.error(validation.error);
}Configuration Options
SecureStorageOptions
interface SecureStorageOptions {
iterations?: number; // PBKDF2 iterations (default: 100000)
saltLength?: number; // Salt length in bytes (default: 16)
ivLength?: number; // IV length in bytes (default: 12)
keyLength?: number; // Key length in bits (default: 256)
}CookieOptions
interface CookieOptions {
expires?: number; // Expiration in days (default: 365)
path?: string; // Cookie path (default: '/')
domain?: string; // Cookie domain
secure?: boolean; // HTTPS only (default: true)
sameSite?: "Strict" | "Lax" | "None"; // SameSite attribute (default: 'Strict')
httpOnly?: boolean; // HttpOnly flag (default: true, note: cannot be set from JS)
}Examples
Example 1: User Session Management
import {
SecureLocalStorage,
SecureSessionStorage,
} from "@devinc3/secure-storage";
// Persistent user preferences
const persistentStorage = new SecureLocalStorage("app-secret-key");
await persistentStorage.setItem("theme", "dark");
await persistentStorage.setItem("language", "en");
// Temporary session data
const sessionStorage = new SecureSessionStorage("app-secret-key");
await sessionStorage.setItem("sessionToken", "abc123xyz");
await sessionStorage.setItem("lastActivity", Date.now());Example 2: Cookie-Based Authentication
import { SecureCookies } from "@devinc3/secure-storage";
const secureCookies = new SecureCookies(
"app-secret-key",
{},
{
expires: 7, // 7 days
secure: true, // HTTPS only
sameSite: "Strict",
}
);
// Store authentication token
await secureCookies.setItem("authToken", {
token: "jwt-token-here",
expiresAt: Date.now() + 7 * 24 * 60 * 60 * 1000,
});
// Retrieve token
const authData = await secureCookies.getItem("authToken");Example 3: Custom Encryption Options
import { SecureLocalStorage } from "@devinc3/secure-storage";
// Higher security (slower operations)
const highSecurityStorage = new SecureLocalStorage("master-key", {
iterations: 200000, // More iterations = more secure but slower
saltLength: 32, // Longer salt
keyLength: 256, // AES-256
});
// Balanced security and performance
const balancedStorage = new SecureLocalStorage("master-key", {
iterations: 100000, // OWASP recommended minimum
saltLength: 16,
keyLength: 256,
});Example 4: Error Handling
import {
SecureLocalStorage,
DecryptionError,
StorageError,
} from "@devinc3/secure-storage";
const storage = new SecureLocalStorage("master-key");
try {
await storage.setItem("data", { sensitive: "information" });
const data = await storage.getItem("data");
} catch (error) {
if (error instanceof DecryptionError) {
console.error("Decryption failed:", error.message);
// Data may have been tampered with or key is incorrect
} else if (error instanceof StorageError) {
console.error("Storage error:", error.message);
} else {
console.error("Unexpected error:", error);
}
}Example 5: Type-Safe Storage
import { SecureLocalStorage } from "@devinc3/secure-storage";
interface User {
id: string;
name: string;
email: string;
}
const storage = new SecureLocalStorage("master-key");
// TypeScript will infer the return type
const user = await storage.getItem<User>("user");
if (user) {
console.log(user.name); // TypeScript knows user has a 'name' property
}
// Type-safe storage
await storage.setItem<User>("user", {
id: "123",
name: "John",
email: "[email protected]",
});Security Considerations
Master Key Management
- Never hardcode master keys in your source code
- Use environment variables or secure key management services
- Generate strong, random master keys (minimum 16 characters recommended)
- Consider using a key derivation function to generate the master key from a user password
Best Practices
- Use HTTPS: Always use HTTPS in production to protect data in transit
- Key Rotation: Plan for key rotation if master keys are compromised
- Secure Storage: Store master keys securely (never in localStorage or cookies)
- Error Handling: Always handle encryption/decryption errors appropriately
- Validation: Validate master keys before use
Cryptographic Details
- Encryption Algorithm: AES-256-GCM (Galois/Counter Mode)
- Key Derivation: PBKDF2 with SHA-256
- Iterations: 100,000 (OWASP recommended minimum)
- Salt: 128-bit random salt per encryption
- IV: 96-bit random IV per encryption
- Authentication: Built-in authentication tag prevents tampering
Limitations
- Client-Side Only: This library is for client-side encryption only
- Master Key Security: The security of encrypted data depends on the master key being kept secret
- Browser Support: Requires Web Crypto API support (all modern browsers)
- Cookie HttpOnly: The
httpOnlyflag cannot be set from JavaScript (must be set server-side)
Browser Support
This library requires the Web Crypto API, which is supported in:
- Chrome 37+
- Firefox 34+
- Safari 11+
- Edge 12+
- Opera 24+
Performance
Encryption and decryption operations are asynchronous and typically complete in:
- Encryption: ~10-50ms (depending on iterations and data size)
- Decryption: ~10-50ms (depending on iterations and data size)
Performance can be tuned by adjusting the iterations option (lower = faster, but less secure).
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
Support
For issues, questions, or contributions, please visit the GitHub repository.
