metodos generar encriptar encriptacion ejemplo desencriptar codigo cifrado cesar c# php cookies encryption encryption-symmetric

generar - metodos de encriptacion c#



C#Cifrado a PHP descifrado (2)

Debido a que la cadena está parcialmente bien, pero al final hay errores que sugieren un problema de relleno dentro del cifrado que espera bloques exactos de 256 bytes. Sugiero configurar el relleno como PKCS7 (PaddingMode.PKCS7) en lugar de Ceros en el lado C # que PHP entenderá sin problemas (ya que es el modo predeterminado en ese analizador).

Edición: Vaya, no me di cuenta de que tenías lo siguiente en tu PHP:

$enc = $_COOKIE["MyCookie"];

Esta es la advertencia. Es probable que PHP no esté obteniendo los datos cifrados tal como están y está ejecutando un proceso de desinfección de urldecode. Debería imprimir esta variable para ver que realmente coincide con lo que se está enviando desde el código C #.

Edit2:

Convierta los espacios en blanco en caracteres faltantes de la cookie agregando esto:

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

Estoy tratando de cifrar algunos datos (de cookie) en C # y luego descifrarlos en PHP. He optado por utilizar el cifrado Rijndael. Casi lo tengo funcionando, ¡excepto que solo una parte del texto está descifrado! Comencé a trabajar desde este ejemplo: descifrar la cadena cifrada de PHP en C #

Aquí está el texto (JSON) que estoy cifrando (información confidencial eliminada):

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

Así que me conecto a la aplicación C # que crea / codifica la cookie a partir de Key y IV almacenados y luego redirige a la aplicación PHP que se supone descifra / lee la cookie. Cuando descifro la cookie, sale así:

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

ACTUALIZACIÓN : he ido un poco más lejos y este es ahora el resultado

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

Como puede ver, comienza a descifrarlo, pero luego se desordena ...

Cuando descifre la cadena, saldrá correctamente (con el relleno, que tengo una función para eliminar el relleno), pero si cambio la cadena de prueba por un carácter, obtengo basura nuevamente:

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

Aquí está el código c # que utilizo para generar la clave aleatoria y IV:

ACTUALIZACIÓN : solo estoy usando la clave estática / IV por ahora, aquí están:

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

Luego guardo la clave y el IV en una base de datos para recuperarlos más tarde para la codificación / decodificación.

Esta es la clase de encriptación 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); } }

Aquí está el código PHP que estoy usando para descifrar los datos:

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

Estoy un poco inseguro acerca de esta parte, porque todo el código de ejemplo que he visto simplemente pasa la cadena codificada en base64 directamente al descifrador, pero en mi ejemplo, tengo que descodificarla en base64 antes de pasarla, de lo contrario, aparece el error Que la clave y el IV no son de la longitud correcta.

ACTUALIZACIÓN : Estoy usando claves ASCII en el formato que necesita PHP. Si genero claves de la clase RijndaelManaged, no funcionan en el lado de PHP, pero puedo usar las claves que se sabe que funcionan en el lado de PHP y usarlas en el lado de C # de RijndaelManaged.

Por favor, hágame saber si omití cualquier información pertinente. TIA!


Para la posteridad estoy colocando la solución completa aquí.

Clase de cifrado C #

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

Fragmento de desencriptación de PHP

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