e2ee-adapter
Version:
Plug-and-play End-to-End Encryption middleware for Express.js and NestJS using hybrid AES-CBC + RSA encryption with secure key exchange
89 lines • 3.77 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createE2EEMiddleware = createE2EEMiddleware;
const e2ee_common_1 = require("../utils/e2ee-common");
/**
* Create E2EE middleware for Express.js
* @param options - Middleware configuration options
* @returns E2EEMiddleware
*/
function createE2EEMiddleware(options) {
const { config, onError, onDecrypt, onEncrypt } = options;
// Validate configuration
(0, e2ee_common_1.validateConfig)(config);
// Merge configuration with defaults
const finalConfig = (0, e2ee_common_1.mergeConfigWithDefaults)(config);
/**
* Create E2EE error
*/
function createError(message, code, statusCode = 400) {
return (0, e2ee_common_1.createE2EEError)(message, code, statusCode);
}
/**
* Main middleware function
*/
return async (req, res, next) => {
try {
// Process request and check if it should be handled
const processingResult = (0, e2ee_common_1.processRequest)(req, finalConfig, createError);
if (processingResult.shouldContinue) {
return next();
}
// Handle request decryption
let e2eeContext = await (0, e2ee_common_1.handleRequestDecryption)(req, finalConfig, createError, onDecrypt);
// Setup encryption context for response-only encryption if needed
if (!finalConfig.enableRequestDecryption &&
finalConfig.enableResponseEncryption) {
e2eeContext = await (0, e2ee_common_1.setupResponseEncryptionContext)(req, finalConfig, createError);
}
// Store encryption context for response
if (e2eeContext) {
req.e2ee = e2eeContext;
}
// Handle response encryption only
if (finalConfig.enableResponseEncryption) {
// Store original send method
const originalSend = res.send;
// Override send method to encrypt response data
res.send = function (data) {
const e2eeContext = req.e2ee;
if (!e2eeContext || !e2eeContext.aesKey || !e2eeContext.iv) {
// If no encryption context, send original data
return originalSend.call(this, data);
}
// Handle encryption asynchronously
(0, e2ee_common_1.handleResponseEncryption)(data, e2eeContext, createError, onEncrypt, res)
.then((encryptedData) => {
// Send the encrypted data
originalSend.call(this, encryptedData);
})
.catch((error) => {
if (onError) {
onError(error, req, res);
}
// Send error response
originalSend.call(this, {
error: 'Encryption failed',
message: error instanceof Error ? error.message : 'Unknown error',
});
});
// Return the response object for chaining
return this;
};
}
next();
}
catch (error) {
if (onError) {
onError(error, req, res);
}
const e2eeError = error;
res.status(e2eeError.statusCode || 400).json({
error: 'E2EE Error',
code: e2eeError.code || 'UNKNOWN_ERROR',
message: e2eeError.message,
});
}
};
}
//# sourceMappingURL=e2ee.js.map