2013-09-04 2 views
6

Я пытаюсь переписать эту функцию в C#. но C# выход не соответствует РНРPHP MCRYPT_RIJNDAEL_128 шифрование в C#

версии 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# Version

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

Почему вы прыгаете через эти '' CryptoStream' + MemoryStream' обручи, когда вы могли бы просто назвать 'RIJN .TransformFinalBlock'? – CodesInChaos

+0

Для других, пытающихся заставить это работать, PaddingMode.Zeros (ответ Syon ниже) был для меня решением. –

ответ

6

шифрования/дешифрования с помощью 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; 
    } 
} 

шифрования/дешифрования с использованием 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

Две проблемы с кодом C#.

  1. Вы не должны кодировать содержимое вашего MemoryStream в UTF8. Выходной сигнал CryptoStream двоичный и не будет правильно преобразован. Либо верните byte[], либо если вы действительно хотите строку, закодируйте вывод на Hex или Base64.

  2. Вам необходимо установить режим заполнения через rijn.Padding = PaddingMode.Zeros;. Хотя это явно не указано, PHP заполняет данные до размера блока, используя 0. По умолчанию для заполнения для SymmetricAlgorithm является PKCS7.

Также обратите внимание, что подписи ваших методов PHP и C# отличаются. Порядок параметров для вашей функции PHP: data, key, iv, а метод C# - data, iv, key. Если у вас все еще есть проблема после изменений, перечисленных выше, возможно, что ваш IV и ключ отменены при вызове вашего метода шифрования на C#.

+0

@nullException: Это не решит вашу проблему? Тестирование этих изменений с помощью кода исправляет это для меня. – Syon

+0

+1 ваш пункт 2 является хорошим моментом, однако решение Мелады добавляет дополнение PKCS7 к тексту тоже (и должно быть удалено позже), поэтому результаты должны быть одинаковыми как на C#, так и на PHP (я получаю одинаковый результат для обоих) – AaA

+0

@Syon +1 ... PaddingMode.Zeros была для меня проблемой, хотя я нашел отзыв в другом месте. Ваш ответ требует большего количества оборотов! –

Смежные вопросы