C#加密到解密PHP [英] C# Encryption to PHP Decryption

查看:580
本文介绍了C#加密到解密PHP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要加密在C#中的一些(饼干)的数据,然后在PHP解密。我选择使用Rijndael加密。我差点它的工作,惟独文本的一部分被解密!我开始从这个例子的工作:解密PHP在C#中的加密字符串

I'm trying to encrypt some (cookie) data in C# and then decrypt it in PHP. I have chosen to use Rijndael encryption. I've almost got it working, except only part of the text is decrypted! I started working from this example: Decrypt PHP encrypted string in C#

下面的文字,我加密(敏感信息已删除)(JSON):

Here's the text (JSON) that I am encrypting (sensitive information removed):

{"DisplayName":"xxx", "Username": "yyy", "EmailAddress":"zzz"}

所以,我登录到它创建/编码从存储密钥和IV的饼干,然后重定向到被认为解密/读取cookie的PHP应用程序的C#应用​​程序。当我解密的cookie,它出来是这样的:
<击>

So I login to the C# app which creates/encodes the cookie from stored Key and IV and then redirects to the PHP app which is supposed to decrypt/read the cookie. When I decrypt the cookie, it comes out like this:

{"DisplayName":"xxx","F�A ;��HP=D�������4��z����ť���k�#E���R�j�5�\�t. t�D��" 

更新:我已经得到了一点点进一步,这是现在的结果。

UPDATE: i've gotten a little bit further and this is now the result

string(96) "{"DisplayName":"xxx","Username":"yyy","EmailAddress"�)ق��-�J��k/VV-v� �9�B`7^" 

正如你所看到的,它开始解密它,但后来被搞砸...

As you can see, it starts decrypting it, but then gets messed up...

当解密字符串,它出来正确的(与填充,我有一个函数删除填充),但如果我一个字符改变测试字符串我再次得到垃圾:

When Decrypt the string it comes out correct (with padding, which I have a function to remove padding), but if I change the test string by one character I get garbage again:

B�nHL�Ek    �¿?�UΣlO����OЏ�M��NO/�f.M���Lƾ�CC�Y>F��~�qd�+

<击>下面是我用它来生成随机密钥和IV的C#代码:

更新:我只是用静态密钥/ IV现在,在这里,他们分别是:

UPDATE: I'm just using static key/IV for now, here they are:

Key: lkirwf897+22#bbtrm8814z5qq=498j5
IV: 741952hheeyy66#cs!9hjv887mxx7@8y

<击>

RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.BlockSize = 256;
symmetricKey.KeySize = 256;
symmetricKey.Padding = PaddingMode.Zeros;
symmetricKey.Mode = CipherMode.CBC;
string key = Convert.ToBase64String(symmetricKey.Key);
string IV = Convert.ToBase64String(symmetricKey.IV);




我那么关键和IV保存到数据库中检索。后来换编码/解码

I then save the key and IV to a database to be retrieved later for encoding/decoding.

这是完整的加密类:

public static class Encryption
    {
        public static string Encrypt(string prm_text_to_encrypt, string prm_key, string prm_iv)
        {
            var sToEncrypt = prm_text_to_encrypt;

            var rj = new RijndaelManaged()
            {
                Padding = PaddingMode.PKCS7,
                Mode = CipherMode.CBC,
                KeySize = 256,
                BlockSize = 256,
                //FeedbackSize = 256
            };

            var key = Encoding.ASCII.GetBytes(prm_key);
            var IV = Encoding.ASCII.GetBytes(prm_iv);
            //var key = Convert.FromBase64String(prm_key);
            //var IV = Convert.FromBase64String(prm_iv);

            var encryptor = rj.CreateEncryptor(key, IV);

            var msEncrypt = new MemoryStream();
            var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);

            var toEncrypt = Encoding.ASCII.GetBytes(sToEncrypt);

            csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
            csEncrypt.FlushFinalBlock();

            var encrypted = msEncrypt.ToArray();

            return (Convert.ToBase64String(encrypted));
        }

        public static string Decrypt(string prm_text_to_decrypt, string prm_key, string prm_iv)
        {

            var sEncryptedString = prm_text_to_decrypt;

            var rj = new RijndaelManaged()
            {
                Padding = PaddingMode.PKCS7,
                Mode = CipherMode.CBC,
                KeySize = 256,
                BlockSize = 256,
                //FeedbackSize = 256
            };

            var key = Encoding.ASCII.GetBytes(prm_key);
            var IV = Encoding.ASCII.GetBytes(prm_iv);
            //var key = Convert.FromBase64String(prm_key);
            //var IV = Convert.FromBase64String(prm_iv);

            var decryptor = rj.CreateDecryptor(key, IV);

            var sEncrypted = Convert.FromBase64String(sEncryptedString);

            var fromEncrypt = new byte[sEncrypted.Length];

            var msDecrypt = new MemoryStream(sEncrypted);
            var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);

            csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);

            return (Encoding.ASCII.GetString(fromEncrypt));
        }

        public static void GenerateKeyIV(out string key, out string IV)
        {
            var rj = new RijndaelManaged()
            {
                Padding = PaddingMode.PKCS7,
                Mode = CipherMode.CBC,
                KeySize = 256,
                BlockSize = 256,
                //FeedbackSize = 256
            };
            rj.GenerateKey();
            rj.GenerateIV();

            key = Convert.ToBase64String(rj.Key);
            IV = Convert.ToBase64String(rj.IV);
        }
    }

下面是我使用对数据进行解密的PHP代码

Here's the PHP code I am using to decrypt the data:

    function decryptRJ256($key,$iv,$string_to_decrypt)
{
    $string_to_decrypt = base64_decode($string_to_decrypt);
    $rtn = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $string_to_decrypt, MCRYPT_MODE_CBC, $iv);
    //$rtn = rtrim($rtn, "\0\4");
    $rtn = unpad($rtn);
    return($rtn);
}

function unpad($value)
{
    $blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
    //apply pkcs7 padding removal
    $packing = ord($value[strlen($value) - 1]);
    if($packing && $packing < $blockSize){
        for($P = strlen($value) - 1; $P >= strlen($value) - $packing; $P--){
            if(ord($value{$P}) != $packing){
                $packing = 0;
            }//end if
        }//end for
    }//end if 

    return substr($value, 0, strlen($value) - $packing); 
}

$ky = 'lkirwf897+22#bbtrm8814z5qq=498j5'; // 32 * 8 = 256 bit key
$iv = '741952hheeyy66#cs!9hjv887mxx7@8y'; // 32 * 8 = 256 bit iv

$enc = $_COOKIE["MyCookie"];

$dtext = decryptRJ256($ky, $iv, $enc);
var_dump($dtext);



<击>我有点不确定这部分,因为所有的示例代码我已经看到简单的传入直接编码字符串解密以base64,但在我的例子,我不得不BASE64_DECODE它之前,我通过它,否则我得到的错误,关键和IV是不正确的长度。

更新:我使用ASCII键由PHP所需要的格式。如果我生成他们没有在PHP端工作RijndaelManaged类键,但我可以用已知在PHP一边工作,并在RijndaelManaged的C#端使用它们的密钥。

UPDATE: I'm using ASCII keys in the format needed by PHP. If I generate keys from the RijndaelManaged class they dont work on the PHP side, but I can use keys that are known to work on PHP side and use them in the RijndaelManaged C# side.

请让我知道如果我离开了任何相关信息。 TIA!

Please let me know if I left out any pertinent information. TIA!

推荐答案

由于串被部分确定,但有乱码在结束它会提示加密内的填充问题其中预计256个字节确切的块数。我建议设置填充为 PKCS7 (PaddingMode.PKCS7)代替零C#的一侧PHP就会明白没有问题(因为它是默认模式上解析器)

Since the string is partially OK, but there is gibberish at the end it would suggest a padding problem within the encryption which expects exact blocks of 256 bytes. I suggest setting the padding as PKCS7 (PaddingMode.PKCS7) instead of Zeros on the C# side which PHP will understand without issues (as it's the default mode on that parser).

编辑:哎呀,我没有注意到,你有你的PHP以下内容:

Oops, I did not notice that you had the following in your PHP:

$enc = $_COOKIE["MyCookie"];

这是需要注意的。 PHP很可能没有得到加密的数据原样,并运行一些urldecode消毒。你应打印此变量以发现它实际上匹配的是什么从C#代码发送

This is the caveat. PHP is likely not getting the encrypted data as-is and is running some urldecode sanitizing. You should print this variable to see that it really matches what is being sent from the C# code.

EDIT2:

通过添加此从cookie转换的空白字符丢失+字符:

Convert the whitespaces to missing + characters from the cookie by adding this:

str_replace(' ', '+', $enc);

这篇关于C#加密到解密PHP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