用PHP加密,用Javascript解密(cryptojs)

用PHP加密,用Javascript解密(cryptojs),javascript,php,encryption,cryptojs,Javascript,Php,Encryption,Cryptojs,我的基本加密/解密有问题。我已经到处寻找了一个有效的例子,但还没有找到一个有效的例子 -我将用php加密,用cryptojs解密以获得一个小的安全层 <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"> <? $text = "this is the text here"; $key = "encryptionkey"; $msgEncrypted = mcrypt

我的基本加密/解密有问题。我已经到处寻找了一个有效的例子,但还没有找到一个有效的例子

-我将用php加密,用cryptojs解密以获得一个小的安全层

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js">
<?
$text = "this is the text here";
$key = "encryptionkey";

$msgEncrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
$msgBase64 = trim(base64_encode($msgEncrypted));

echo "<h2>PHP</h2>";
echo "<p>Encrypted:</p>";
echo $msgEncrypted;
echo "<p>Base64:</p>";
echo $msgBase64;
 ?>

<p>AES Decrypt</p>
<script> 
    var key = 'encryptionkey';
    var encrypted = "<?php echo $msgBase64 ?>";
    //tried  var base64decode = CryptoJS.enc.Base64.parse(encrypted); 
    var decrypted = CryptoJS.AES.decrypt(encrypted, key);
    console.log( decrypted.toString(CryptoJS.enc.Utf8) );
</script>

AES解密

var key='encryptionkey'; var=”; //尝试var base64decode=CryptoJS.enc.Base64.parse(加密); var decrypted=CryptoJS.AES.decrypt(加密,密钥); log(decrypted.toString(CryptoJS.enc.Utf8));

我遗漏了哪一步?

您使用的两个库试图容纳严格来说无效的输入。Rijndael需要16、24或32字节长的随机字节字符串。您可以提供一个13个字符的字符串。PHP库Mcrypt直接使用字符串(可能是utf8编码的)作为二进制输入,用于
Mcrypt\u RIJNDAEL\u 256
。另一方面,CryptoJS

此外,使用的加密算法甚至不匹配。Mcrypt在256位版本中使用很少实现的原始Rijndael变体,而CryptoJS实现了众所周知的Rijndael方案的AES256变体。不过,这两个版本(
MCRYPT_RIJNDAEL_128
和AES128)的128位版本是相同的

稍后您将面临的第三个问题是,Mcrypt还对加密的数据使用疯狂的填充方案。由于Rijndael是一种分组密码,它只能加密16、24或32字节的块(取决于变体-AES始终使用16字节块)。因此,必须对这些数据进行填充。Mcrypt以一种非内射的方式通过添加零来实现这一点。如果您只对字符串进行编码,这对您来说不会有太大的问题,因为utf8编码的字符串从不包含零字节,所以您可以将它们去掉()

解决所有这些问题的最简单方法是避免自己实现任何加密(在没有广泛知识的情况下,强烈建议不要这样做)。您是否可以改为通过https传输敏感信息,https将使用TLS(以前称为SSL)加密和验证通道

安全注意事项:此答案上的代码容易受到选定的密文攻击。看

下面是一个使用PHP加密字符串并使用CryptoJS解密的工作示例

在PHP方面:

使用MCRYPT_RIJNDAEL_128(而非256)与AES配对。这里的128是块大小,而不是键大小

也发送IV。你需要静脉注射来解密

$text = "this is the text here";
$key = "encryptionkey";

// Note: MCRYPT_RIJNDAEL_128 is compatible with AES (all key sizes)
$iv = random_bytes(16);

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);

echo "iv:".base64_encode($iv)."\n";
echo "ciphertext:".base64_encode($ciphertext)."\n";
以下是测试运行的示例输出:

iv:BMcOODpuQurUYGICmOqqbQ==
ciphertext:ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4=
重要:因为我们没有验证密文。另见:

在CryptoJS方面:

您的密钥只有13个ASCII可打印字符,非常弱。Mcrypt填充的使用字节将密钥设置为有效的密钥大小

IV转换为单词数组

我没有太多的运气将密文作为单词数组进行解密,因此我将其保留为Base64格式

CryptoJS = require("crypto-js")

// Mcrypt pads a short key with zero bytes
key = CryptoJS.enc.Utf8.parse('encryptionkey\u0000\u0000\u0000')

