使用 nodejs crypto 与 php 的 mcrypt 解密 Blowfish-ecb

Posted

技术标签:

【中文标题】使用 nodejs crypto 与 php 的 mcrypt 解密 Blowfish-ecb【英文标题】:Decrypting blowfish-ecb with nodejs crypto vs php's mcrypt 【发布时间】:2012-01-28 16:24:27 【问题描述】:

我正在尝试使用内置加密库在 Node.js 中解码以下 base64 编码的密文

2tGiKhSjSQEjoDNukf5BpfvwmdjBtA9kS1EaNPupESqheZ1TCr5ckEdWUvd+e51XWLUzdhBFNOBRrUB5jR64Pjf1VKvQ4dhcDk3Fdu4hyUoBSWfY053Rfd3fqpgZVggoKk4wvmNiCuEMEHxV3rGNKeFzOvP/P3O5gOF7HZYa2dgezizXSgnnD6mCp37OJXqHuAngr0pps/i9819O6FyKgu6t2AzwbWZkP2sXvH3OGRU6oj5DFTgiKGv1GbrM8mIrC7rlRdNgiJ9dyHrOAwqO+SVwzhhTWj1K//PoyyzDKUuqqUQ6AvJl7d1o5sHNzeNgJxhywMT9F10+gnliBxIg8gGSmzBqrgwUNZxltT4uEKz67u9eJi59a0HBBi/2+umzwOCHNA4jl1x0mv0MhYiX/A==

它似乎可以使用字符串 typeconfig.sys^_- 作为键与 php 的 mcrypt 函数一起使用,如将值输入到 http://www.tools4noobs.com/online_tools/decrypt/ 并选择 Blowfish、ECB、Base64 解码所示。

但是,当我在 Node.js 中运行以下代码时:

var crypto = require('crypto');
var data = "2tGiKhSjSQEjoDNukf5BpfvwmdjBtA9kS1EaNPupESqheZ1TCr5ckEdWUvd+e51XWLUzdhBFNOBRrUB5jR64Pjf1VKvQ4dhcDk3Fdu4hyUoBSWfY053Rfd3fqpgZVggoKk4wvmNiCuEMEHxV3rGNKeFzOvP/P3O5gOF7HZYa2dgezizXSgnnD6mCp37OJXqHuAngr0pps/i9819O6FyKgu6t2AzwbWZkP2sXvH3OGRU6oj5DFTgiKGv1GbrM8mIrC7rlRdNgiJ9dyHrOAwqO+SVwzhhTWj1K//PoyyzDKUuqqUQ6AvJl7d1o5sHNzeNgJxhywMT9F10+gnliBxIg8gGSmzBqrgwUNZxltT4uEKz67u9eJi59a0HBBi/2+umzwOCHNA4jl1x0mv0MhYiX/A==";
var decipher = crypto.createDecipher('bf-ecb', 'typeconfig.sys^_-');
data = decipher.update(data, "base64", "utf8");
data += decipher.final("utf8");
console.log(data);

我得到垃圾输出:

