node.js - Nodejs createCipheriv 像 openssl
问题描述
MariaDB 的静态加密依赖于 openssl 对 keys.txt 文件 ( https://mariadb.com/kb/en/library/encryption-key-management/#encrypting-the-key-file ) 的 sha1 加密。我需要使用 Node.js 启动一个 MariaDB 实例。所以,我需要使用 Node.js 以类似的方式加密这个文件。到目前为止,使用https://github.com/beeven/gulp-openssl-encrypt作为指南,我已经能够复制 openssl 的-md md5
. 但这不是 MariaDB 所需的 sha1 摘要。
function md5(data) {
let hash = crypto.createHash('md5');
hash.update(data);
return hash.digest();
}
const buffer = Buffer.from(stringToEncrypt);
const salt = crypto.randomBytes(8);
const password = Buffer.from(encryptionKey);
const hash1 = md5(Buffer.concat([password, salt]));
const hash2 = md5(Buffer.concat([hash1, password, salt]));
const key = Buffer.concat([hash1, hash2]);
const iv = md5(Buffer.concat([hash2, password, salt]));
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const chunks = [Buffer.from('Salted__'),salt];
chunks.push(cipher.update(buffer));
chunks.push(cipher.final());
let encryptedStuff = Buffer.concat(chunks);
(编辑:澄清)我想要的是这样的:
function sha1(data) {
let hash = crypto.createHash('sha1');
hash.update(data);
return hash.digest();
}
const buffer = Buffer.from(stringToEncrypt);
const salt = crypto.randomBytes(8);
const password = Buffer.from(encryptionKey);
const hash1 = sha1(Buffer.concat([password, salt]));
const hash2 = sha1(Buffer.concat([hash1, password, salt]));
const key = Buffer.concat([hash1, hash2]);
const iv = sha1(Buffer.concat([hash2, password, salt]));
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const chunks = [Buffer.from('Salted__'),salt];
chunks.push(cipher.update(buffer));
chunks.push(cipher.final());
let encryptedStuff = Buffer.concat(chunks);
但是当我尝试这样做时,密钥和 iv 变得太长,并且出现“无效密钥长度”错误。因此,当我尝试按照https://github.com/nodejs/node/issues/6696的建议对其进行切片时,它确实对其进行了加密,但 openssl 无法对其进行解密。
解决方案
For details on the OpenSSL password-based encryption scheme used for enc
namely EVP_BytesToKey
, see https://crypto.stackexchange.com/questions/3298/is-there-a-standard-for-openssl-interoperable-aes-encryption
AES-256 in CBC mode requires 48 octets for key+IV and SHA1 output is 20 octets, so you must:
// do three hashes, much as you already have
hash1 = sha1(Buffer.concat([password, salt]));
hash2 = sha1(Buffer.concat([hash1, password, salt]));
hash3 = sha1(Buffer.concat([hash2, password, salt]));
// then concatenate them and split _that_ to key and IV
total = Buffer.concat([hash1,hash2,hash3]);
key = total.slice(0,32);
iv = total.slice(32,48);
For md5 treating them separately worked because it happens MD5 output of 16 octets is exactly half the key size and exactly the IV size.
推荐阅读
- angular - 在Angular 2 Seed项目中根据域名动态设置App Title
- ruby-on-rails - 如果存在具有相同属性的记录,则更改 Create 的行为
- r - 在 R 的不同列中插入重复项和非重复项
- reactjs - 在 React 中,存储大数据数组的更好地方是什么?
- powershell - 按用户属性过滤 AD 组;退货不当
- python - 按间隔对数据帧进行分组
- qt - OpenCV4 - 深度神经网络 - dnn.hpp 没有这样的文件或目录
- python - 如何根据环境从我的 settings.py DATABASES 数组中激活数据库设置?
- c# - 许多按钮触发 backgroundWorker
- git - 从 Powershell 运行“Git-Clone”,即使它似乎可以工作,也会出现错误