【问题标题】:Decrypting Blowfish CBC in Javascript that has been encrypted with PHP mcrypt用 PHP mcrypt 加密的 Javascript 中的 Blowfish CBC 解密
【发布时间】:2016-07-25 01:29:01
【问题描述】:

我很难尝试在 PHP 中解密已使用 Blowfish CBC 加密的字符串;

我正在使用 Node.js 在 Javascript 的客户端上进行使用 Mocha 编写的单元测试。 我正在使用 Node 的内置加密功能。

这是用于在 PHP 中解密字符串的代码。

<?php
 $cipher = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '');
 $iv = "my_iv";
 $key = substr("my_key", 0, 56);

 // I read that php automaticly pads my key with \0 to make it 56char long.

 if (mcrypt_generic_init($cipher, $key, $iv) != -1) {
   $text = mdecrypt_generic($cipher, urldecode("X%10%8F%AD%1C%1D%E1f%29%CD%D2%E1%81%B0%BE%D2M%8E3%D6%5DO%29%E3%E6%EF%24%A0%E0g%22%DA%D7YK%5B%AA%E6P%91%BA%B8U%C1%87k%7F%07%FD%9D%BF%1F%BD%95r%04%F0%18%A9%27%E17%2C%A8"));
   mcrypt_generic_deinit($cipher);
   echo rtrim($text, "\0");
 } else {
    echo "ERRROR";
 }
?>

这段代码给了我正确的输出,它是一个作为字符串的序列化数组。

然后我尝试了两个库在 JS 中使用相同的流程进行解密,

使用加密(内置节点):

var crypto = require('crypto');
var iv = new Buffer('my_iv');
var key = new Buffer('my_key');
var text = new Buffer(unescape("X%10%8F%AD%1C%1D%E1f%29%CD%D2%E1%81%B0%BE%D2M%8E3%D6%5DO%29%E3%E6%EF%24%A0%E0g%22%DA%D7YK%5B%AA%E6P%91%BA%B8U%C1%87k%7F%07%FD%9D%BF%1F%BD%95r%04%F0%18%A9%27%E17%2C%A8"));
var decipher = crypto.createDecipheriv('bf-cbc', key, iv);
var decrypted = decipher.update(text, '', '');
    decrypted += decipher.final('');
    console.log(decrypted);

给我这个错误:

error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
at Decipheriv.Cipher.final (crypto.js:320:27)

还有用于节点的 mcrypt 模块:https://github.com/tugrul/node-mcrypt

    var MCrypt = require('mcrypt').MCrypt;
    var bfCcb = new MCrypt('blowfish', 'cbc');
    var iv = Buffer.from('my_iv');
    var key = Buffer.from('my_key_padded_with_0\0\0');
    var text = Buffer.from(unescape("X%10%8F%AD%1C%1D%E1f%29%CD%D2%E1%81%B0%BE%D2M%8E3%D6%5DO%29%E3%E6%EF%24%A0%E0g%22%DA%D7YK%5B%AA%E6P%91%BA%B8U%C1%87k%7F%07%FD%9D%BF%1F%BD%95r%04%F0%18%A9%27%E17%2C%A8"));

    bfCcb.open(key, iv);

    var plaintext = bfCcb.decrypt(text);
    console.log(plaintext.toString());

它给了我错误的输出,

我不知道这是否与可能的编码有关,或者我是否在配置我的 javascripts 对象时遗漏了什么...

如果有人遇到过这个问题,请告诉我。

【问题讨论】:

  • Blowfish 不应再在新代码中使用,当前选择是 AES(高级加密标准)。另外最好不要使用 mcrypt,它是废弃软件,多年未更新,不支持标准 PKCS#7 填充,仅支持甚至不能用于二进制数据的非标准空填充。而是考虑使用defuse,它正在维护中并且是正确的。
  • 不要依赖参数填充,因为没有标准,每个实现都可以随心所欲。只需为 IV 和密钥提供正确的长度即可。
  • 当数据必须以 ASCII 而非 URL 编码表示时,通常使用十六进制的 Base64。

标签: javascript node.js cryptography blowfish mcrypt-js


【解决方案1】:

好的,忽略安全性。

注意:Blowfish 的块大小为 64 位,密钥长度从 32 位到 448 位不等。

错误消息说明错误是什么:“错误的最终块长度”,非常具体。基于块的加密要求输入是块大小的倍数。 “my_url_encodeed_string”是 22 字节的 ling,它不是 8 字节的 Blowfish 块大小的倍数。

“my_url_encodeed_string”未加密(加密后似乎是随机位和字节),因此无法解密。它也不是 URL 编码的,所以不需要unescape

mcrypt 没有产生错误并不意味着它成功解密了它的数据。 Blowfish 加密本身无法判断解密是否成功。进一步(你不会喜欢这样的):

最好不要使用 mcrypt,它是废弃软件,多年未更新,不支持标准 PKCS#7 填充,只有非标准的空填充,甚至不能用于二进制数据。而是考虑使用defuse,它正在维护中并且是正确的。

进一步:不要依赖参数填充,因为没有标准,每个实现都可以随心所欲。只需为 IV 和密钥提供正确的长度即可。

【讨论】:

  • my_url_encode_string 只是一个示例,但目前不是我正在解码的确切类型的字符串,只是给出了我试图在那里解密的数据类型的示例,将更新我的问题一个卷轴示例。
猜你喜欢
  • 2015-09-25
  • 2023-03-03
  • 2014-02-06
  • 2011-08-31
  • 2019-05-15
  • 2019-09-09
  • 2012-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多