草庐IT

php - Mcrypt js 加密值不同于 PHP mcrypt/Mcrypt JS 解密生成的值不适用于 UTF-8 字符

coder 2024-01-03 原文

我一直在尝试在服务器端、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 库中使用了以下私有(private)变量。

 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 端解密。


*链接:*

Mcrypt JS library

Base64 JS library

最佳答案

主要问题似乎是您的 string_encryptstring_decrypt PHP 函数无法访问 $key 变量,因此对于加密 key mcrypt_encrypt 使用 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0。参见 this question寻求解释。 PHP 应该报告 key 未定义的通知,您是否关闭了错误报告?从加密函数中回显 key 以确认这一点。

另一个问题是 Mcrypt JS 库中的错误。如果 key 长度小于 32 字节,这个库用 \0 填充加密 key ,问题是这不是 PHP mcrypt_encrypt 功能垫键。 mcrypt_encrypt 函数将 key 填充到最接近的有效 key 长度(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>

一些注意事项...

  1. 您不能修剪 string_encrypt 函数的输出。这将导致删除前导或尾随零,从而使您无法解密输出。
  2. ECB 模式不安全,您真的不应该使用它。 CBC 是必经之路。 CBC 确实需要一个 IV,并且加密和解密的 IV 必须相同。
  3. Javascript 加密出于各种原因并不安全,考虑到您对它的使用,任何人都可以简单地查看页面源代码或调试正在运行的 javascript 以获取加密 key 。阅读 ntoskrnl 在您的问题评论中发布的链接。

更新:

您的 Base64 编码问题发生是因为 library you're using不适用于二进制数据。对于 Base64 javascript 库来说,这是一个相当普遍的问题。我建议使用 this library相反。

对于javascript解密时尾部的字符,需要修剪解密后的输出。您在 PHP string_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]

关于php - Mcrypt js 加密值不同于 PHP mcrypt/Mcrypt JS 解密生成的值不适用于 UTF-8 字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18786025/

