【问题标题】:PHP - Decrypt Encrypted String From Node.jsPHP - 从 Node.js 解密加密字符串
【发布时间】:2019-06-29 16:48:35
【问题描述】:

我想使用传递给服务器的 PHP 解密一个加密字符串(在 Nodejs 中加密)。

我找到了完美的 Nodejs 加密/解密库:Cryptr。我在我的 JavaScript 文件中创建了一个连接,向我的服务器发送了一个包含加密字符串的请求。

现在基本上我想解密那个字符串。

看看Cryptr source,似乎他们使用aes-256-ctr作为算法方法,sha256作为加密方法。

我的 Nodejs:https://runkit.com/embed/keu82yjhwyxj

加密字符串:1d510024ad0a5da624b76a2be72022bff3aaadfe8ac5e0b6c178b00333

然后我在 PHP 中执行此操作:

<?php
$encrypted = "1d510024ad0a5da624b76a2be72022bff3aaadfe8ac5e0b6c178b00333";
$algorithm = "aes-256-ctr";
$secret_key = "myTotalySecretKey"; 
$iv = "";

$decrypted_data = openssl_decrypt(pack('H*', $encrypted), $algorithm, $secret_key, OPENSSL_RAW_DATA, $iv);
echo $decrypted_data;

但由于 IV 是在 Cryptr 中随机生成的,我如何在 PHP 中生成它?

如何使用 PHP 解密 Cryptr 加密字符串,使其返回“我喜欢披萨!”?


编辑:

改为 pack('H*', $encrypted) 尝试仅使用 $encrypted。此外,您只需要解密的数据、方法和密钥。

<?php
$encrypted = "1d510024ad0a5da624b76a2be72022bff3aaadfe8ac5e0b6c178b00333";
$algorithm = "aes-256-ctr";
$secret_key = "myTotalySecretKey";

$decrypted_data = openssl_decrypt($encrypted, $algorithm, $secret_key);
echo $decrypted_data;

【问题讨论】:

  • 您的代码是否有效或有什么问题?不清楚
  • @SilvioCro 它不起作用。问题:我不确定如何解密由 Nodejs 的 Cryptr 依赖项生成的 PHP 字符串。
  • 我未删除答案。

标签: php node.js encryption


【解决方案1】:

请勿使用 CRYPTR。 这是不安全的。 I have opened an issue 与开发人员一起,虽然我不确定如何在不完全重写模块的情况下修复它。

Cryptr 使用 CTR 加密模式。此模式专为特定用例而设计,并且能抵抗延展性攻击。如果已知任何加密消息的内容,则可以将该消息转换为任何其他消息。例如,给定用法示例中的加密字符串:

const cryptr = new Cryptr('myTotalySecretKey');

const encryptedString = cryptr.encrypt('bacon');
const decryptedString = cryptr.decrypt(encryptedString);

console.log(encryptedString); // "bcb23b81c4839d06644792878e569de4f251f08007"

(请注意,加密字符串的长度甚至与模块用法中显示的长度不同。这在他们的文档中是一个明显的错误。)

在不知道密钥的情况下,可以修改此字符串以使其解密为“hello”:

var tmp = Buffer.from(encryptedString, "hex");
var b1 = Buffer.from("bacon"), b2 = Buffer.from("hello");
for (var i = 0; i < b1.length; i++) {
    tmp[i + 16] ^= b1[i] ^ b2[i];
}
var ep = tmp.toString("hex");
console.log(ep); // "bcb23b81c4839d06644792878e569de4f855ff8306"

确实:

var dp = cryptr.decrypt(ep);
console.log(dp); // "hello"

从密码学的角度来看,这确实是一件大事。攻击者刚刚修改了传输中的加密消息,而您无法检测到它。

不要使用这个模块。如果需要便携式加密,请使用the Sodium library; Node 和 PHP 都有可用的绑定。

【讨论】:

  • 我明白了,谢谢你的警告。加密的数据基本上是API中需要的用户名,因此API不能被利用。我一直在寻找一个好的解决方案,但找不到一个。您提到的库,我可以从 Nodejs 传递加密信息并在 PHP 中解密吗?
  • 如果您正在实施通过 HTTP 运行的 API,您应该使用 HTTPS(并且仅使用 HTTPS)来保护通信。没有理由在此之上使用其他任何东西。
  • 那么通过 HTTPS 发送 GET 请求 api.php?username=Test&amp;removePoints=100(删除用户余额)是 100% 安全的吗?
  • 不,POST 请求
  • 知道了。但是如果其他人有 API url,他们可能会发送一个虚假的 POST 请求,并拥有该 API,例如,从其他用户那里删除积分,对吗?
【解决方案2】:

您需要在传递消息和安全密钥时传递 IV。

所以我做了一点测试

$encrypted = openssl_encrypt("test", "aes-256-ctr", "123", 0, "aaaaaaaaaaaaaaaa");
$algorithm = "aes-256-ctr";
$secret_key = "123"; 
$iv = "";

$decrypted_data = openssl_decrypt($encrypted, $algorithm, $secret_key, 0, "aaaaaaaaaaaaaaaa");
echo $decrypted_data;

而且它有效。 是的,它是随机生成的,但您可以并且必须将其(作为加密消息)传递给服务器。

我不确定 IV 参数的用途是什么,但如果 IV 参数为空,PHP 会发出警告。

我刚刚在 Cryptr 的 GitHub 页面上找到了这个。它说:

iv 随机生成并添加到结果中

【讨论】:

  • 我已经编辑了我的问题,并根据这个答案添加了编辑后的 ​​PHP 代码。它似乎没有解密字符串。
  • 感谢您的示例。由于某种原因,我仍然无法真正让它与我的问题中的示例一起使用。您可以尝试使用问题中的代码吗?
  • 从客户端向服务器发送加密消息和密钥的代码在哪里?
  • 在生成加密消息时不知道 IV,您无法对其进行解密。
  • 这基本上回答了我的问题。看来我的代码和这个加密库不适合我想要实现的目标。
猜你喜欢
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 2017-03-10
  • 2010-09-18
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
相关资源
最近更新 更多