2010-09-17 11 views
6

Heredé un código C# y necesito portarlo a PHP. Aquí está:¿En qué se diferencian los métodos de descifrado C# y PHP?

string key = "some key"; 
string strEncrypted = "some encrypted string"; 

byte[] hashedKey = new MD5CryptoServiceProvider().ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); 
byte[] strToDecrypt = Convert.FromBase64String(strEncrypted); 

TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider(); 
tripleDES.Key = hashedKey; 
tripleDES.Mode = CipherMode.ECB; 

string strDecrypted = UTF8Encoding.UTF8.GetString(tripleDES.CreateDecryptor().TransformFinalBlock(strToDecrypt, 0, strToDecrypt.Length)); 

Mi código PHP es el siguiente:

$key = 'some key'; 
$str_encrypted = 'some encrypted string'; 

$hashed_key = md5($key, TRUE); 
$str_to_decrypt = base64_decode($str_encrypted); 

// The IV isn't used for ECB, but it prevents a warning. 
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB), MCRYPT_RAND); 

$str_decrypted = mcrypt_decrypt(MCRYPT_TRIPLEDES, $hashed_key, $str_to_decrypt, MCRYPT_MODE_ECB, $iv); 

Pero los dos valores desencriptados no son lo mismo, y no puedo entender por qué. He leído muchas preguntas similares aquí y en otros lugares, pero ninguna de ellas parece explicar el problema que estoy teniendo.

Realmente agradecería cualquier ayuda para descifrar por qué la cadena de PHP descifrado no coincide con la cadena C# desencriptada.

+0

Eche un vistazo a los valores hash md5 de cada versión y vea si el problema está allí o después. También resuene las diversas matrices de bytes y juegue a detectar la diferencia. – colithium

+0

Gracias. Intenté eso primero, pero como no sabía mucho sobre C#, no estaba muy seguro de lo que estaba haciendo. Todo parecía estar en línea con el paso de descifrado, pero creo que no estoy 100% seguro. Sin embargo, hashedKey y strToDecrypt tienen las mismas longitudes que sus equivalentes PHP y los mismos caracteres imprimibles, por lo que parece bastante cierto que son los mismos. – matthewwithanm

Respuesta

2

fin he conseguido encontrar la respuesta en a comment on the Mcrypt page of the PHP manual:

Al utilizar 3DES entre PHP y C#, es de señalar que existen diferencias sutiles que si no se cumplen estrictamente, darán lugar a cifrar problema molesto/descifrar datos.

1), cuando se usa una clave de 16 bytes, php y C# generan una cadena de resultados totalmente diferente. parece que se requiere una clave de 24 bytes para que php y C# funcionen igual.

2), php no tiene una opción de "relleno", mientras que C# tiene 3 (?). Mi trabajo es agregar nulos, es decir, chr (0) al final de la cadena fuente para hacer su tamaño de 8 veces, mientras que en C#, se requiere PaddingMode.Zeros.

3) el tamaño de la clave tiene que ser un tiempo de 8, en php, para que funcione para C#.

El punto clave aquí es # 1. Como la clave utilizada es el resultado del hashing de md5, tendrá 16 bytes. Si, en cambio, uso una clave de 24 bytes para encriptar (y luego descifrar) todo es caprichoso.

Hasta ahora, no he podido encontrar una explicación de por qué teclas de 16 bytes producen un resultado diferente (o si hay una solución alternativa). Si tiene alguna información al respecto, ¡por favor comparta!

0

La clave C# está codificada en UTF8 antes de ser codificada con MD5. ¿Equivalente PHP probablemente no?

La salida C# también está codificada en UTF8 nuevamente.

No estoy muy familiarizado con PHP, pero al parecer la función que desea es utf8_encode, así que intenta actualizar su lado PHP para esto:

$key = 'some key'; 
$str_encrypted = 'some encrypted string'; 

$hashed_key = md5(utf8_encode($key), TRUE); 
$str_to_decrypt = base64_decode($str_encrypted); 

// The IV isn't used for ECB, but it prevents a warning. 
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB), MCRYPT_RAND); 

$str_decrypted = utf8_encode(mcrypt_decrypt(MCRYPT_TRIPLEDES, $hashed_key, $str_to_decrypt, MCRYPT_MODE_ECB, $iv)) 

Más allá de la diferencia de codificación UTF-8, no es garantizado (de la muestras que proporcionó) que str_encrypted está codificado en base64, en el lado C# o php.

Será mejor que siga los consejos de colithium y refleje las entradas para asegurarse de que todos sus datos de entrada coincidan en un nivel de byte.

+0

Sí, lo intenté, pero no afecta la salida. – matthewwithanm

+0

Casi siempre es un error de codificación en un lado. ¿El str_encrypted es definitivamente base64 codificado en ambos lados? – PaulG

+0

Sí, estoy usando exactamente la misma cadena, como se muestra en mi código de ejemplo. Misma entrada. – matthewwithanm

2

Es posible que desee opinar sobre este foro: http://forums.asp.net/t/1498290.aspx Al parecer, alguien el año pasado tuvo lo que parece ser exactamente el mismo problema.

Desde ese sitio, parece que las cosas C# deben codificarse con UTF-7. No UTF-8.

+0

Lo había visto, pero parecía como si lo de utf7 fuera una mala interpretación de cómo estaba funcionando. (En cualquier caso, parece que no funciona). – matthewwithanm

Cuestiones relacionadas