y
�:����d�(����Q�i��z1��4�� �k�(� ��a5����u��73c/��(ֻ��)��������fȠ���
                                                              �ec�-<z�8����(�-L���ԛ�I��1L*��u�4�j-�Чh쭊@\P)?޼�.�^���q㊬�U���W&�x��85�T-ג9,dE<g�`*�
��|@����k"�!�D'u���,x��7����
                 ��9q=q�q��ա>�w�T����H3͜�i)R��zy��C��
                                                    ��o�

我还尝试了对库本身的测试,因为它似乎能够很好地处理它自己编码的东西:

var crypto = require('crypto')
var cipher = crypto.createCipher("bf-ecb", "key");
var data = cipher.update("foobar", "utf8", "base64");
data += cipher.final("base64");
console.log(data);
var decipher = crypto.createDecipher("bf-ecb", "key");
data = decipher.update(data, "base64", "utf8");
data += decipher.final("utf8");
console.log(data);

产生:

y0rq5pYkiU0=
foobar

但复制并粘贴该 base64 字符串并将其输入到 http://www.tools4noobs.com/online_tools/decrypt/ 旁边的键“key”也会产生垃圾输出。

这两个库不应该产生相同的输出,还是我做错了什么?

【问题讨论】:

Node.js 和 PHP 的 mcrypt 的文档不清楚,但看起来 Node.js 使用了密钥派生函数,而 mcrypt 使用的是原样的密钥。由于 Node.js 实现了 PBKDF2,我猜这是它的密钥派生算法,但我不知道如何指定参数。您应该弄清楚它使用的参数,然后根据您的密码派生一个密钥,并在 PHP 端使用该密钥。 哦,另外,我注意到在工作的 Node.js 代码中,您使用 createCipher() 来加密 解密,而在您原来的、不工作的代码中,您正在使用createDecipher() @erickson 是的,createCipher 两次是拼写错误,抱歉.. 我的问题是我正在尝试与需要该特定原始密钥的另一个服务兼容(请参阅第一个 base64 编码例如字符串),所以你的回答帮助解释了两者之间的区别,它实际上并不能帮助我解码和编码我需要的东西。 【参考方案1】:

Node.js 在将密码用作密钥之前计算密码的 MD5 哈希值。据我所知,mcrypt 按原样使用密钥。

计算密码的 MD5 哈希值,并将其用作 mcrypt 密钥。

【讨论】:

这似乎足以推动正确的方向。 createCiphercreateDecipher 使用密钥的 MD5 哈希,而 createCipherivcreateDecipheriv 使用原始密钥和提供的 IV。更改代码以使用 crypto.createDecipheriv('bf-ecb', 'typeconfig.sys^_-', '') 使其现在可以工作。谢谢! @erickson 对这个问题有什么想法吗? ***.com/questions/37825261/…【参考方案2】:

https://github.com/tugrul/node-mcrypt

var mcrypt = require('mcrypt');

var bfEcb = new mcrypt.MCrypt('blowfish', 'ecb');

bfEcb.open('typeconfig.sys^_-');

var cipherText = new Buffer('2tGiKhSjSQEjoDNukf5BpfvwmdjBtA9kS1EaNPupESqheZ1TCr5ckEdWUvd+e51XWLUzdhBFNOBRrUB5jR64Pjf1VKvQ4dhcDk3Fdu4hyUoBSWfY053Rfd3fqpgZVggoKk4wvmNiCuEMEHxV3rGNKeFzOvP/P3O5gOF7HZYa2dgezizXSgnnD6mCp37OJXqHuAngr0pps/i9819O6FyKgu6t2AzwbWZkP2sXvH3OGRU6oj5DFTgiKGv1GbrM8mIrC7rlRdNgiJ9dyHrOAwqO+SVwzhhTWj1K//PoyyzDKUuqqUQ6AvJl7d1o5sHNzeNgJxhywMT9F10+gnliBxIg8gGSmzBqrgwUNZxltT4uEKz67u9eJi59a0HBBi/2+umzwOCHNA4jl1x0mv0MhYiX/A==', 'base64');

console.log(bfEcb.decrypt(cipherText).toString());

bfEcb.close();

【讨论】:

以上是关于使用 nodejs crypto 与 php 的 mcrypt 解密 Blowfish-ecb的主要内容,如果未能解决你的问题,请参考以下文章

比较用 PHP hash() 和 NodeJS crypto.createHash() 制作的 SHA256

如何在php hash_pbkdf2中使用字节数组类型的nodejs crypto pbkdf2 salt

nodeJS之crypto模块md5和Hmac加密

crypto在web的使用

nodeJS之crypto模块公钥加密及解密

Nodejs crypto.pbkdf2 结果与 CryptoJS.PBKDF2 不同