2010-12-01 16 views
18

Je rencontre actuellement un peu de problème avec le décryptage d'un message crypté par php mcrypt. Le code php est comme suivant:Cryptage/décryptage multi plate-forme (php vers C# .NET) avec 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/>"; 
?> 

Le message crypté est ensuite envoyé à une plate-forme ASP.NET (C#). Cependant, j'ai un problème pour conserver l'ordre de décryptage (base64 décode en urldecode). Le code que j'avais dans ASP.NET est comme suit (iv et la clé est la même que celle 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); 

Le problème que je vais avoir est que, après que j'ai reçu le message chiffré de php, je me suis converti en octet [], puis reconverti en UTF8 chaîne codée afin que je puisse l'urldecode. alors je donne le résultat dans la fonction où j'ai converti la chaîne en byte [] et l'ai couru à travers le processus de déchiffrement. Cependant, je ne peux pas obtenir le résultat désiré ... des idées?

Merci d'avance.

+0

Vous n'avez pas besoin de 'urlencode' les données cryptées avant vous' base64_encode' il. – Powerlord

Répondre

31

Ici, je peux voir des problèmes des deux côtés. S'il vous plaît gardez à l'esprit que ce que vous obtenez lors de l'encodage n'est pas une chaîne, mais plutôt un tableau d'octets.

Donc, en PHP, vous n'avez pas besoin d'urlencode cyphertext.

L'encodage en base64 est tout ce dont vous avez besoin. Lorsque vous ouvrez base64_encode help vous voyez

base64_encode Encode les données fournies avec base64. Ce codage est conçu pour rendre les données binaires survivre au transport

Une chose - d'avoir votre message décodé en .net avec une longueur correcte, vous devez ajouter manuellement avec des caractères de remplissage. Le mode de remplissage par défaut pour RijndaelManaged est PKCS7, permet de s'en tenir à cela. Vous devez étendre votre chaîne source à des blocs pairs avec un code de caractères égal au nombre d'octets de remplissage.

<?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/>"; 
?> 

A côté C# vous avez coulée de base64 à byte [] à chaîne à octet []. Vous devez faire la première conversion de base64 à octet [] seulement. Souvenez-vous que base64 contient le texte chiffré qui est une donnée binaire, pas une chaîne. Notez également que RijndaelManaged est IDisposable, donc je l'ai enveloppé dans using() construct. L'appel à Close() est nécessaire mais pas suffisant comme indiqué dans 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; 
} 

En conséquence, le code suivant en C# vous ramènera la chaîne initiale:

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

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

J'ai essayé ça, et ça marche! Super que vous l'affichez. – Yuki

+0

Bravo pour les exemples. J'ai terminé le code avec le côté de décryptage et tout mettre dans un [gist] (https://gist.github.com/2036829) –

+0

J'ai essayé ce code, pour accepter la clé $ à partir de POST.when l'application C# essaie de décrypter la chaîne cryptée, Une clé spécifiée par l'exception non valide pour cet algorithme est levée.S'il vous plaît aidez-moi sur http://stackoverflow.com/questions/10160690/php-encryption-and-decryption-with-data-from-post-method-using-c-sharp – techno