有关php - Mcrypt js 加密值不同于 PHP mcrypt/Mcrypt JS 解密生成的值不适用于 UTF-8 字符的更多相关文章

  1. ruby - 使用 AES 的 Rails 加密,过于复杂 - 2

    我在加密来self正在使用的第三方供应商的值时遇到问题。他们的指令如下:1)Converttheencryptionpasswordtoabytearray.2)Convertthevaluetobeencryptedtoabytearray.3)Theentirelengthofthearrayisinsertedasthefirstfourbytesontothefrontofthefirstblockoftheresultantbytearraybeforeencryption.4)EncryptthevalueusingAESwith:1.256-bitkeysize,2.25

  2. Ruby 等同于 Sphinx 文档生成器? - 2

    Ruby有一些不错的文档生成器,例如Yard、rDoc,甚至Glyph。问题是Sphinx可以做网站、PDF、epub、LaTex等。它在重组文本中完成所有这些事情。在Ruby世界中有替​​代方案吗?也许是程序的组合?如果我也能使用Markdown就更好了。 最佳答案 自1.0版以来,Sphinx有了“域”的概念,它是从Python和/或C以外的语言标记代码实体(如方法调用、对象、函数等)的方法。有一个rubydomain,所以你可以只使用Sphinx本身。您唯一会缺少的(我认为)是Sphinx使用autodoc从源代码自动创建文档

  3. ruby - 如何使用私钥加密完全加密 Ruby 中的数据? - 2

    首先,关于我们系统的一些信息,它基本上是建筑行业的电子招标解决方案。所以:列表项我们的系统有多家公司每个公司都有多个用户每家公司可以创建多个拍卖然后其他公司可以为可用的拍卖提交他们的出价。一个出价包含数百或数千个单独的项目,我们只需要加密这些记录的“价格”部分。我们面临的问题是,我们的大客户不希望我们知道投标价格,至少在投标过程中是这样,这是完全可以理解的。现在,我们只是通过对称加密对价格进行加密,因此即使价格在数据库中有效加密,他们担心的是我们拥有解密价格的key。因此,我们正在研究某种形式的公钥加密系统。以下是我们对解决方案的初步想法:当一家公司注册时,我们会使用OpenSSL为其

  4. ruby-on-rails - 我如何比较 'Bcrypt' Gem解密的密码和加密的密码 - 2

    我正在尝试对某些帖子的评论使用简单的身份验证。用户使用即时ID和密码输入评论我使用“bcrypt”gem将密码存储在数据库中。在comments_controller.rb中像这样@comment=Comment.new(comment_params)bcrypted_pwd=BCrypt::Password.create(@comment.user_pwd)@comment.user_pwd=bcrypted_pwd当用户想要删除他们的评论时,我使用data-confirm-modalgem来确认数据在这部分,我必须解密用户输入的密码以与数据库中的加密密码进行比较我怎样才能解密密码,

  5. ruby-on-rails - Rails 导入 CSV 错误 : invalid byte sequence in UTF-8 - 2

    尝试在我的Rails应用程序中导入CSV文件时,出现错误UTF-8中的无效字节序列。一切正常,直到我添加了一个gsub方法来将其中一个CSV列与我的数据库中的一个字段进行比较。当我导入CSV文件时,我想检查每一行的地址是否包含在特定客户端的不同地址数组中。我有一个带有alt_addresses属性的客户端模型,其中包含客户端地址的几种不同可能格式。然后我有一个引用模型(如果您熟悉本地SEO,您就会知道这个术语)。引用模型没有地址字段,但它有一个nap_correct?字段(NAP代表“姓名”、“地址”、“电话号码”)。如果CSV行的名称、地址和电话号码与我在该客户的数据库中拥有的相同,

  6. ruby - 如何在Elixir中使用AES CBC 128进行加密和解密 - 2

    我在Rails中有一个具有以下方法的应用程序,该方法可以加密和解密文本并与Java客户端通信。defencrypt(string,key)cipher=OpenSSL::Cipher::AES.new(128,:CBC)cipher.encryptcipher.padding=1cipher.key=hex_to_bin(Digest::SHA1.hexdigest(key)[0..32])cipher_text=cipher.update(string)cipher_textexcenddefhex_to_bin(str)[str].pack"H*"enddefbin_to_hex(

  7. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  8. ruby-on-rails - 如何防止错误 "code converter not found (UTF-8)"? - 2

    我在生产环境(CentOS5.6)中遇到此错误,但在开发环境(Ubuntu11.04)中运行良好。在这两种环境中,该应用程序都使用Ruby1.9.3和Rails3.0.9,并由passenger和nginx提供服务。我的Mechanizegem版本是2.3。未找到代码转换器(UTF-8)此代码的最后一行触发它:mech=Mechanize.newpage=mech.get("http://myurl.com/login.php?login_name=a&password=b")form=page.form_with(:name=>"loginForm")form.field_with(

  9. Ruby:模糊测试所有 unicode 字符(UTF8/编码/字符串操作) - 2

    我无法遍历整个unicode字符范围。我到处找...我正在构建一个模糊器,并希望将所有unicode字符(一次一个)嵌入到一个url中。例如:http://www.example.com?a=\uff1c我知道有一些内置工具,但我需要更多的灵active。如果我能像下面那样做:"\u"+"ff1c"那就太好了。这是我得到的最接近的:char="\u0000"...#withiniterationchar.succ!...但在字符"\u0039"之后,即数字9,我将得到"10"而不是":" 最佳答案 您可以使用pack将数字转换为UT

  10. ruby , `match' : invalid byte sequence in UTF-8 - 2

    我对UTF-8编码有一些问题。我在这里阅读了一些帖子,但它仍然无法正常工作。这是我的代码:#!/bin/envruby#encoding:utf-8defdeterminefile=File.open("/home/lala.txt")file.eachdo|line|puts(line)type=line.match(/DOG/)puts('aaaaa')iftype!=nilputs(type[0])breakendendend这是我文件的前3行:;?lalalalal60000065535-1362490443-0000006334-0000018467-0000000041en

随机推荐