iv = CryptoJS.enc.Base64.parse('BMcOODpuQurUYGICmOqqbQ==')

// Keep the ciphertext in Base64 form
ciphertext = 'ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4='

/**
 * DANGER DANGER WILL ROBINSON! <== Stop editing my answer or I will delete it.
 *
 * This example code doesn't demonstrate AUTHENTICATED ENCRYPTION
 * and is therefore vulnerable to chosen-ciphertext attacks.
 *
 * NEVER USE THIS CODE TO PROTECT SENSITIVE DATA!
 */

// Mcrypt uses ZERO padding
plaintext = CryptoJS.AES.decrypt(ciphertext, key, { iv: iv, padding: CryptoJS.pad.ZeroPadding })

// I ran this in nodejs
process.stdout.write(CryptoJS.enc.Utf8.stringify(plaintext))
CryptoJS=require(“CryptoJS”)
//Mcrypt用零字节填充一个短键
key=CryptoJS.enc.Utf8.parse('encryptionkey\u0000\u0000\u0000')
iv=CryptoJS.enc.Base64.parse('bmcoodpuqruygicmoqqbq==')
//将密文保持为Base64格式
密文='ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4='
/**

*危险,危险,鲁宾逊 我也需要同样的东西,并且我编写了一个简短的库,它适用于支持openssl的CryptoJS 3.x和PHP。希望这有帮助,这里有源代码和示例文件

PHP库 示例Javascript PHP示例
不要太过拘泥于编码,只需使用base64解码器即可

关于php代码:

$encrypt_val=base64_encode("value");
在js上:

var my_orignal_val = window.atob(passed_val);

这足以满足您的要求。

谢谢!不幸的是,我没能让你的例子起作用。当我删除“padding:CryptoJS.pad.ZeroPadding”时,它几乎可以工作了——但是添加了“padding:CryptoJS.pad.ZeroPadding”���" 另外,我想知道如何更改示例中的encrpytion键“\u0000\u0000\u0000”是什么意思?如何确定需要多少?这是这里的文本在UTF-16中编码的是42个字节,加密时会填充到48个字节。这些额外的6个字节将在末尾显示为三个UTF-16字符,这将解释三个有趣的字符。尝试CryptoJS.pad.NoPadding,并查看最后这些字节的二进制值。它们都是0x00还是0x06?每个\u0000都在添加一个零字节0x00,如果字符串是UTF-16,则添加两个零字节。Mcrypt必须将密钥填充到16、24或32字节。如果是ASCII或UTF-8,则为16字节。如果是UTF-16,则为32字节。你应该用一把更结实的钥匙。选择一个16、24或32字节的密钥大小,并使用加密强随机数据进行加密。
MCRYPT_RAND
不是CSPRNG。您需要在CBC模式下对IVs进行CSPRNG。另外,你的答案更新可以从修订链接中看到。看起来不错。但是你为什么选择不使用IV/盐呢?顺便说一句,我想补充一句,你刚刚发布了这篇文章,真是太神奇了。。。这正是我想要的,因为Mcrypt是GPL,而OpenSSL是Apache/BSD@JSON我想让这个例子尽可能简短——它应该显示基本流程是如何工作的。我也不是密码专家,我不确定定制IV和定制salt应该有什么帮助。Salt和IV是存在的,并且总是不同的,因为Salt是随机生成的,而IV是由密码短语和随机Salt生成的。但是当你可以改进代码时,请在我的GIT repos上进行。@Brainhuong上面的代码有许可证吗?只是想确保万一我想把代码和我的其他东西一起分发。@php_coder_3809625 GPL v3-我会把它添加到GitHub repos自述中。你不是说第二段中的MCRYPT_RIJNDAEL_128吗?实际上,
var my_orignal_val=window.btoa(passed_val)
var encrypted = CryptoJS.AES.encrypt(JSON.stringify("value to encrypt"), "my passphrase", {format: CryptoJSAesJson}).toString();
var decrypted = JSON.parse(CryptoJS.AES.decrypt(encrypted, "my passphrase", {format: CryptoJSAesJson}).toString(CryptoJS.enc.Utf8));
$encrypted = cryptoJsAesEncrypt("my passphrase", "value to encrypt");
$decrypted = cryptoJsAesDecrypt("my passphrase", $encrypted);
$encrypt_val=base64_encode("value");
var my_orignal_val = window.atob(passed_val);