Javascript 用CryptoJS加密,用PHP解密

Javascript 用CryptoJS加密,用PHP解密,javascript,php,encryption,mcrypt,cryptojs,Javascript,Php,Encryption,Mcrypt,Cryptojs,在客户端(移动设备),我使用CryptoJS加密用户密码: var lib_crypt = require('aes'); $.loginButton.addEventListener('click', function(e){ var key = lib_crypt.CryptoJS.enc.Hex.parse('bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3'); var iv = lib_crypt.C

在客户端(移动设备),我使用CryptoJS加密用户密码:

var lib_crypt = require('aes');

$.loginButton.addEventListener('click', function(e){

var key = lib_crypt.CryptoJS.enc.Hex.parse('bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3');
var iv  = lib_crypt.CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');

var encrypted = lib_crypt.CryptoJS.AES.encrypt($.passwordInput.value, key, { iv: iv });

var password_base64 = encrypted.ciphertext.toString(lib_crypt.CryptoJS.enc.Base64); 
return password_base64; 
});
在服务器端,我想用mcrypt_decrypt对其进行解密:

function decryptPassword($password)
{
    $key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");
    $ciphertext_dec = base64_decode($password);
    $iv_dec = "101112131415161718191a1b1c1d1e1f";

    $ciphertext_dec = substr($ciphertext_dec, 16);
    $decryptedPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);

    return trim($decryptedPassword);
}

我使用相同的钥匙和IV,我做错了什么?

你在两边做的事情不一样

四, 您确实在CryptoJS中解析了IV,但忘了在PHP中解析:

$iv_dec = pack('H*', "101112131415161718191a1b1c1d1e1f");
要修复您的IV错误,您可能会注意到前16个字节是乱七八糟的。当静脉注射错误时就会发生这种情况。请注意,CryptoJS默认使用CBC模式,因此在解密过程中,IV仅对第一个块有影响删除此项:

$ciphertext_dec = substr($ciphertext_dec, 16);
衬垫 你可能注意到大多数明文都不正确。它们以一些奇怪的重复字符结尾。这是默认情况下在CryptoJS中应用的PKCS#7填充。您必须自己在PHP中删除填充。好消息是,Maarten Bodewes为此提供了一个合适的复制粘贴解决方案

trim()
可能适用于零填充,但在使用PKCS#7中定义的适当填充方案时则不适用。您可以完全删除
trim()
调用,因为它没有用处,可能会导致意外的纯文本,因为从开始到结束都会修剪零字节和空白。

您好

为了实现这一点,应该考虑使用键和iv,每个键和iv都有32个十六进制数字,我必须用我的东西来解决这个问题,下面就是它的方式

<!--
This reach.your.crypto.js is just a ficticious placeholder, 
that was used replaced by http://crypto-js.googlecode.com/svn/tags/3.1.2/build/,
which does not exist anymore,
which is the path to your CryptoJS library,
that can be downloaded through 
https://code.google.com/archive/p/crypto-js/downloads?page=1
-->
<script src="reach.your.crypto.js/rollups/aes.js">
</script>

<script type="text/javascript">
//The key and iv should be 32 hex digits each, any hex digits you want, 
//but it needs to be 32 on length each
var key = CryptoJS.enc.Hex.parse("0123456789abcdef0123456789abcdef");
var iv =  CryptoJS.enc.Hex.parse("abcdef9876543210abcdef9876543210");

/*
if you wish to have a more friendly key, you can convert letters to Hex this way:
var a = "D";
var hex_D = a.charCodeAt(0).toString(16);
just to mention,
if it were to binary, it would be:
var binary_D = a.charCodeAt(0).toString(2);
*/

var secret = "Hi, this will be seen uncrypted later on";

//crypted
var encrypted = CryptoJS.AES.encrypt(secret, key, {iv:iv});
//and the ciphertext put to base64
encrypted = encrypted.ciphertext.toString(CryptoJS.enc.Base64);    
//Assuming you have control on the server side, and know the key and iv hexes(we do),
//the encrypted var is all you need to pass through ajax,
//Let's follow with welcomed pure JS style, to reinforce one and other concept if needed
var xh = new XMLHttpRequest();
xh.open("POST", "decrypt_in_php.php", true);
xh.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xh.send("encrypted="+encodeURIComponent(encrypted));
</script>

//密钥和iv应分别为32个十六进制数字,任何您想要的十六进制数字,
//但每个长度必须为32
var key=CryptoJS.enc.Hex.parse(“0123456789abcdef0123456789abcdef”);
var iv=CryptoJS.enc.Hex.parse(“abcdef9876543210abcdef9876543210”);
/*
如果希望使用更友好的键,可以通过以下方式将字母转换为十六进制:
var a=“D”;
var hex_D=a.charCodeAt(0).toString(16);
更何况,,
如果它是二进制的,它将是:
var binary_D=a.charCodeAt(0).toString(2);
*/
var secret=“您好,这将在稍后被取消冻结”;
//隐秘的
var encrypted=CryptoJS.AES.encrypt(secret,key,{iv:iv});
//而密文被放到base64
加密=encrypted.ciphertext.toString(CryptoJS.enc.Base64);
//假设您在服务器端拥有控制权,并且知道密钥和iv hexes(我们知道),
//通过ajax只需加密var即可,
//让我们跟随欢迎的纯JS风格,如果需要的话,加强一个和另一个概念
var xh=新的XMLHttpRequest();
open(“POST”,“decrypt_in_php.php”,true);
setRequestHeader(“内容类型”、“应用程序/x-www-form-urlencoded”);
xh.send(“encrypted=“+encodeURIComponent(encrypted));
现在用PHP进行接收和解密

<?php
//Here we have the key and iv which we know, because we have just chosen them on the JS,
//the pack acts just like the parse Hex from JS

$key = pack("H*", "0123456789abcdef0123456789abcdef");
$iv =  pack("H*", "abcdef9876543210abcdef9876543210");

//Now we receive the encrypted from the post, we should decode it from base64,
$encrypted = base64_decode($_POST["encrypted"]);
$shown = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv);

