【问题标题】:Character encoding problem with decryption in PHP from C#从 C# 在 PHP 中解密的字符编码问题
【发布时间】:2011-07-14 13:43:39
【问题描述】:

我想我已经为你准备好了一份。

我有一些加密和解密字符串的 C# 代码。它看起来像这样:

    public static string EncryptString(String toEncrypt, String key)
    {
        Debug.WriteLine("Encrypting string: " + toEncrypt + "&key:" + key);
        Rijndael AES = Rijndael.Create();
        AES.KeySize = 128;
        AES.BlockSize = 128;
        AES.Mode = CipherMode.ECB;
        AES.Padding = PaddingMode.Zeros;
        MD5CryptoServiceProvider Hasher = new MD5CryptoServiceProvider();
        AES.Key = Hasher.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
        ICryptoTransform crypto = AES.CreateEncryptor(AES.Key, AES.IV); 
        byte[] txt = UTF8Encoding.UTF8.GetBytes( HEADER + toEncrypt);
        byte[] cipherText = crypto.TransformFinalBlock(txt, 0, txt.Length);
        return Convert.ToBase64String(cipherText);;
    }

当我在 C# 中加密或解密时,它就像一个魅力。在 php 中,我有一个如下所示的解密算法:

    if($msg!= "" && $key != "")
    {           
        $msg = parseMsg($msg);
        mcrypt_get_key_size ( MCRYPT_RIJNDAEL_128,  MCRYPT_MODE_ECB);
        $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, md5($key,true), base64_decode($msg),MCRYPT_MODE_ECB);      
        $headerLoc = strpos($decrypted,$correctHeader);         
        /*$decrypted = str_replace($correctHeader,"",$decrypted);
        for($x = 0; $x < 31; $x++)
        { 
            // an attempt at getting rid of control characters
            $decrypted = str_replace(chr($x),"",$decrypted);
        }*/
    }

注释掉的代码只是我为正确解码字符串所做的一些尝试。奇怪的是,有时它可以工作,有时甚至没有奇怪的字符。

例如:

带钥匙的 Herp Derp:红色作品

带有关键箭鱼的消息 Herp Derp 不起作用。

带有红色键的长消息不起作用。

没有关键剑鱼作品的消息。

这是否意味着消息密钥的长度是问题的一部分?

我已经确保消息和密钥在 php 和 C# 之间正确传输,这绝对是编码/解码的问题,基于吐出的垃圾我认为它与 UTF8 编码。我怀疑 填充模式 也是可能的罪魁祸首,有什么想法吗? 编辑:我没有注意到会 foobar 整个字符串的 1 或 2 个缺失的加号,对不起堆栈:\ *

有人知道怎么解决吗?

编辑 更改为密钥大小后,没有字符串起作用。 使用消息 Herp Derp 和密码 red,php 输出解密为 .�ʇ'y-�US2~h\�0�nAZ=�\2/�����|�a���R�`�/�� ����nY�7�.有谁知道那可能是什么字符编码?

比较 C# 中刚刚加密的密文的字节数和刚刚解密的 PHP,我得到了 C#

php 然后是 c#

这表明 mcrypt 调用不起作用,但我该如何解决?

编辑我已将打包模式更改为零,以尝试进一步简化问题。

已解决我会尽快发布解决方案。

【问题讨论】:

  • 不要使用ASCIIEncoding.UTF8 - 就像在说JpegEncoder.Png
  • 好吧,我可以责怪 MSFT 允许你这样做(通过子类显式引用基类的静态成员) - 但使用 Encoding.UTF8 将是明智得多。没有人强迫你使用ASCIIEncoding来创建令人困惑的代码。
  • 我无法在此处跟踪您 IV。
  • 你确定AES.KeySize = 256 吗?我认为您在双方都使用了 128 位哈希。
  • @Shane:老实说,我没有看它 - 因为我很确定问题将解码的原始二进制输出转换为通过执行 UTF-8 解码的字符串,我不知道 PHP 是如何处理的。

标签: c# php encryption utf-8 character-encoding


【解决方案1】:

前段时间遇到同样的问题,我的源被“某物”破坏,后来发现是字符串函数。 strpos 不是 UTF8 友好的,仅仅使用这个函数就会改变你的字符编码。作为解决方案,更换

 # this line I suspect is your culprit, the mere inclusion of it is corrupting your data
 # php defaulted string functions are ASCII, even if you change your character set PHP 
 # changes it to ASCII
 $headerLoc = strpos($decrypted,$correctHeader);

 #this works in most cases it did not work for me, it may work for you
 $headerLoc = mb_strpos($decrypted,$correctHeader,0,mb_detect_encoding($decrypted,"auto"));

关于我如何使用出色的 PHP UTF8 lib 解决此问题的博客文章。这个库所做的是将所有内容转换为 unicode,然后您可以从那里开始处理它。在这种情况下可能会很麻烦,因此请尝试执行上述操作。

Hack your own Utf8 ready String functions from Unicode

我发现 PHP 网站上的任何地方都没有提到这个有点烦人,我似乎记得过去有好几次这个问题。

资源

PHP mb_strpos | PHP strpos

【讨论】:

    【解决方案2】:

    不幸的是,base 64 编码的字符串有 +'s,当 url 编码没有被转义时已经存在的 +'s,当字符串被解码时,+'s 被替换为空格。 *post url-encode 机制有错误吗?我这样说是因为虽然空格被编码为 +,但如果你已经有 +,它不应该用转义字符编码吗? *

    无论哪种方式,我删除了 parseMsg 中的空格,结果是一个看起来非常相似的字符串,但与 php.ini 的输出不完全相同。输出的编码其实是没有问题的,到目前为止还没有必要进行utf8编码,虽然这可能是因为它没有经过足够严格的测试。

    【讨论】:

    • 好的,我已经花了很多时间试图解决 utf8 问题,我知道解决它的痛苦。就在几周前,我给自己设定了解决一些 PHP/utf8 异常的目标。我计算出来的是大多数字符串函数的返回值,比如 strpos 总是在 ascii 中。在正常情况下这很好,PHP 能够将其转回 utf8。当您开始使用双字节字符时,一切都会出错。很高兴你解决了。
    • 再次感谢您花时间尝试解决我的问题...我应该更加认真地对待调试的黄金法则之一,检查您的输入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 2019-11-17
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 2020-08-04
    • 2010-09-18
    相关资源
    最近更新 更多