cross-crypto-ts
Version:
Cifrado híbrido seguro con interoperabilidad entre lenguajes como Python, TypeScript y Rust, basado en AES-GCM (256 bits) y RSA-OAEP (4096 bits).
65 lines (64 loc) • 2.78 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.encryptHybrid = encryptHybrid;
// src/encrypt.ts
const node_forge_1 = __importDefault(require("node-forge"));
const fs_1 = __importDefault(require("fs"));
const v8_1 = __importDefault(require("v8"));
function encryptHybrid(data, publicKeyPem, mode = 'json') {
const aesKey = node_forge_1.default.random.getBytesSync(32);
const nonce = node_forge_1.default.random.getBytesSync(12);
const publicKey = node_forge_1.default.pki.publicKeyFromPem(publicKeyPem);
const encryptedAesKey = publicKey.encrypt(aesKey, 'RSA-OAEP');
if (mode === 'stream') {
if (typeof data !== 'string')
throw new TypeError('Stream mode requiere path al archivo');
const inputPath = data;
const finalPath = inputPath + '.enc';
const cipher = node_forge_1.default.cipher.createCipher('AES-GCM', aesKey);
cipher.start({ iv: nonce });
const inputBuffer = fs_1.default.readFileSync(inputPath);
cipher.update(node_forge_1.default.util.createBuffer(inputBuffer.toString('binary')));
cipher.finish();
const encryptedData = cipher.output.getBytes();
const tag = cipher.mode.tag.getBytes();
fs_1.default.writeFileSync(finalPath, Buffer.from(encryptedData, 'binary'));
return {
encryptedKey: node_forge_1.default.util.encode64(encryptedAesKey),
nonce: node_forge_1.default.util.encode64(nonce),
tag: node_forge_1.default.util.encode64(tag),
encryptedPath: finalPath,
mode: 'stream'
};
}
let plaintext;
if (mode === 'json') {
plaintext = JSON.stringify(data);
}
else if (mode === 'v8') {
const serialized = v8_1.default.serialize(data);
plaintext = Buffer.from(serialized).toString('binary');
}
else if (Buffer.isBuffer(data)) {
plaintext = data.toString('binary');
}
else {
plaintext = Buffer.from(data).toString('binary');
}
const cipher = node_forge_1.default.cipher.createCipher('AES-GCM', aesKey);
cipher.start({ iv: nonce });
cipher.update(node_forge_1.default.util.createBuffer(plaintext));
cipher.finish();
const encrypted = cipher.output.getBytes();
const tag = cipher.mode.tag.getBytes();
return {
encryptedKey: node_forge_1.default.util.encode64(encryptedAesKey),
encryptedData: node_forge_1.default.util.encode64(encrypted),
nonce: node_forge_1.default.util.encode64(nonce),
tag: node_forge_1.default.util.encode64(tag),
mode: mode
};
}