echo $shown;
//Although the decrypted is shown, there may be needed to trim and str_replace some \r \n \x06 \x05, if there is not a better "trim" way to do it though
?>

有了这些,我们将返回“嗨,这将在稍后被看到”
:)

这是一个基于PHP的解决方案,使用
openssl\u decrypt

JavaScript部分(针对浏览器的NodeJS开发)-首先,使用
npm安装crypto-js
安装,然后使用js代码:

import aes from 'crypto-js/aes'
import encHex from 'crypto-js/enc-hex'
import padZeroPadding from 'crypto-js/pad-zeropadding'

// message to encrypt
let msg = "Hello world";

// the key and iv should be 32 hex digits each, any hex digits you want, but it needs to be 32 on length each
let key = encHex.parse("0123456789abcdef0123456789abcdef");
let iv =  encHex.parse("abcdef9876543210abcdef9876543210");

// encrypt the message
let encrypted = aes.encrypt(msg, key, {iv:iv, padding:padZeroPadding}).toString();

// and finally, send this "encrypted" string to your server
在PHP方面,您的代码如下所示:

// we use the same key and IV
$key = hex2bin("0123456789abcdef0123456789abcdef");
$iv =  hex2bin("abcdef9876543210abcdef9876543210");

// we receive the encrypted string from the post
$encrypted = $_POST['decrypt'];
$decrypted = openssl_decrypt($encrypted, 'AES-128-CBC', $key, OPENSSL_ZERO_PADDING, $iv);
// finally we trim to get our original string
$decrypted = trim($decrypted);

您可能希望添加您遇到的问题的示例。从代码来看,我目前的回答只是假设。感谢Artjom的快速响应,去除填充物最好使用什么:Maarten Bodewes或trim()的解决方案?谢谢
trim()。千万不要使用
trim()
,因为如果明文的开头或结尾包含零字节或空白,可能会导致不可预见的后果。如何将其改为使用字符串密钥?php v7.2上将删除mcrypt_decrypt函数。还有别的选择吗?怎么样?文件不存在。。。不要尝试共享这样的链接……事实上,我刚刚更新了它,感谢@pankajkumarHow@openssl\u encrypt,如果我们也必须在php端获得相同的加密文本。对我来说重要的是->密码长度。我尝试使用自定义密码,只是像“xyz”这样的字符串,但它不起作用。它必须像本例中那样进行密码编码。要测试的THXJSFIDLE示例: