C# Encryption to PHP Decryption

后端 未结 2 1649
难免孤独
难免孤独 2020-11-30 05:18

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 te

相关标签:
2条回答
  • 2020-11-30 05:26

    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).

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

    $enc = $_COOKIE["MyCookie"];
    

    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:

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

    str_replace(' ', '+', $enc);
    
    0 讨论(0)
  • 2020-11-30 05:34

    For posterity I'm placing the fully completed solution here.

    C# Encryption Class

    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,
            };
    
            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,
            };
    
            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,
            };
            rj.GenerateKey();
            rj.GenerateIV();
    
            key = Convert.ToBase64String(rj.Key);
            IV = Convert.ToBase64String(rj.IV);
        }
    }
    

    PHP Decryption Snippet

    <?php
    function decryptRJ256($key,$iv,$encrypted)
    {
        //PHP strips "+" and replaces with " ", but we need "+" so add it back in...
        $encrypted = str_replace(' ', '+', $encrypted);
    
        //get all the bits
        $key = base64_decode($key);
        $iv = base64_decode($iv);
        $encrypted = base64_decode($encrypted);
    
        $rtn = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CBC, $iv);
        $rtn = unpad($rtn);
        return($rtn);
    }
    
    //removes PKCS7 padding
    function unpad($value)
    {
        $blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC);
        $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;
                }
            }
        }
    
        return substr($value, 0, strlen($value) - $packing); 
    }
    ?>
    <pre>
    <?php
    
    $enc = $_COOKIE["MyCookie"];
    
    $ky = ""; //INSERT THE KEY GENERATED BY THE C# CLASS HERE
    $iv = ""; //INSERT THE IV GENERATED BY THE C# CLASS HERE
    
    $json_user = json_decode(decryptRJ256($ky, $iv, $enc), true);
    
    var_dump($json_user);
    
    ?>
    
    0 讨论(0)
提交回复
热议问题