TL;DR
Learn how to implement robust data encryption strategies, including database encryption, file system encryption, and key management
import { MermaidDiagram } from '@/components/mermaid-diagram'
Learn how to implement robust data encryption strategies to protect sensitive information. This comprehensive guide covers encryption methods, key management, and best practices.
graph TB
subgraph "Key Management"
KMS["Key Management Service"]
Master["Master Key"]
Data["Data Key"]
end
subgraph "Encryption"
Plain["Plaintext"]
Encrypt["Encryption"]
Cipher["Ciphertext"]
end
subgraph "Storage"
DB["Database"]
File["File System"]
Cloud["Cloud Storage"]
end
KMS --> Master
Master --> Data
Data --> Encrypt
Plain --> Encrypt
Encrypt --> Cipher
Cipher --> DB
Cipher --> File
Cipher --> Cloud
style KMS fill:#3b82f6,stroke:#2563eb,color:white
style Master fill:#3b82f6,stroke:#2563eb,color:white
style Data fill:#3b82f6,stroke:#2563eb,color:white
style Plain fill:#f1f5f9,stroke:#64748b
style Encrypt fill:#f1f5f9,stroke:#64748b
style Cipher fill:#f1f5f9,stroke:#64748b
style DB fill:#f1f5f9,stroke:#64748b
style File fill:#f1f5f9,stroke:#64748b
style Cloud fill:#f1f5f9,stroke:#64748b
/>
}
$1
Encryption methods include:
1. Symmetric: Same key for encryption/decryption
2. Asymmetric: Public/private key pairs
3. Hybrid: Combines both approaches
4. End-to-End: Data encrypted throughout transit
$1
$1
Implement secure database encryption:
`` // database-encryption.ts
import { createCipheriv, createDecipheriv, randomBytes, scrypt } from 'crypto';
import { promisify } from 'util'; interface EncryptionConfig {
algorithm: string;
keyLength: number;
ivLength: number;
} class DatabaseEncryption {
private readonly config: EncryptionConfig;
private readonly salt: Buffer;
private key: Buffer | null = null; constructor(config: EncryptionConfig = {
algorithm: 'aes-256-gcm',
keyLength: 32,
ivLength: 16
}) {
this.config = config;
this.salt = randomBytes(32);
} async initialize(password: string): Promise try {
const scryptAsync = promisify(scrypt);
this.key = await scryptAsync(password, this.salt, this.config.keyLength) as Buffer;
} catch (error) {
throw new Error( }
} async encrypt(data: string): Promise<{
iv: string;
encryptedData: string;
authTag: string;
}> {
if (!this.key) {
throw new Error('Encryption not initialized');
} try {
const iv = randomBytes(this.config.ivLength);
const cipher = createCipheriv(
this.config.algorithm,
this.key,
iv,
{ authTagLength: 16 }
); let encryptedData = cipher.update(data, 'utf8', 'hex');
encryptedData += cipher.final('hex');
const authTag = cipher.getAuthTag(); return {
iv: iv.toString('hex'),
encryptedData,
authTag: authTag.toString('hex')
};
} catch (error) {
throw new Error( }
} async decrypt(encryptedData: string, iv: string, authTag: string): Promise if (!this.key) {
throw new Error('Encryption not initialized');
} try {
const decipher = createDecipheriv(
this.config.algorithm,
this.key,
Buffer.from(iv, 'hex'),
{ authTagLength: 16 }
); decipher.setAuthTag(Buffer.from(authTag, 'hex')); let decryptedData = decipher.update(encryptedData, 'hex', 'utf8');
decryptedData += decipher.final('utf8'); return decryptedData;
} catch (error) {
throw new Error( }
} async encryptField document: T,
fields: string[]
): Promise const encryptedDoc = { ...document }; for (const field of fields) {
if (field in document && typeof document[field] === 'string') {
const encrypted = await this.encrypt(document[field]);
encryptedDoc[field] = JSON.stringify(encrypted);
}
} return encryptedDoc;
} async decryptField document: T,
fields: string[]
): Promise const decryptedDoc = { ...document }; for (const field of fields) {
if (field in document && typeof document[field] === 'string') {
const { iv, encryptedData, authTag } = JSON.parse(document[field]);
decryptedDoc[field] = await this.decrypt(encryptedData, iv, authTag);
}
} return decryptedDoc;
}
} // Example usage
async function main() {
const encryption = new DatabaseEncryption();
await encryption.initialize('secure-password'); // Encrypt document fields
const document = {
id: '123',
name: 'John Doe',
ssn: '123-45-6789',
email: 'john@example.com'
}; const sensitiveFields = ['ssn', 'email'];
const encryptedDoc = await encryption.encryptField(document, sensitiveFields);
console.log('Encrypted document:', encryptedDoc); // Decrypt document fields
const decryptedDoc = await encryption.decryptField(encryptedDoc, sensitiveFields);
console.log('Decrypted document:', decryptedDoc);
} main().catch(console.error);
typescript
Error initializing encryption: ${error.message});
Encryption error: ${error.message});
Decryption error: ${error.message});
`
$1
Implement secure file system encryption:
` // file-encryption.ts
import { createReadStream, createWriteStream } from 'fs';
import { pipeline } from 'stream/promises';
import { createCipheriv, createDecipheriv, randomBytes, scrypt } from 'crypto';
import { promisify } from 'util'; interface FileEncryptionConfig {
algorithm: string;
keyLength: number;
ivLength: number;
chunkSize: number;
} class FileEncryption {
private readonly config: FileEncryptionConfig;
private readonly salt: Buffer;
private key: Buffer | null = null; constructor(config: FileEncryptionConfig = {
algorithm: 'aes-256-gcm',
keyLength: 32,
ivLength: 16,
chunkSize: 64 * 1024 // 64KB chunks
}) {
this.config = config;
this.salt = randomBytes(32);
} async initialize(password: string): Promise try {
const scryptAsync = promisify(scrypt);
this.key = await scryptAsync(password, this.salt, this.config.keyLength) as Buffer;
} catch (error) {
throw new Error( }
} async encryptFile(
inputPath: string,
outputPath: string,
metadata: Record ): Promise if (!this.key) {
throw new Error('Encryption not initialized');
} try {
const iv = randomBytes(this.config.ivLength);
const cipher = createCipheriv(
this.config.algorithm,
this.key,
iv,
{ authTagLength: 16 }
); // Write IV and metadata at the beginning of the file
const header = {
iv: iv.toString('hex'),
metadata
}; const output = createWriteStream(outputPath);
output.write(JSON.stringify(header) + '\n'); const input = createReadStream(inputPath, {
highWaterMark: this.config.chunkSize
}); await pipeline(input, cipher, output); // Get and write auth tag at the end
const authTag = cipher.getAuthTag();
output.write(authTag);
} catch (error) {
throw new Error( }
} async decryptFile(
inputPath: string,
outputPath: string
): Promise if (!this.key) {
throw new Error('Encryption not initialized');
} try {
const input = createReadStream(inputPath, {
highWaterMark: this.config.chunkSize
}); // Read header
let headerStr = '';
for await (const chunk of input) {
headerStr += chunk;
if (headerStr.includes('\n')) {
break;
}
} const header = JSON.parse(headerStr.split('\n')[0]);
const { iv, metadata } = header; const decipher = createDecipheriv(
this.config.algorithm,
this.key,
Buffer.from(iv, 'hex'),
{ authTagLength: 16 }
); const output = createWriteStream(outputPath); await pipeline(input, decipher, output); return metadata;
} catch (error) {
throw new Error( }
} async encryptDirectory(
inputDir: string,
outputDir: string,
options: {
include?: string[];
exclude?: string[];
metadata?: Record } = {}
): Promise // Implementation for directory encryption
} async decryptDirectory(
inputDir: string,
outputDir: string,
options: {
include?: string[];
exclude?: string[];
} = {}
): Promise // Implementation for directory decryption
return [];
}
} // Example usage
async function main() {
const encryption = new FileEncryption();
await encryption.initialize('secure-password'); // Encrypt file
await encryption.encryptFile(
'sensitive.txt',
'encrypted.bin',
{ created: new Date().toISOString() }
); // Decrypt file
const metadata = await encryption.decryptFile(
'encrypted.bin',
'decrypted.txt'
);
console.log('File metadata:', metadata);
} main().catch(console.error);
typescript
Error initializing encryption: ${error.message});
File encryption error: ${error.message});
File decryption error: ${error.message});
`
$1
Implement secure transport:
` // secure-transport.ts
import { createServer, Server, TLSSocket } from 'tls';
import { readFileSync } from 'fs';
import { promisify } from 'util'; interface TLSConfig {
cert: string;
key: string;
ca?: string[];
requestCert?: boolean;
rejectUnauthorized?: boolean;
} class SecureTransport {
private server: Server | null = null;
private readonly config: TLSConfig; constructor(config: TLSConfig) {
this.config = {
...config,
requestCert: config.requestCert ?? true,
rejectUnauthorized: config.rejectUnauthorized ?? true
};
} createSecureServer(
handler: (socket: TLSSocket) => void,
port: number = 8443
): Promise return new Promise((resolve, reject) => {
try {
const options = {
cert: readFileSync(this.config.cert),
key: readFileSync(this.config.key),
ca: this.config.ca?.map(ca => readFileSync(ca)),
requestCert: this.config.requestCert,
rejectUnauthorized: this.config.rejectUnauthorized
}; this.server = createServer(options, handler); this.server.on('error', (error) => {
console.error('Server error:', error);
reject(error);
}); this.server.listen(port, () => {
console.log( resolve();
});
} catch (error) {
reject(error);
}
});
} async closeServer(): Promise if (this.server) {
const closeAsync = promisify(this.server.close.bind(this.server));
await closeAsync();
this.server = null;
}
}
} // Example usage
async function main() {
const transport = new SecureTransport({
cert: '/path/to/cert.pem',
key: '/path/to/key.pem',
ca: ['/path/to/ca.pem']
}); await transport.createSecureServer((socket) => {
console.log('Client connected:', socket.authorized ? 'authorized' : 'unauthorized'); socket.on('data', (data) => {
console.log('Received:', data.toString());
socket.write('Echo: ' + data);
}); socket.on('error', (error) => {
console.error('Socket error:', error);
}); socket.on('end', () => {
console.log('Client disconnected');
});
});
} main().catch(console.error);
typescript
Secure server listening on port ${port});
`
$1
Implement secure key management:
` // key-management.ts
import { randomBytes, createHash, createCipheriv, createDecipheriv } from 'crypto';
import { promisify } from 'util';
import { readFile, writeFile } from 'fs/promises'; interface KeyConfig {
algorithm: string;
keyLength: number;
ivLength: number;
iterations: number;
} class KeyManager {
private readonly config: KeyConfig;
private masterKey: Buffer | null = null;
private keys: Map constructor(config: KeyConfig = {
algorithm: 'aes-256-gcm',
keyLength: 32,
ivLength: 16,
iterations: 100000
}) {
this.config = config;
} async initialize(password: string): Promise try {
const salt = randomBytes(32);
const scryptAsync = promisify(require('crypto').scrypt);
this.masterKey = await scryptAsync(
password,
salt,
this.config.keyLength,
{ N: this.config.iterations }
) as Buffer;
} catch (error) {
throw new Error( }
} async generateKey(keyId: string): Promise if (!this.masterKey) {
throw new Error('Key manager not initialized');
} try {
const key = randomBytes(this.config.keyLength);
const iv = randomBytes(this.config.ivLength); const cipher = createCipheriv(
this.config.algorithm,
this.masterKey,
iv,
{ authTagLength: 16 }
); let encryptedKey = cipher.update(key);
encryptedKey = Buffer.concat([encryptedKey, cipher.final()]);
const authTag = cipher.getAuthTag(); this.keys.set(keyId, key); // Store encrypted key
await this.storeKey(keyId, {
iv: iv.toString('hex'),
key: encryptedKey.toString('hex'),
authTag: authTag.toString('hex')
}); return key;
} catch (error) {
throw new Error( }
} async getKey(keyId: string): Promise const cachedKey = this.keys.get(keyId);
if (cachedKey) {
return cachedKey;
} if (!this.masterKey) {
throw new Error('Key manager not initialized');
} try {
const storedKey = await this.loadKey(keyId);
const decipher = createDecipheriv(
this.config.algorithm,
this.masterKey,
Buffer.from(storedKey.iv, 'hex'),
{ authTagLength: 16 }
); decipher.setAuthTag(Buffer.from(storedKey.authTag, 'hex')); let key = decipher.update(Buffer.from(storedKey.key, 'hex'));
key = Buffer.concat([key, decipher.final()]); this.keys.set(keyId, key);
return key;
} catch (error) {
throw new Error( }
} async rotateKey(keyId: string): Promise try {
const oldKey = await this.getKey(keyId);
const newKey = await this.generateKey(typescript
Error initializing key manager: ${error.message});
Error generating key: ${error.message});
Error retrieving key: ${error.message});
${keyId}_new);
// Re-encrypt data with new key
// Implementation depends on your specific use case
// Delete old key
this.keys.delete(keyId);
await this.deleteKey(keyId);
// Rename new key
this.keys.set(keyId, newKey);
this.keys.delete(${keyId}_new await this.renameKey( } catch (error) {
throw new Error( }
} private async storeKey(
keyId: string,
data: { iv: string; key: string; authTag: string }
): Promise await writeFile(
JSON.stringify(data),
{ encoding: 'utf8' }
);
} private async loadKey(
keyId: string
): Promise<{ iv: string; key: string; authTag: string }> {
const data = await readFile( return JSON.parse(data);
} private async deleteKey(keyId: string): Promise // Implementation for deleting key file
} private async renameKey(oldId: string, newId: string): Promise // Implementation for renaming key file
}
} // Example usage
async function main() {
const keyManager = new KeyManager();
await keyManager.initialize('master-password'); // Generate new key
const key1 = await keyManager.generateKey('key1');
console.log('Generated key:', key1.toString('hex')); // Retrieve key
const retrievedKey = await keyManager.getKey('key1');
console.log('Retrieved key:', retrievedKey.toString('hex')); // Rotate key
await keyManager.rotateKey('key1');
const rotatedKey = await keyManager.getKey('key1');
console.log('Rotated key:', rotatedKey.toString('hex'));
} main().catch(console.error);
);
${keyId}_new, keyId);
Error rotating key: ${error.message});
keys/${keyId}.json,
keys/${keyId}.json, { encoding: 'utf8' });
``
$1
1. Algorithm Selection
- Use strong algorithms
- Follow standards
- Regular updates
- Proper key lengths
2. Key Management
- Secure storage
- Regular rotation
- Access control
- Backup strategy
3. Implementation
- Input validation
- Error handling
- Logging
- Monitoring
4. Compliance
- Data regulations
- Industry standards
- Regular audits
- Documentation
$1
Effective encryption requires:
1. Strong algorithms
2. Secure key management
3. Proper implementation
4. Regular maintenance
5. Compliance monitoring
Remember to:
$1
1. [NIST Encryption Guidelines](https://csrc.nist.gov/publications/detail/sp/800-175b/rev-1/final)
2. [OWASP Cryptographic Storage](https://owasp.org/www-project-cheat-sheets/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html)
3. [AWS KMS Best Practices](https://docs.aws.amazon.com/kms/latest/developerguide/best-practices.html)
4. [Node.js Crypto Documentation](https://nodejs.org/api/crypto.html)
5. [Encryption Standards](https://www.iso.org/standard/39727.html)
Why This Matters
Understanding the business and technical context helps you make informed decisions rather than blindly following patterns.
Trade-offs to Consider
Every architectural decision involves trade-offs. Consider your specific requirements, team expertise, and scale when evaluating options.
When NOT to Use This
Knowing when a solution doesn't apply is as valuable as knowing when it does. Consider alternatives for your specific situation.
Decision Framework
Use this framework to evaluate whether this approach is right for your use case based on your specific constraints and requirements.