mysql 和 node.js 上的 AES 加密

Posted

技术标签:

【中文标题】mysql 和 node.js 上的 AES 加密【英文标题】:AES encryption on mysql and node.js 【发布时间】:2021-11-15 07:16:44 【问题描述】:

我几天来一直在以下问题上苦苦挣扎,之前发布了同样的问题,但没有得到任何积极的反馈。

我正在使用 mysql in build aes_encrypt 方法来加密新的和现有的数据。 https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html

SET @@SESSION.block_encryption_mode = 'aes-256-ecb';
INSERT INTO test_aes_ecb ( column_one, column_two )
values ( aes_encrypt('text','key'), aes_encrypt('text', 'key'));

我使用了 ecb ciper,所以不需要使用 iv。问题是我无法从 node.js 端解密它。

我正在使用 sequelize 并尝试从节点端通过 model --> decrypt 调用数据。

我尝试了以下库,

"aes-ecb": "^1.3.15",
"aes256": "^1.1.0",
"crypto-js": "^4.1.1",
"mysql-aes": "0.0.1",

以下是 sequelize 调用

的代码 sn-ps
async function testmysqlAESModel () 
    const users = await test.findAll();
    console.log('users', users[0].column_one);
    var decrypt = AES.decrypt( users[0].column_one, 'key' );

它返回的缓冲区数据和无法从节点端解密,有人可以为此提供适当的例子吗?我挣扎了好几天。

编辑

将记录插入mysql,如下查询。

SET @@SESSION.block_encryption_mode = 'aes-256-ecb';
INSERT INTO test_aes_ecb ( id, column_one, column_two )
VALUES (1, 2,AES_ENCRYPT('test',UNHEX('gVkYp3s6v9y$B&E)H@McQeThWmZq4t7w')));

在这样调用的nodejs中,

testmysqlAESModel();
async function testmysqlAESModel () 
    const users = await test.findAll();
    console.log('users', users[0].column_one);
    var decipher = crypto.createDecipheriv(algorithm, Buffer.from("gVkYp3s6v9y$B&E)H@McQeThWmZq4t7w", "hex"), "");
    var encrypted = Buffer.from(users[0].column_one); // Note that this is what is stored inside your database, so that corresponds to users[0].column_one
    var decrypted = decipher.update(encrypted, 'binary', 'utf8');
    decrypted += decipher.final('utf8');
    console.log(decrypted);


我遇到了错误,

我使用下面的链接来创建 256 位密钥。

https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx

还是无法解决,能否提供样例项目或任何类型的支持代码sn-p?

【问题讨论】:

您是如何创建密钥的/密钥的长度是多少? 我的 ket 是字母数字键,类似于这种格式 8d6754e1-4524-4b1b-b0b8-81156c11c3a1 它是从 uuid 生成器创建的 【参考方案1】:

这里有多个问题:

    确保您的密钥长度正确。 AES 是为特定的密钥长度(即 128、196 和 256 位)指定的。如果您使用任何其他密钥长度,那么您的密钥将被加密库填充(零扩展)或截断。这是一个非标准的过程,不同的实现会以不同的方式做到这一点。为避免这种情况,请使用正确长度的密钥并将其存储为十六进制而不是 ascii(以避免字符集问题)

    关于密钥推断的密码的潜在问题。一些 AES 实现使用方法从密码/密码短语中推断密钥。由于您在 MySQL 中使用原始键,因此您不想推断任何东西,但也想在 NodeJS 中使用原始键。这意味着如果您使用的是本机加密模块,则您希望使用 createDecipheriv 而不是 createDecipher

注意:您使用的 AES 模式 (ECB) 本质上是不安全的,因为相等的输入导致相等的输出。有一些方法可以使用其他 AES 模式,例如 CBC 或 GCM。您已收到警告。

例子:

MySQL SELECT AES_ENCRYPT('text',UNHEX('F3229A0B371ED2D9441B830D21A390C3')) as test; 返回缓冲区[145,108,16,83,247,49,165,147,71,115,72,63,152,29,218,246]

在 Node 中解码可能如下所示:

var crypto = require('crypto');
var algorithm = 'aes-128-ecb';
var decipher = crypto.createDecipheriv(algorithm, Buffer.from("F3229A0B371ED2D9441B830D21A390C3", "hex"), "");
var encrypted = Buffer.from([145,108,16,83,247,49,165,147,71,115,72,63,152,29,218,246]); // Note that this is what is stored inside your database, so that corresponds to users[0].column_one
var decrypted = decipher.update(encrypted, 'binary', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);

这会再次打印text

请注意,F3229A0B371ED2D9441B830D21A390C3 是此示例中的键,您显然必须创建自己的键。只需确保您的密钥与示例具有相同的长度,并且是有效的十六进制字符串。

【讨论】:

谢谢你的回答,我用新的试用代码编辑了问题,你能看看吗? 您的密钥必须是十六进制编码的(您使用的网站上有一个复选框),您的不是。我强烈建议不要使用其他人的网络服务来生成密钥。相反,您可以使用 OpenSSL 来执行此操作:openssl enc -aes-256-ecb -k replacethiswithsomethingrandom -P -md sha256。另外,您的示例 javascript 代码中的 algorithm 是什么?如果你想要 aes 256,那一定是aes-256-ecb 感谢您的回复,我已经挣扎了好几天了。 嗨,我有一个小问题,这是解密上面mysql插入数据的方法吗?从 test_aes_ecb 中选择 AES_DECRYPT (UNHEX(column_two), 'key' );

以上是关于mysql 和 node.js 上的 AES 加密的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP 中加密字符串并在 Node.js 中解密

Node.js实现对mysql数据库的crud时报加密方式错误解决方案

符合Good Node JS AES标准的Encrypt Decrypt模块

node.js 怎么用crypto rsa加密密码

如何使用 JavaScript 在浏览器中加密数据并使用 Node.js 在服务器端解密

等效于 MySQL aes_encrypt() 函数的 AES 加密方法