@boopathi02/secure-e2e-framework
v1.0.18
Published
Enterprise Application Layer Encryption SDK
Maintainers
Readme
@boopathi02/secure-e2e-framework
Enterprise application-layer encryption SDK for securing HTTP requests, responses, file uploads, WebSocket communication, and streaming data.
Features
- Application-Layer Encryption: Secures payloads using AES-256-GCM (authenticates and encrypts data).
- HTTP Client/Server Integrations: Axios interceptors for frontend; Express middleware for backend.
- File Uploads: Seamless Multer integration for handling encrypted files and multipart forms.
- WebSocket Support: Socket.io middleware to automatically encrypt/decrypt emitted events.
- Streaming: Web Streams API support (
TransformStream) for chunked stream encryption and decryption. - Replay Protection: Timestamp window validation and nonce tracking to prevent replay attacks.
Why This Package?
While HTTPS/TLS protects data in transit, it typically terminates at the load balancer or reverse proxy. This SDK provides an additional layer of application-level security by encrypting the application payload itself. The plaintext data is only available at the final application controller or the client.
Architecture
sequenceDiagram
participant Client
participant Server
participant Controller
Client->>Client: Encrypt Request (AES-256-GCM)
Client->>Server: Encrypted Payload (JSON/FormData/Buffer)
Server->>Server: Express Middleware Decrypts
Server->>Controller: Plaintext Data
Controller->>Server: Response Plaintext Data
Server->>Server: Express Middleware Encrypts
Server->>Client: Encrypted Response
Client->>Client: Axios Interceptor DecryptsInstallation
npm install @boopathi02/secure-e2e-framework axios
# or
pnpm add @boopathi02/secure-e2e-framework axiosPeer Dependencies:
axiosis required for theApiClient.socket.ioandsocket.io-client(optional, required if using WebSocket features).express(optional, required if using Server Middleware).
Quick Start / Client Usage
The ApiClient wraps Axios and automatically encrypts outgoing requests and decrypts incoming responses (including error responses).
import { ApiClient, MemoryKeyProvider } from '@boopathi02/secure-e2e-framework';
// 1. Setup the key provider with a secure 32-byte key (base64 encoded or Uint8Array)
const keyProvider = new MemoryKeyProvider({
default: 'YOUR_BASE64_ENCODED_32_BYTE_KEY'
});
// 2. Initialize the Secure API Client
const client = new ApiClient({
encryption: {
keyProvider: keyProvider,
replayProtection: true
}
}, 'https://api.yourdomain.com');
// 3. Make requests (Payloads are automatically encrypted!)
async function fetchSecureData() {
try {
const response = await client.post('/secure-endpoint', {
sensitiveData: 'secret-value'
});
// The response body is automatically decrypted
console.log('Decrypted response:', response.data);
} catch (error) {
// If the server returns a 4xx/5xx encrypted error, it is also decrypted automatically
console.error('Request failed', error);
}
}Server Usage
The framework provides the secureMiddleware (alias for secureE2E) for Express to handle decryption of incoming requests (JSON, Query Params, FormData, and Raw Buffers) and encryption of outgoing JSON responses.
import express from 'express';
import { secureMiddleware, MemoryKeyProvider, createSecureServer } from '@boopathi02/secure-e2e-framework';
const app = express();
const keyProvider = new MemoryKeyProvider({
default: 'YOUR_BASE64_ENCODED_32_BYTE_KEY'
});
// Initialize global core (required for backend middleware)
createSecureServer({
encryption: {
keyProvider: keyProvider,
replayProtection: true
}
});
app.use(express.json());
// Apply secure middleware globally or per route
app.use(secureMiddleware());
app.post('/secure-endpoint', (req, res) => {
// req.body is already decrypted!
console.log('Decrypted Body:', req.body);
// res.json() will automatically encrypt the response payload!
res.json({ message: 'Success', received: req.body });
});File Uploads (Multer Integration)
To handle encrypted file uploads, pass your multer middleware to the secureMiddleware options. The middleware will decrypt the file buffer (or disk file) automatically after multer processes it.
import express from 'express';
import multer from 'multer';
import { secureMiddleware } from '@boopathi02/secure-e2e-framework';
const app = express();
const upload = multer({ storage: multer.memoryStorage() }); // or dest: 'uploads/'
// Apply the secure middleware combined with multer
app.post('/upload',
secureMiddleware({ upload: upload.single('document') }),
(req, res) => {
// req.file is now the DECRYPTED file buffer!
console.log('Decrypted file details:', req.file);
// If formData had other text fields, they are also decrypted in req.body
console.log('Decrypted form data:', req.body);
res.json({ success: true, fileSize: req.file?.size });
}
);FormData / Multipart Support
When sending FormData from the client:
- JSON text fields: Encrypted text fields are parsed and decrypted into
req.body. - Files: Encrypted files are intercepted, processed by
secureMiddleware(if configured withmulter), and replaced with their decrypted versions inreq.fileorreq.files. - Arrays and Multiple Files: Supported seamlessly through
req.filesarrays or objects.
WebSocket Support
The framework can seamlessly encrypt and decrypt Socket.io events.
Server WebSocket
import { Server } from 'socket.io';
import { SocketManager, MemoryKeyProvider } from '@boopathi02/secure-e2e-framework';
const io = new Server(3000);
const keyProvider = new MemoryKeyProvider({ default: 'YOUR_BASE64_KEY' });
const socketManager = new SocketManager({ encryption: { keyProvider } });
// Attaches middleware to intercept incoming/outgoing events
socketManager.attachSecureMiddleware(io);
io.on('connection', (socket) => {
socket.on('secure-event', (data) => {
// data is decrypted
socket.emit('secure-response', { status: 'Received' }); // Automatically encrypted
});
});Client WebSocket
import { io } from 'socket.io-client';
import { SecureSocketClient, MemoryKeyProvider } from '@boopathi02/secure-e2e-framework';
const socket = io('http://localhost:3000');
const keyProvider = new MemoryKeyProvider({ default: 'YOUR_BASE64_KEY' });
const secureSocket = new SecureSocketClient({ encryption: { keyProvider } }, socket);
// Use secureSocket.socket to emit/listen for events
secureSocket.socket.emit('secure-event', { secret: 'data' });
secureSocket.socket.on('secure-response', (data) => {
console.log('Decrypted:', data);
});Binary and Streaming API
The SDK provides SecureStreamEngine for chunked encryption/decryption using the Web Streams API (TransformStream). It uses an efficient streaming frame format that avoids large memory allocations.
import { SecureStreamEngine } from '@boopathi02/secure-e2e-framework';
// Creating stream transformers
const encryptStream = SecureStreamEngine.createEncryptTransformStream(config, 'keyId');
const decryptStream = SecureStreamEngine.createDecryptTransformStream(config, 'keyId');
// Example usage with Web APIs (e.g., fetch response streams)
const response = await fetch('/encrypted-video-stream');
const decryptedWebStream = response.body.pipeThrough(decryptStream);Security Features: Replay Protection
By default, the payload contains a timestamp and a 16-byte nonce. The server tracks nonces (up to 10,000 in memory) and validates that requests fall within an acceptable time window to prevent replay attacks.
Ensure your client and server clocks are reasonably synchronized when enabling this feature.
Key Management
The framework relies on symmetric encryption (AES-256-GCM) and requires a 256-bit (32-byte) key. Keys are managed via providers implementing the KeyProvider interface.
MemoryKeyProvider is provided out of the box. You can initialize it with a base64 encoded string or a Uint8Array.
Generating a secure key (Node.js):
import { randomBytes } from 'crypto';
const secureKey = new Uint8Array(randomBytes(32));
// Store this securely! Do NOT generate on every startup unless using dynamic key exchange.Do not use new Uint8Array(32) as a real key, as it generates an insecure, predictable array of zeros.
In a distributed environment, you should implement your own KeyProvider backed by Redis, a database, or a Key Management Service (KMS) so that all servers can resolve keyId to the same secret.
Configuration Reference
| Option | Type | Default | Description |
|---|---|---|---|
| encryption.algorithm | string | 'AES-256-GCM' | The encryption algorithm. |
| encryption.keyProvider | KeyProvider | (Required) | Interface implementation to retrieve keys. |
| encryption.replayProtection | boolean | true | Enables timestamp and nonce validation. |
| encryption.replayWindowMs | number | 300000 | Acceptable time window in milliseconds (default: 5 mins). |
Security Considerations
- HTTPS/TLS Still Required: This SDK provides application-layer encryption. It does NOT replace HTTPS/TLS. Always use HTTPS in production to prevent man-in-the-middle (MITM) attacks and protect metadata.
- Key Storage: Do not hardcode encryption keys in source code. Use secure environment variables, KMS, or secrets managers.
- Key Rotation: Implement key rotation strategies in your custom
KeyProviderutilizing thekeyIdparameter included in every encrypted payload.
Error Handling & Troubleshooting
- Decryption Failed: Ensure the client and server are using the exact same 32-byte key. Check that
keyIdmatches on both sides. - Payload timestamp outside acceptable window (ReplayError): Ensure client and server clocks are synchronized. If device clocks drift heavily, adjust
replayWindowMsor implement a time-sync API. - Duplicate nonce detected: A request payload was intercepted and re-sent within the replay window. The server blocked it correctly.
- Unsupported TransformStream: The streaming API requires an environment that supports the Web Streams API (Node 16.5+, modern browsers).
- Socket/Axios Error Responses:
ApiClientautomatically attempts to decrypterror.response. If decryption fails, the raw Axios error is thrown.
Production Checklist
- [ ] HTTPS/TLS is enabled on the server/load balancer.
- [ ] 32-byte AES keys are generated cryptographically and stored securely.
- [ ] Application clocks are synchronized via NTP to support Replay Protection.
- [ ] A persistent
KeyProvider(e.g., Redis-backed) is used if running multiple Node.js instances. - [ ] Sensitive data and decrypted payloads are not accidentally logged.
License
MIT
