2010-12-01 19 views
18

Actualmente estoy teniendo un problema al descifrar un mensaje cifrado por php mcrypt. código El php es la siguiente:Cifrado/descifrado multiplataforma (php a C# .NET) con Rijndael

<?php 
    //$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
    $iv = "45287112549354892144548565456541"; 
    $key = "anjueolkdiwpoida"; 
    $text = "This is my encrypted message"; 
    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv); 
    $crypttext = urlencode($crypttext); 
    $crypttext64=base64_encode($crypttext); 
    print($crypttext64) . "\n<br/>"; 
?> 

El mensaje que el cifrado se envía entonces a una plataforma ASP.NET (C#). Sin embargo, tengo problemas para mantener el orden de descifrado (decodificación de base64 a urldecode). El código que tenía en ASP.NET es como la siguiente (iv y la clave es el mismo que en php):

public string Decode(string str) 
{ 
    byte[] decbuff = Convert.FromBase64String(str); 
    return System.Text.Encoding.UTF8.GetString(decbuff); 
} 

static public String DecryptRJ256(string cypher, string KeyString, string IVString) 
{ 

    string sRet = ""; 
    RijndaelManaged rj = new RijndaelManaged(); 
    UTF8Encoding encoding = new UTF8Encoding(); 


    try 
    { 
     //byte[] message = Convert.FromBase64String(cypher); 
     byte[] message = encoding.GetBytes(cypher); 

     byte[] Key = encoding.GetBytes(KeyString); 
     byte[] IV = encoding.GetBytes(IVString); 

     rj.Padding = PaddingMode.Zeros; 
     rj.Mode = CipherMode.CBC; 
     rj.KeySize = 256; 
     rj.BlockSize = 256; 
     rj.Key = Key; 
     rj.IV = IV; 
     MemoryStream ms = new MemoryStream(message); 

     using (CryptoStream cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read)) 
     { 
      using (StreamReader sr = new StreamReader(cs)) 
      { 
       sRet = sr.ReadToEnd(); 
      } 
     } 

    } 
    finally 
    { 
     rj.Clear(); 
    } 

    return sRet; 


} 

string temp = DecryptRJ256(Server.UrlDecode(Decode(cypher)), keyString, ivString); 

El problema que estoy teniendo es que después de que recibimos el mensaje cifrado de php, Convertí en byte [] y luego convertido de nuevo a cadena codificada UTF8 para que pueda urldecode it. luego introduzco el resultado en la función donde convertí la cadena nuevamente en byte [] y la ejecuté a través del proceso de descifrado. Sin embargo, no puedo obtener el resultado deseado ... ¿alguna idea?

Gracias de antemano.

+0

No es necesario que 'urlencode' los datos cifrados antes de que usted' base64_encode' TI. – Powerlord

Respuesta

31

Aquí puedo ver problemas en ambos lados.

Tenga en cuenta que lo que obtiene al codificar no es una cadena, sino una matriz de bytes. Por lo tanto, en PHP no necesita urlencode cyphertext.

codificación base64 es todo lo que necesita. Al abrir base64_encode help ves

base64_encode codifica los datos dados con base 64. Esta codificación es diseñado para hacer que los datos binarios sobrevivir transporte

Una cosa más - tener su mensaje decodificado en .NET con una longitud correcta, hay que añadir manualmente con caracteres de relleno. El modo de relleno predeterminado para RijndaelManaged es PKCS7, vamos a seguir con él. Debe extender su cadena de origen a los bloques pares con el código de caracteres igual al número de bytes de relleno.

<?php 
    $iv = "45287112549354892144548565456541"; 
    $key = "anjueolkdiwpoida"; 
    $text = "This is my encrypted message"; 

    // to append string with trailing characters as for PKCS7 padding scheme 
    $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
    $padding = $block - (strlen($text) % $block); 
    $text .= str_repeat(chr($padding), $padding); 

    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv); 

    // this is not needed here    
    //$crypttext = urlencode($crypttext); 

    $crypttext64=base64_encode($crypttext); 
    print($crypttext64) . "\n<br/>"; 
?> 

en C# secundarios que tenga fundición de base 64 a byte [] a cadena a byte []. Debe hacer la primera conversión de base64 a byte [] solamente. Recuerde, base64 está reteniendo el texto cifrado que es información binaria, no cadena. También tenga en cuenta que RijndaelManaged es IDisposable, por lo que lo he envuelto en el uso de() construir. Llamar a Close() es necesario pero no lo suficiente como se indica en MSDN.

public byte[] Decode(string str) 
{ 
    var decbuff = Convert.FromBase64String(str); 
    return decbuff; 
} 

static public String DecryptRJ256(byte[] cypher, string KeyString, string IVString) 
{ 
    var sRet = ""; 

    var encoding = new UTF8Encoding(); 
    var Key = encoding.GetBytes(KeyString); 
    var IV = encoding.GetBytes(IVString); 

    using (var rj = new RijndaelManaged()) 
    { 
     try 
     { 
      rj.Padding = PaddingMode.PKCS7; 
      rj.Mode = CipherMode.CBC; 
      rj.KeySize = 256; 
      rj.BlockSize = 256; 
      rj.Key = Key; 
      rj.IV = IV; 
      var ms = new MemoryStream(cypher); 

      using (var cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read)) 
      { 
       using (var sr = new StreamReader(cs)) 
       { 
        sRet = sr.ReadLine(); 
       } 
      } 
     } 
     finally 
     { 
      rj.Clear(); 
     } 
    } 

    return sRet; 
} 

Como resultado, siguiente código en C# le devolverá la cadena inicial:

var iv = "45287112549354892144548565456541"; 
var key = "anjueolkdiwpoida"; 
var cypher = "u+rIlHB/2rrT/u/qFInnlEkg2unhizsNzGVb9O54sP8="; 

var temp = DecryptRJ256(Decode(cypher), key, iv); 
+0

¡He intentado esto, y funciona! Genial que lo publiques. – Yuki

+0

Bien hecho para los ejemplos. He completado el código con el lado de descifrado y puse todo en un [gist] (https://gist.github.com/2036829) –

+0

Intenté este código, para aceptar $ key de POST.when la aplicación C# intenta descifrar la cadena cifrada. Se genera una clave especificada por una excepción no válida para este algoritmo.Por favor, ayúdenme http://stackoverflow.com/questions/10160690/php-encryption-and-decryption-with-data-from-post-method-using-c-sharp – techno