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-psasync 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 加密的主要内容,如果未能解决你的问题,请参考以下文章
Node.js实现对mysql数据库的crud时报加密方式错误解决方案
符合Good Node JS AES标准的Encrypt Decrypt模块