【问题标题】:Encryption with Node Crypto - Decryption with PHP openssl_decrypt fails使用节点加密进行加密 - 使用 PHP openssl_decrypt 解密失败
【发布时间】:2017-03-24 17:13:10
【问题描述】:

我正在尝试在节点服务中创建 JWT(JSON Web 令牌),然后需要在 PHP 服务中进行检查。

据我所知,我正在根据spec 创建令牌,并使用节点crypto 库对签名进行加密。我读过,在这些技术之间可靠工作的唯一算法是aes-128-cbc,所以这是我正在使用的算法。

我在使用mcrypt_decrypt 时遇到了一些运气,但它仍然不是 100% 正确,这仍然是失败的。此外,由于该库已被弃用,我宁愿使用 openssl_decrypt,我根本无法使用它,它只会返回 false。

秘密和初始化向量都存储在数据库中类型为 varchar(16) 的字段中,因此它们在两个代码位中是相同的。我使用的是 16 字节的块大小,因此与 16 字节的秘密和 iv 匹配。

我尝试了二进制、十六进制和 base64 格式的不同组合,但无法让 openssl_decrypt 函数返回除 false 之外的任何内容。

这个问题归结为如何在节点中加密字符串并在 PHP 中解密?或者我目前对这些方法的使用有什么问题?

节点 v7.4.0

var crypto = require('crypto');
var secret = crypto.randomBytes(16);
var iv = crypto.randomBytes(16);
var header = { type:'JWT', alg: 'aes-128-cbc' };
var payload = { iss: 'auth-token', exp: Date.now() + 86400, token: <some uuid> };

var data = new Buffer(JSON.stringify(header)).toString('base64') + '.' + new Buffer(JSON.stringify(payload)).toString('base64');
var cipher = crypto.createCipheriv('aes-128-cbc', secret, iv);
var encrypted = cipher.update(data, 'utf8', 'base64') + cipher.final('base64');
var JWT = data + '.'+ encrypted;

PHP v7.0.13(也尝试过 v7.1.1)

list($header64, $payload64, $sigEnc) = explode('.', $_POST['jwt']);
$header = base64_decode ($header64);
$payload = base64_decode ($payload64);
$signature = openssl_decrypt($sigEnc, 'aes-128-cbc', $secret, null, $iv); // secret and iv are both straight out of the database

更新

我现在在这里改变了我的目标并使用了哈希,这可能是正确的方法。因此,在 Node 服务中,我使用存储在数据库中的随机密钥创建 base64 标头和有效负载的 SHA256 哈希。然后在 PHP 服务中我做同样的事情并比较哈希值。这是一个更好的方法,我以前应该采取的。

但是仍然存在一个问题,如何在 Node 中可靠地加密字符串并在 PHP 中解密?

【问题讨论】:

  • 必须有正确实现规范的库。两边都检查了吗?
  • 有一些库,但对于应该相当简单的内容来说,它们似乎有点矫枉过正。
  • 您的应用程序中的示例明文、密钥、iv 和密文怎么样,以便我们检查您的工作?你也是 FITH CoinOp,还是其他人?
  • 问题可能出在任何地方,例如密钥和 IV 的编码。您应该提供一些示例输入和输出。另外,你为什么使用 AES-CBC 作为一种 MAC?通过这样做,您可能会通过填充预言攻击为攻击者提供解密预言。您应该使用适当的 MAC,例如 HMAC。
  • 我的印象是,如果你想在 Node 和 PHP 之间进行 2 路加密,那么 aes-128-cbc 是最可靠的算法。但是是的,最后使用哈希更有意义。

标签: php node.js encryption jwt


【解决方案1】:

有一些库,但对于应该相当简单的内容来说,它们似乎有点矫枉过正。

它应该相当简单,但显然不是。

对于密码学,您要么对它足够了解以从头开始自己实施算法,要么您不尝试,因为出错的风险太大。当你犯了一个错误,就像你在没有任何工作时所做的那样已经够糟糕了,但当它看起来有效但很弱并且容易受到一些你没有想到的攻击时,情况就更糟了。

如果您非常重视安全性,那么请使用正确的工具来完成这项工作。在 Node 中你有:

many more

对于 PHP,你有:

请参阅https://jwt.io/ 了解更多信息、更多工具和更多教程。

如果您想在不使用库的情况下自己学习如何正确执行此操作,请阅读这些库的源代码 - 它们都是开源、免费软件。

【讨论】:

  • 我使用 JWT 的事实并不那么重要。我更多地问在节点中加密字符串并在 PHP 中解密它的最佳方法是什么?我希望不需要一个库,因为这两种语言都有加密和解密方法。我不是在谈论自己创建一种新的加密形式,只是使用已经可用的方法。
猜你喜欢
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多