简体   繁体   English

PHP-从Node.js解密加密的字符串

[英]PHP - Decrypt Encrypted String From Node.js

I want to decrypt a encrypted string (encrypted in Nodejs) using PHP passed to the server. 我想使用传递给服务器的PHP解密一个加密的字符串(在Nodejs中加密)。

I have found the perfect Nodejs encrypt/decrypt library: Cryptr . 我找到了完善的Nodejs加密/解密库: Cryptr I've created a connection in my JavaScript file sending a request to my server with the encrypted string in it. 我已经在JavaScript文件中创建了连接,并向其中的服务器发送了带有加密字符串的请求。

Now basically I want to decrypt that string. 现在基本上我想解密该字符串。

Taking a look at the Cryptr source , it seems they're using aes-256-ctr as algo method, and sha256 as encryption method. 看一下Cryptr源 ,似乎他们使用aes-256-ctr作为算法方法,并使用sha256作为加密方法。

My Nodejs: https://runkit.com/embed/keu82yjhwyxj 我的Node.js: https ://runkit.com/embed/keu82yjhwyxj

Encrypted string: 1d510024ad0a5da624b76a2be72022bff3aaadfe8ac5e0b6c178b00333 加密的字符串: 1d510024ad0a5da624b76a2be72022bff3aaadfe8ac5e0b6c178b00333

Then I do this in PHP: 然后,我在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;

But since the IV is randomly generated in Cryptr, how would I generate this in PHP? 但是由于IV是在Cryptr中随机生成的,我将如何在PHP中生成它?

How can I decrypt Cryptr encrypted strings using PHP, so it returns "I love pizza!"? 如何使用PHP解密Cryptr加密的字符串,因此返回“我爱披萨!”?


Edit: 编辑:

Instead pack('H*', $encrypted) try with $encrypted only. 相反,pack('H *',$ encrypted)仅尝试$ encrypted。 Also, you need only data, method and key for decryption. 另外,您只需要数据,方法和密钥即可解密。

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

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

DO NOT USE CRYPTR. 请勿使用CRYPTR。 It is insecure. 这是不安全的。 I have opened an issue with the developer, although I'm not sure how it can be fixed without a complete rewrite of the module. 尽管我不确定在不完全重写模块的情况下如何解决该问题 ,但我已经向开发人员提出了一个问题

Cryptr uses the CTR encryption mode. Cryptr使用CTR加密模式。 This mode is designed for specific use cases, and is not resistant to malleability attacks. 此模式是针对特定用例设计的,并且不能抵抗延展性攻击。 If the contents of any encrypted message are known, it is possible to transform that message into any other message. 如果知道任何加密消息的内容,则可以将该消息转换为任何其他消息。 For example, given the encrypted string from the usage sample: 例如,给定用法样本中的加密字符串:

const cryptr = new Cryptr('myTotalySecretKey');

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

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

(Note that the encrypted string isn't even the same length as what is shown in the module usage. This is an apparent error in their documentation.) (请注意,加密的字符串的长度甚至与模块用法中显示的长度不同。这是他们文档中的明显错误。)

Without knowledge of the key, it is possible to modify this string to make it decrypt to "hello": 在不知道密钥的情况下,可以修改此字符串以使其解密为“ 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"

And indeed: 确实:

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

This is a really big deal from a cryptographic perspective. 从加密的角度来看,这确实是一件大事。 An attacker has just modified an encrypted message in transit, and you have no way of detecting it. 攻击者刚刚修改了传输中的加密邮件,因此您无法检测到它。

Don't use this module. 不要使用此模块。 If you need portable encryption, use the Sodium library ; 如果您需要便携式加密,请使用Sodium库 there are bindings available for both Node and PHP. 有Node和PHP可用的绑定。

You need to pass IV as you pass message and security key. 在传递消息和安全密钥时,您需要传递IV。

So I did little test 所以我没有做任何测试

$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;

And it Works. 而且有效。 Yes, it's randomly generated, but you can and have to pass it(as encrypted message) to the server. 是的,它是随机生成的,但是您可以并且必须将其(作为加密消息)传递到服务器。

I'm not sure what is the purpose of IV parameter but PHP gives you warning if IV param is empty. 我不确定IV参数的目的是什么,但是如果IV参数为空,PHP会警告您。

I just found this on GitHub page for Cryptr. 我刚刚在GitHub页面上找到了Cryptr。 It says: 它说:

The iv is randomly generated and prepended to the result iv是随机生成的,并放在结果的前面

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM