hybrid-encryption-express
v1.0.1
Published
Production-ready hybrid encryption middleware for Express.js with RSA-OAEP + AES-256-GCM
Maintainers
Readme
@your-scope/hybrid-encryption-express
Production-ready hybrid encryption middleware for Express.js applications with full TypeScript support.
Features
- Hybrid Encryption: RSA-OAEP-2048 for key exchange + AES-256-GCM for payload encryption
- Session Management: Per-client session-based AES keys with configurable expiry
- Express Integration: Seamless middleware for request/response encryption
- TypeScript First: Full type safety with IntelliSense support
- Tree Shakable: ESM + CJS dual build with proper exports
- Pluggable Storage: In-memory session store with Redis-ready interface
- Security Focused: Constant-time comparisons, secure key handling
Installation
npm install @your-scope/hybrid-encryption-expressQuick Start
Basic Express Setup
import express from 'express';
import {
createHybridCrypto,
hybridDecryptMiddleware,
hybridEncryptMiddleware,
cryptoRouter
} from '@your-scope/hybrid-encryption-express';
const app = express();
const hybridCrypto = createHybridCrypto();
// Middleware setup
app.use(express.json());
app.use(hybridDecryptMiddleware({ hybridCrypto }));
app.use(hybridEncryptMiddleware({ hybridCrypto }));
// Crypto routes for handshake
app.use(cryptoRouter({ hybridCrypto }));
// Your protected routes
app.post('/api/data', (req, res) => {
// req.body is automatically decrypted
// Response will be encrypted if X-Encrypted: true header is present
res.json({ message: 'Data received', data: req.body });
});
app.listen(3000);TypeScript Setup
import express, { Request, Response } from 'express';
import {
createHybridCrypto,
hybridDecryptMiddleware,
hybridEncryptMiddleware,
cryptoRouter,
type HybridCryptoOptions
} from '@your-scope/hybrid-encryption-express';
const options: HybridCryptoOptions = {
sessionTtlMs: 10 * 60 * 1000, // 10 minutes
skipRoutes: ['/health', '/public']
};
const app = express();
const hybridCrypto = createHybridCrypto(options);
app.use(express.json());
app.use(hybridDecryptMiddleware({ hybridCrypto }));
app.use(hybridEncryptMiddleware({ hybridCrypto }));
app.use(cryptoRouter({ hybridCrypto }));
app.post('/api/secure', (req: Request, res: Response) => {
// TypeScript knows about req.encryptionMetadata
if (req.encryptionMetadata?.encrypted) {
console.log('Request was encrypted');
}
res.json({ secure: true, data: req.body });
});Client Integration
1. Get Public Key
const response = await fetch('/crypto/public-key');
const { publicKey } = await response.json();2. Generate AES Key and Handshake
import { createPublicKey, publicEncrypt, randomBytes } from 'crypto';
// Generate AES-256 key
const aesKey = randomBytes(32);
// Encrypt AES key with RSA public key
const publicKeyObj = createPublicKey(publicKey);
const encryptedAesKey = publicEncrypt({
key: publicKeyObj,
padding: 1, // RSA_PKCS1_OAEP_PADDING
oaepHash: 'sha256'
}, aesKey);
// Perform handshake
const handshakeResponse = await fetch('/crypto/handshake', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
clientId: 'unique-client-id',
encryptedAesKey: encryptedAesKey.toString('base64')
})
});
const { success, sessionExpiry } = await handshakeResponse.json();3. Send Encrypted Requests
import { createCipherGCM, randomBytes } from 'crypto';
function encryptData(data, aesKey) {
const iv = randomBytes(12);
const cipher = createCipherGCM('aes-256-gcm', aesKey);
let encrypted = cipher.update(JSON.stringify(data), 'utf8');
encrypted = Buffer.concat([encrypted, cipher.final()]);
return {
data: encrypted.toString('base64'),
iv: iv.toString('base64'),
authTag: cipher.getAuthTag().toString('base64')
};
}
// Send encrypted request
const encryptedPayload = encryptData({ message: 'secret data' }, aesKey);
const response = await fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Client-Id': 'unique-client-id',
'X-Encrypted': 'true'
},
body: JSON.stringify(encryptedPayload)
});API Reference
createHybridCrypto(options?)
Creates a new HybridCrypto instance.
Options:
sessionStore?: SessionStore- Custom session store (default: MemorySessionStore)sessionTtlMs?: number- Session TTL in milliseconds (default: 5 minutes)rsaKeySize?: number- RSA key size (default: 2048)skipRoutes?: string[]- Routes to skip encryption (default: ['/health', '/crypto/public-key', '/crypto/handshake'])
hybridDecryptMiddleware(options)
Express middleware for decrypting incoming requests.
Options:
hybridCrypto: HybridCrypto- HybridCrypto instanceskipRoutes?: string[]- Routes to skip decryptionclientIdHeader?: string- Header name for client ID (default: 'x-client-id')
hybridEncryptMiddleware(options)
Express middleware for encrypting outgoing responses.
Options:
hybridCrypto: HybridCrypto- HybridCrypto instanceskipRoutes?: string[]- Routes to skip encryptionencryptHeader?: string- Header to check for encryption request (default: 'x-encrypted')
cryptoRouter(options)
Express router with crypto endpoints.
Options:
hybridCrypto: HybridCrypto- HybridCrypto instancepublicKeyPath?: string- Public key endpoint path (default: '/crypto/public-key')handshakePath?: string- Handshake endpoint path (default: '/crypto/handshake')testPath?: string- Test endpoint path (default: '/crypto/test')
Custom Session Store
Implement the SessionStore interface for custom storage:
import { SessionStore, SessionData } from '@your-scope/hybrid-encryption-express';
class RedisSessionStore implements SessionStore {
async set(clientId: string, sessionData: SessionData): Promise<void> {
// Store in Redis
}
async get(clientId: string): Promise<SessionData | null> {
// Retrieve from Redis
}
async delete(clientId: string): Promise<void> {
// Delete from Redis
}
async cleanup(): Promise<void> {
// Clean expired sessions
}
}Security Considerations
- RSA keys are generated per server instance
- AES keys are unique per client session
- Sessions expire automatically (configurable TTL)
- Constant-time comparisons prevent timing attacks
- IV and auth tags are validated before decryption
- No secrets are logged
License
MIT
