我一直在尝试在服务器端,PHP和客户端上都实现mcrypt加密/解密技术。我目前正在尝试将mcrypt.js
库用作:
<?php
$key = 'testtesttesttesttesttesttesttest';
function string_encrypt($string, $key) {
$crypted_text = mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
$key,
$string,
MCRYPT_MODE_ECB
);
return base64_encode($crypted_text);
}
function string_decrypt($encrypted_string, $key) {
$decrypted_text = mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$key,
base64_decode($encrypted_string),
MCRYPT_MODE_ECB
);
return trim($decrypted_text);
}
echo 'Provided Text: '.$test_str = 'This is test message.';
echo '<br />';
echo 'Encyrpted Value: '.$enc_str = string_encrypt($test_str, $key);
echo '<br />';
echo 'Decrypted Value: '.string_decrypt($enc_str, $key);
echo '<br />';
?>
<script src='rijndael.js'></script>
<script src='mcrypt.js'></script>
<script src='base64v1_0.js'></script>
<script lang='javascript'>
var enc_str = mcrypt.Encrypt('<?php echo $test_str ?>','');
enc_str = B64.encode(enc_str);
alert(enc_str);
// I don't get this same as encypted PHP text. i.e. $enc_str
var dec_str = B64.decode('<?php echo $enc_str ?>');
alert(mcrypt.Decrypt(dec_str,''));
// I don't get this same as decypted PHP text.
// i.e. string_decrypt($enc_str)
</script>
我在mcrypt.js库中使用了以下私有变量。
var cMode='ecb';
var cCipher='rijndael-256';
var cKey='testtesttesttesttesttesttesttest';
//I am providing the same key
正如我上面评论的enc_str
那样$enc_str
,为什么mcrypt.Decrypt('<?php echo $enc_str ?>', '')
不等于string_decrypt($enc_str, $key)
?为什么不等于?
更新的问题:
我尝试了base64编码/解码,甚至hex2bin / bin2hex来解析这些字符串,但是这两个产生了以下结果:
使用Hex2bin / Bin2hex
PHP结果:
Provided Text: This is test message.
Encyrpted Value: a51e970427ec8f666a5684cc1712ad03b29889cc10f4ccbf55733564d11c0386
Decrypted Value: This is test message.
JS结果:
Provided Text:This is test message.
Mcrypted value:¥'ìfjV̲ÌôÌ¿Us5dÑ
Encyrpted Value:a51e970427ec8f666a5684cc1712ad03b29889cc10f4ccbf55733564d11c0386
After Hex to Bin Text:¥'ìfjV̲ÌôÌ¿Us5dÑ
Decrypted Value:This is test message.�����������
/*These diamond with question mark is produced while decypting the value.*/
使用Base64编码/解码:
PHP结果:
Provided Text: This is test message.
Mcrypt encrypted value : ¥—'ìfjV„̲˜‰ÌôÌ¿Us5dц
/*
Here mcrypted value provided by JS and PHP is different
That is causing to produce different value at two ends
*/
Encyrpted Value: pR6XBCfsj2ZqVoTMFxKtA7KYicwQ9My/VXM1ZNEcA4Y=
Decrypted Value: This is test message.
JS结果:
Provided Text:This is test message.
Mcrypted value:¥'ìfjV̲ÌôÌ¿Us5dÑ
Encyrpted Value:wqUewpcEJ8Oswo9malbChMOMFxLCrQPCssKYwonDjBDDtMOMwr9VczVkw5EcA8KG
After Base64 Decode:¥'ìfjV̲ÌôÌ¿Us5dÑ���
Decrypted Value:This is test message.�����������bFaêF«+JéÓ!ÆÖ
在这两种情况下,UTf-8内容都无法在JS端解密。
*链接:*
主要问题似乎是您string_encrypt
和string_decrypt
PHP函数无权访问该$key
变量,因此对于加密密钥而言,mcrypt_encrypt
它使用\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
。请参阅此问题以获取解释。PHP应该报告key
未定义的通知,也许您已关闭错误报告?从加密功能内部回显密钥以确认这一点。
另一个问题是Mcrypt JS库中的错误。\0
如果密钥长度小于32字节,该库将使用加密密钥填充密钥,问题是这不是PHPmcrypt_encrypt
函数填充密钥的方式。该mcrypt_encrypt
功能将密钥填充到最接近的有效密钥长度(16、24或32个字节)。mcrypt.js中的问题在第63和64行,请对此进行更改:
if(key.length<32)
key+=Array(33-key.length).join(String.fromCharCode(0));
对此:
if(key.length<16)
key+=Array(17-key.length).join(String.fromCharCode(0));
else if(key.length<24 && key.length>16)
key+=Array(25-key.length).join(String.fromCharCode(0));
else if(key.length<32 && key.length>24)
key+=Array(33-key.length).join(String.fromCharCode(0));
现在我们可以确认修复了...
PHP:
function string_encrypt($string) {
$crypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, "", $string, MCRYPT_MODE_ECB);
return $crypted_text;
}
$test_str = "This is test message to be encrypted.";
$enc_str = string_encrypt($test_str);
echo bin2hex($enc_str);
Output:
f98fca4ddc4c10d6cd47df56b081b78566ee4facbcf2254b46f7809d9b255529d2078f28b150e802d72818be1888536fac6219f6ce7b9d9332a24afa09288f0e
Javascript:
function toHex(str) {
var hex = '';
for(var i=0;i<str.length;i++) {
var val = ''+str.charCodeAt(i).toString(16);
if(val.length == 1)
hex += '0'+val;
else
hex += val;
}
return hex;
}
var enc_str = mcrypt.Encrypt("This is test message to be encrypted.", "", "", "rijndael-256", "ecb");
alert(toHex(enc_str));
Output:
f98fca4ddc4c10d6cd47df56b081b78566ee4facbcf2254b46f7809d9b255529d2078f28b150e802d72818be1888536fac6219f6ce7b9d9332a24afa09288f0e
最后,所有这些加密功能都将二进制文件作为输出。在大多数情况下,二进制文件不能以纯文本形式写入,而不会损坏数据。要解决此问题,请将二进制文件编码为Hex或Base64,然后在尝试解密之前对其进行解码。
所以要让一切正常工作...
<?php
$key = 'testtesttesttesttesttesttesttest';
function string_encrypt($string, $key) {
$crypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_ECB);
return $crypted_text;
}
function string_decrypt($encrypted_string, $key) {
$decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted_string, MCRYPT_MODE_ECB);
return trim($decrypted_text);
}
echo $test_str = 'This is test message to be encrypted.'; echo '<br />';
$enc_str = string_encrypt($test_str, $key);
echo bin2hex($enc_str); echo '<br />';
echo string_decrypt($enc_str, $key); echo '<br />';
?>
<script src='rijndael.js'></script>
<script src='mcrypt.js'></script>
<script lang='javascript'>
function toHex(str) {
var hex = '';
for(var i=0;i<str.length;i++) {
var val = ''+str.charCodeAt(i).toString(16);
if(val.length == 1)
hex += '0'+val;
else
hex += val;
}
return hex;
}
function hexToString (hex) {
var str = '';
for (var i=0; i<hex.length; i+=2) {
str += ''+String.fromCharCode(parseInt(hex.charAt(i)+hex.charAt(i+1), 16));
}
return str;
}
var enc_str = mcrypt.Encrypt('<?php echo $test_str ?>', '', 'testtesttesttesttesttesttesttest', 'rijndael-256', 'ecb');
alert(toHex(enc_str));
alert(mcrypt.Decrypt(hexToString('<?php echo bin2Hex($enc_str) ?>'), '', 'testtesttesttesttesttesttesttest', 'rijndael-256', 'ecb').replace(/\x00+$/g, ''));
</script>
还有一些注意事项...
trim
输出string_encrypt
函数。这将导致删除前导零或尾随零,这将使您无法解密输出。更新:
发生Base64编码问题是因为您使用的库不适用于二进制数据。对于Base64 javascript库,这是一个相当普遍的问题。我建议改用这个库。
至于�
使用javascript解密时的结尾字符,您需要修剪解密后的输出。您是在PHPstring_decrypt
方法中执行此操作,而不是在javascript中执行此操作。您可以通过\0
对字符串末尾的所有字符进行正则表达式替换来修剪解密的输出。
例子:
mcrypt.Decrypt(dec_str,'').replace(/\x00+$/g, '')
我本应该在原始帖子中包含此内容,但是\0
由于FF的警报框未显示这些字符,因此我没有注意到输出中的字符。对于那个很抱歉。
最后,我注意到Mcrypt JS库中的另一个错误。第41至47行:
var ciphers={ // block size, key size
"rijndael-128" :[ 16, 32],
"rijndael-192" :[ 24, 32],
"rijndael-256" :[ 32, 32],
"serpent" :[ 16, 32],
"twofish" :[ 16, 32],
}
请注意“ twofish”行末尾的逗号。Firefox和Chrome似乎并不介意,但是IE8会报告错误,并因此而无法加载mcrypt库。要解决问题更改:
"twofish" :[ 16, 32],
到:
"twofish" :[ 16, 32]
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句