2013-09-04 10 views
6

Próbuję przepisać tę funkcję w języku C#. ale wyjście C# typowi PZPPHP MCRYPT_RIJNDAEL_128 Szyfrowanie w C#

wersja PHP

// Encrypt data using AES128-cbc 
function encrypt($data, $key, $iv) { 
    $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'cbc', ''); 
    mcrypt_generic_init($cipher, $key, $iv); 
    $multipass = mcrypt_generic($cipher, $data); 
    mcrypt_generic_deinit($cipher); 
    return $multipass; 
} 

C# w wersji

public static string encrypt(string encryptionString, string iv, string key) 
{ 
    byte[] clearTextBytes = Encoding.UTF8.GetBytes(encryptionString); 
    var rijn = SymmetricAlgorithm.Create(); 
    rijn.KeySize = 128; 
    rijn.Mode = CipherMode.CBC; 
    var ms = new MemoryStream(); 
    var cs = new CryptoStream(ms, rijn.CreateEncryptor(Encoding.UTF8.GetBytes(key), Encoding.UTF8.GetBytes(iv)), CryptoStreamMode.Write); 
    cs.Write(clearTextBytes, 0, clearTextBytes.Length); 
    cs.Close(); 
    var tmp = Encoding.UTF8.GetString(ms.ToArray()); 
    return tmp; 
} 
+0

Dlaczego przeskoczyć przez te 'CryptoStream' +' MemoryStream' obręcze, kiedy można po prostu zadzwonić 'Rijn .TransformFinalBlock'? – CodesInChaos

+0

Dla innych, którzy próbują to zrobić, PaddingMode.Zeros (odpowiedź Syona poniżej) było rozwiązaniem dla mnie. –

Odpowiedz

6

szyfrowania/odszyfrowywania przy użyciu PHP:

class Cipher { 
    private $key, $iv; 
    function __construct() { 
     $this->key = "edrtjfjfjlldldld"; 
     $this->iv = "56666852251557009888889955123458"; 
    } 
    function encrypt($text) { 

     $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, $this->key, $text, MCRYPT_MODE_CBC, $this->iv); 

     return base64_encode($crypttext); 
    } 

    function decrypt($input) { 
     $dectext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->key, base64_decode($input), MCRYPT_MODE_CBC, $this->iv); 
     return $dectext; 
    } 
} 

szyfrowania/odszyfrowywania przy użyciu C#:

public class RijndaelSimple 
    { 
     const string iv = "56666852251557009888889955123458"; 
     const string key = "edrtjfjfjlldldld"; 

     static public String EncryptRJ256(string plainText) 
     { 
      var encoding = new UTF8Encoding(); 
      var Key = encoding.GetBytes(key); 
      var IV = encoding.GetBytes(iv); 
      byte[] encrypted; 

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

        using (var cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write)) 
        { 
         using (var sr = new StreamWriter(cs)) 
         { 
          sr.Write(plainText); 
          sr.Flush(); 
          cs.FlushFinalBlock(); 
         } 
         encrypted = ms.ToArray(); 
        } 
       } 
       finally 
       { 
        rj.Clear(); 
       } 
      } 

      return Convert.ToBase64String(encrypted); 
     } 

     static public String DecryptRJ256(string input) 
     { 
      byte[] cypher = Convert.FromBase64String(input); 

      var sRet = ""; 

      var encoding = new UTF8Encoding(); 
      var Key = encoding.GetBytes(key); 
      var IV = encoding.GetBytes(iv); 

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

    } 
4

Dwa problemy z kodu C#.

  1. Nie powinieneś kodować zawartości twojego MemoryStream do UTF8. Wyjście z CryptoStream jest binarne i nie będzie konwertować poprawnie. Albo zwróć byte[], albo jeśli naprawdę chcesz ciąg, zakoduj wyjście na Hex lub Base64.

  2. Musisz ustawić tryb wypełnienia za pomocą rijn.Padding = PaddingMode.Zeros;. Chociaż nie jest to wyraźnie powiedziane, PHP pobiera dane do rozmiaru bloku za pomocą zer. Domyślną wartością padding dla SymmetricAlgorithm jest PKCS7.

Zauważ również, że podpisy twoich metod PHP i C# są różne. Kolejność parametrów dla funkcji PHP to data, key, iv, natomiast metoda C# to data, iv, key. Jeśli nadal masz problem po zmianach wymienionych powyżej, może to oznaczać, że Twój IV i klucz są odwrócone podczas wywoływania metody szyfrowania C#.

+0

@ nullException: Czy to nie rozwiązuje twojego problemu? Testowanie tych zmian za pomocą kodu naprawia je dla mnie. – Syon

+0

+1 twoja pozycja 2 jest dobrym punktem, jednak rozwiązanie Melada dodaje dopełnienie PKCS7 do tekstu (i powinno zostać usunięte później), więc wyniki powinny być takie same w C# i PHP (otrzymuję ten sam wynik w obu) – AaA

+0

@Syon +1 ... PaddingMode.Zeros był dla mnie problemem, mimo że znalazłem napiwek gdzie indziej. Twoja odpowiedź wymaga więcej uplayów! –