Skip to content

Instantly share code, notes, and snippets.

@RupW
Last active December 13, 2023 14:02
Show Gist options
  • Save RupW/a9f909db0de22d7b3f852c3dac6b5de5 to your computer and use it in GitHub Desktop.
Save RupW/a9f909db0de22d7b3f852c3dac6b5de5 to your computer and use it in GitHub Desktop.
CryptoJS-compatible AES encrypt and decrypt with password / pre-shared secret using Node built-in crypto instead
import * as crypto from 'node:crypto';
// Format is "Salted__", 8-byte salt, cipher text
const saltedPrefixBuffer = Buffer.from('Salted__');
function md5(...inputs: Buffer[]): Buffer {
const hash = crypto.createHash('md5');
inputs.forEach(input => hash.update(input));
return hash.digest();
}
function evpBytesToKey(secret: string, salt: Buffer): { key: Buffer, iv: Buffer } {
const secretBuffer = Buffer.from(secret);
const hash1 = md5(secretBuffer, salt);
const hash2 = md5(hash1, secretBuffer, salt);
const hash3 = md5(hash2, secretBuffer, salt);
return { key: Buffer.concat([hash1, hash2]), iv: hash3 };
}
export function cryptoJsAesDecrypt(inputBuffer: Buffer, secret: string): Buffer {
if (!saltedPrefixBuffer.equals(inputBuffer.subarray(0, 8))) {
throw Error('Bad input buffer format');
}
const salt = inputBuffer.subarray(8, 16);
const cipherText = inputBuffer.subarray(16);
const { key, iv } = evpBytesToKey(secret, salt);
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
return Buffer.concat([decipher.update(cipherText), decipher.final()]);
}
export function cryptoJsAesEncrypt(inputBuffer: Buffer, secret: string): Buffer {
const salt = crypto.randomBytes(8);
const { key, iv } = evpBytesToKey(secret, salt);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
return Buffer.concat([
saltedPrefixBuffer,
salt,
cipher.update(inputBuffer),
cipher.final(),
]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment