Criptografia C # para Decodificação do PHP

Eu estou tentando criptografar alguns dados (cookie) em c # e, em seguida, descriptografá-lo em PHP. Eu escolhi usar a criptografia Rijndael. Eu quase consegui trabalhar, exceto que apenas parte do texto foi decifrado! Comecei a trabalhar com este exemplo:Descriptografar string criptografada em PHP em c #

Aqui está o texto (JSON) que estou criptografando (informações confidenciais removidas):

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

Então, eu faço o login no aplicativo C # que cria / codifica o cookie a partir da chave armazenada e IV e, em seguida, redireciona para o aplicativo PHP que deve descriptografar / ler o cookie. Quando decifro o cookie, sai assim:

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

ATUALIZAR: eu comecei um pouco mais longe e este é agora o resultado

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

Como você pode ver, ele começa a descriptografá-lo, mas fica confuso ...

Quando descriptografar a string, ela sai correta (com padding, que tenho uma função para remover padding), mas se eu alterar a string de teste por um caractere, recebo lixo novamente:

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

Aqui está o código c # que eu uso para gerar a chave aleatória e IV:

ATUALIZAR: Estou usando apenas a chave estática / IV por agora, aqui estão elas:

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

 Em seguida, salve a chave e IV em um banco de dados a ser recuperado posteriormente para codificação / decodificação.

Esta é a classe de criptografia completa:

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);
        }
    }

Aqui está o código PHP que estou usando para descriptografar os dados:

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

Eu estou um pouco inseguro sobre esta parte, porque todo o código de exemplo que eu vi simplesmente passa a string codificada em base64 diretamente para o decodificador, mas no meu exemplo, eu tenho que base64_decode-lo antes de passá-lo caso contrário recebo o erro que a chave e o IV não têm o tamanho correto.

ATUALIZAR: Estou usando chaves ASCII no formato necessário pelo PHP. Se eu gerar chaves da classe RijndaelManaged, elas não funcionarão no lado do PHP, mas eu posso usar chaves que funcionam no lado do PHP e usá-las no lado RijndaelManaged do C #.

Por favor, deixe-me saber se deixei de fora qualquer informação pertinente. TIA!

questionAnswers(2)

yourAnswerToTheQuestion