What is Encryption?
Encryption is the process of transforming readable data (plaintext) into an unreadable format (ciphertext) using mathematical algorithms and encryption keys. Only parties with the correct decryption key can convert the ciphertext back to plaintext, ensuring data confidentiality during transmission over networks or storage on devices.
How Encryption Works
Basic Encryption Process
Plaintext → [Encryption Algorithm + Key] → Ciphertext → [Decryption Algorithm + Key] → Plaintext
Example:
// Conceptual example (use proper crypto libraries in production)
const plaintext = "Hello, World!";
const key = "secret-key-12345";
// Encryption
const ciphertext = encrypt(plaintext, key);
// Output: "3a7f9b2c8d1e4f6g..."
// Decryption
const decrypted = decrypt(ciphertext, key);
// Output: "Hello, World!"
Types of Encryption
Symmetric Encryption
Uses the same key for both encryption and decryption:
// AES (Advanced Encryption Standard) example
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
const algorithm = 'aes-256-cbc';
const key = randomBytes(32); // 256-bit key
const iv = randomBytes(16); // Initialization vector
// Encryption
function encrypt(text: string): string {
const cipher = createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// Decryption
function decrypt(encrypted: string): string {
const decipher = createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
const message = "Sensitive API key: sk_live_12345";
const encrypted = encrypt(message);
const decrypted = decrypt(encrypted);
Common Algorithms:
- AES (Advanced Encryption Standard) - Most widely used
- DES (Data Encryption Standard) - Deprecated, insecure
- 3DES (Triple DES) - Legacy systems
- ChaCha20 - Modern, fast alternative to AES
Advantages:
- Fast encryption/decryption
- Suitable for large data volumes
- Low computational overhead
Disadvantages:
- Key distribution challenge
- Same key must be shared securely
- Compromised key exposes all data
Asymmetric Encryption (Public-Key Cryptography)
Uses a key pair: public key for encryption, private key for decryption:
import { generateKeyPairSync, publicEncrypt, privateDecrypt } from 'crypto';
// Generate RSA key pair
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});
// Encrypt with public key
function encryptWithPublicKey(text: string): Buffer {
return publicEncrypt(publicKey, Buffer.from(text));
}
// Decrypt with private key
function decryptWithPrivateKey(encrypted: Buffer): string {
return privateDecrypt(privateKey, encrypted).toString();
}
const message = "Secret message";
const encrypted = encryptWithPublicKey(message);
const decrypted = decryptWithPrivateKey(encrypted);
Common Algorithms:
- RSA (Rivest-Shamir-Adleman) - Widely used for key exchange
- ECC (Elliptic Curve Cryptography) - Smaller keys, same security
- Diffie-Hellman - Key exchange protocol
- ElGamal - Alternative to RSA
Advantages:
- Secure key distribution
- Digital signatures
- No shared secret needed
Disadvantages:
- Slower than symmetric encryption
- Not suitable for large data
- More complex implementation
Encryption in Web Development
HTTPS and TLS Encryption
All communication through CorsProxy is encrypted using TLS:
// Your browser ←[TLS encrypted]→ CorsProxy ←[TLS encrypted]→ Destination
const response = await fetch(
'https://corsproxy.io/?url=https://api.example.com/data',
{
headers: {
'x-cors-api-key': process.env.CORS_API_KEY,
'Authorization': 'Bearer secret-token'
}
}
);
// The Authorization header is encrypted in transit
// No one can intercept and read your credentials
End-to-End Encryption
// Encrypt data before sending through proxy
import { createCipheriv, randomBytes, scryptSync } from 'crypto';
class EncryptedAPI {
private key: Buffer;
private algorithm = 'aes-256-gcm';
constructor(password: string) {
// Derive key from password
this.key = scryptSync(password, 'salt', 32);
}
async sendEncrypted(url: string, data: any) {
// Encrypt payload
const iv = randomBytes(16);
const cipher = createCipheriv(this.algorithm, this.key, iv);
let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
// Send encrypted data through proxy
const response = await fetch(`https://corsproxy.io/?url=${url}`, {
method: 'POST',
headers: {
'x-cors-api-key': process.env.CORS_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
encrypted,
iv: iv.toString('hex'),
authTag: authTag.toString('hex')
})
});
return response.json();
}
}
// Even if proxy is compromised, data remains encrypted
const api = new EncryptedAPI('user-secret-password');
await api.sendEncrypted('https://api.example.com/submit', {
creditCard: '1234-5678-9012-3456',
cvv: '123'
});
Client-Side Encryption
// Encrypt sensitive data before storing or transmitting
class SecureStorage {
private async generateKey(password: string): Promise<CryptoKey> {
const encoder = new TextEncoder();
const keyMaterial = await crypto.subtle.importKey(
'raw',
encoder.encode(password),
'PBKDF2',
false,
['deriveBits', 'deriveKey']
);
return crypto.subtle.deriveKey(
{
name: 'PBKDF2',
salt: encoder.encode('unique-salt'),
iterations: 100000,
hash: 'SHA-256'
},
keyMaterial,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
}
async encrypt(text: string, password: string): Promise<string> {
const key = await this.generateKey(password);
const encoder = new TextEncoder();
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
encoder.encode(text)
);
const combined = new Uint8Array(iv.length + encrypted.byteLength);
combined.set(iv);
combined.set(new Uint8Array(encrypted), iv.length);
return btoa(String.fromCharCode(...combined));
}
async decrypt(ciphertext: string, password: string): Promise<string> {
const key = await this.generateKey(password);
const combined = Uint8Array.from(atob(ciphertext), c => c.charCodeAt(0));
const iv = combined.slice(0, 12);
const data = combined.slice(12);
const decrypted = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv },
key,
data
);
return new TextDecoder().decode(decrypted);
}
}
// Usage
const storage = new SecureStorage();
const encrypted = await storage.encrypt('API_KEY=sk_live_12345', 'master-password');
localStorage.setItem('config', encrypted);
// Later
const decrypted = await storage.decrypt(localStorage.getItem('config')!, 'master-password');
Encryption Algorithms
AES (Advanced Encryption Standard)
The gold standard for symmetric encryption:
// AES-256-GCM (Galois/Counter Mode) - Recommended
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
function aesEncrypt(plaintext: string, key: Buffer): {
encrypted: string;
iv: string;
authTag: string;
} {
const iv = randomBytes(12); // 96-bit IV for GCM
const cipher = createCipheriv('aes-256-gcm', key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
return {
encrypted,
iv: iv.toString('hex'),
authTag: cipher.getAuthTag().toString('hex')
};
}
function aesDecrypt(
encrypted: string,
key: Buffer,
iv: string,
authTag: string
): string {
const decipher = createDecipheriv(
'aes-256-gcm',
key,
Buffer.from(iv, 'hex')
);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// Use case: Encrypting API responses
const key = randomBytes(32); // Store securely
const data = JSON.stringify({ apiKey: 'secret', token: 'bearer-xyz' });
const { encrypted, iv, authTag } = aesEncrypt(data, key);
const decrypted = aesDecrypt(encrypted, key, iv, authTag);
Key Sizes:
- AES-128: 128-bit key (16 bytes)
- AES-192: 192-bit key (24 bytes)
- AES-256: 256-bit key (32 bytes) - Most secure
RSA (Rivest-Shamir-Adleman)
Asymmetric encryption for key exchange and digital signatures:
import { generateKeyPairSync, publicEncrypt, privateDecrypt } from 'crypto';
// Generate 4096-bit RSA key pair (higher security)
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'strong-passphrase'
}
});
// Hybrid encryption: RSA for key, AES for data
function hybridEncrypt(data: string, recipientPublicKey: string) {
// Generate random AES key
const aesKey = randomBytes(32);
// Encrypt data with AES
const iv = randomBytes(16);
const cipher = createCipheriv('aes-256-cbc', aesKey, iv);
let encryptedData = cipher.update(data, 'utf8', 'hex');
encryptedData += cipher.final('hex');
// Encrypt AES key with RSA
const encryptedKey = publicEncrypt(
recipientPublicKey,
aesKey
).toString('base64');
return {
encryptedData,
encryptedKey,
iv: iv.toString('hex')
};
}
// Use case: Secure API key sharing
const apiKeyPackage = hybridEncrypt(
'sk_live_very_long_api_key_12345',
publicKey
);
Encryption Standards and Compliance
PCI DSS (Payment Card Industry)
Required for handling credit card data:
// PCI DSS requires encryption of cardholder data
class PCICompliantStorage {
private key: Buffer;
constructor(encryptionKey: string) {
// Use strong key derivation
this.key = scryptSync(encryptionKey, 'pci-salt', 32);
}
encryptCardData(cardNumber: string, cvv: string) {
// Encrypt before storage
const data = JSON.stringify({ cardNumber, cvv });
const iv = randomBytes(16);
const cipher = createCipheriv('aes-256-gcm', this.key, iv);
let encrypted = cipher.update(data, 'utf8', 'hex');
encrypted += cipher.final('hex');
return {
encrypted,
iv: iv.toString('hex'),
authTag: cipher.getAuthTag().toString('hex')
};
}
// Never log or expose plaintext card data
// Use tokenization when possible
}
GDPR (General Data Protection Regulation)
Encryption as privacy protection:
// GDPR Article 32: Security of processing
// Encryption of personal data
class GDPRCompliantAPI {
async storePersonalData(userData: {
email: string;
name: string;
address: string;
}) {
// Encrypt PII before storage
const key = process.env.ENCRYPTION_KEY!;
const encrypted = this.encryptPII(userData, key);
// Store encrypted data
await database.insert({
user_data_encrypted: encrypted,
encryption_algorithm: 'AES-256-GCM',
created_at: new Date()
});
}
private encryptPII(data: any, key: string): string {
const cipher = createCipheriv(
'aes-256-gcm',
Buffer.from(key, 'hex'),
randomBytes(12)
);
let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
}
HIPAA (Health Insurance Portability and Accountability Act)
Required for healthcare data:
- Encryption at rest: AES-256
- Encryption in transit: TLS 1.2+
- Key management: Regular rotation
- Access controls: Role-based encryption keys
Encryption Best Practices
1. Use Strong Algorithms
// Good: Modern, secure algorithms
const goodAlgorithms = [
'aes-256-gcm',
'chacha20-poly1305',
'aes-256-cbc' // with proper HMAC
];
// Bad: Deprecated, insecure algorithms
const badAlgorithms = [
'des', // Broken
'rc4', // Broken
'md5', // Collision attacks
'sha1' // Deprecated
];
2. Generate Secure Keys
import { randomBytes, scryptSync } from 'crypto';
// Good: Cryptographically secure random
const secureKey = randomBytes(32); // 256 bits
// Good: Key derivation from password
const derivedKey = scryptSync('user-password', 'unique-salt', 32);
// Bad: Weak key generation
const weakKey = Buffer.from('password123'); // Predictable
const anotherWeakKey = Buffer.from(Math.random().toString()); // Not crypto-secure
3. Proper Key Storage
// Environment variables (server-side only)
const encryptionKey = process.env.ENCRYPTION_KEY;
// Key management service
import { KMSClient, DecryptCommand } from '@aws-sdk/client-kms';
class KeyManager {
private kms: KMSClient;
constructor() {
this.kms = new KMSClient({ region: 'us-east-1' });
}
async getEncryptionKey(): Promise<Buffer> {
const command = new DecryptCommand({
CiphertextBlob: Buffer.from(process.env.ENCRYPTED_KEY!, 'base64')
});
const response = await this.kms.send(command);
return Buffer.from(response.Plaintext!);
}
}
// Never hardcode keys in source code
// const key = "hardcoded-secret-key"; // NEVER DO THIS
4. Use Authenticated Encryption
// GCM mode provides both encryption and authentication
function secureEncrypt(plaintext: string, key: Buffer) {
const iv = randomBytes(12);
const cipher = createCipheriv('aes-256-gcm', key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
// Auth tag prevents tampering
const authTag = cipher.getAuthTag();
return { encrypted, iv, authTag };
}
// Verify authenticity during decryption
function secureDecrypt(
encrypted: string,
key: Buffer,
iv: Buffer,
authTag: Buffer
) {
const decipher = createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8'); // Throws if tampered
return decrypted;
}
Encryption and CorsProxy
Secure Proxy Communication
// All traffic through CorsProxy is TLS encrypted
const response = await fetch(
'https://corsproxy.io/?url=https://api.example.com',
{
headers: {
'x-cors-api-key': process.env.CORS_API_KEY,
// These headers are encrypted in transit
'Authorization': 'Bearer token',
'X-API-Secret': 'secret-value'
}
}
);
// End-to-end encryption chain:
// 1. Your app encrypts data
// 2. TLS encrypts connection to CorsProxy
// 3. CorsProxy uses TLS to destination
// 4. Response follows same encrypted path back
Additional Layer of Encryption
// For extra security, encrypt payload before proxying
class DoubleEncryptedRequest {
async sendSecure(url: string, data: any) {
// Layer 1: Encrypt application data
const encrypted = await this.encryptPayload(data);
// Layer 2: TLS encryption via CorsProxy
const response = await fetch(`https://corsproxy.io/?url=${url}`, {
method: 'POST',
headers: {
'x-cors-api-key': process.env.CORS_API_KEY,
'Content-Type': 'application/octet-stream'
},
body: encrypted
});
return response.arrayBuffer();
}
private async encryptPayload(data: any): Promise<ArrayBuffer> {
const key = await this.getEncryptionKey();
const iv = crypto.getRandomValues(new Uint8Array(12));
const encryptedContent = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
new TextEncoder().encode(JSON.stringify(data))
);
// Combine IV and encrypted data
const result = new Uint8Array(iv.length + encryptedContent.byteLength);
result.set(iv);
result.set(new Uint8Array(encryptedContent), iv.length);
return result.buffer;
}
private async getEncryptionKey(): Promise<CryptoKey> {
// Import key from secure storage
const keyData = Buffer.from(process.env.APP_ENCRYPTION_KEY!, 'base64');
return crypto.subtle.importKey(
'raw',
keyData,
'AES-GCM',
false,
['encrypt', 'decrypt']
);
}
}
Common Encryption Mistakes
1. ECB Mode
// Bad: ECB mode reveals patterns
const badCipher = createCipheriv('aes-256-ecb', key, null);
// Identical plaintext blocks = identical ciphertext blocks
// Good: Use CBC or GCM with IV
const goodCipher = createCipheriv('aes-256-gcm', key, randomBytes(12));
// Randomized, no patterns visible
2. Reusing IVs
// Bad: Same IV for multiple encryptions
const staticIV = Buffer.from('1234567890123456');
const cipher1 = createCipheriv('aes-256-cbc', key, staticIV);
const cipher2 = createCipheriv('aes-256-cbc', key, staticIV);
// Vulnerable to attacks
// Good: Generate new IV for each encryption
const cipher1 = createCipheriv('aes-256-cbc', key, randomBytes(16));
const cipher2 = createCipheriv('aes-256-cbc', key, randomBytes(16));
3. No Authentication
// Bad: Encryption without authentication
const encrypted = cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
// Can be tampered with
// Good: Authenticated encryption
const cipher = createCipheriv('aes-256-gcm', key, iv);
const encrypted = cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
const authTag = cipher.getAuthTag(); // Prevents tampering