TripleDES Шифрование в C # и PHP не совпадает (PKCS7, ECB)? - PullRequest
3 голосов
/ 14 января 2011

Я потратил пару часов, пытаясь понять это, но я просто не могу заставить его работать. У меня есть подпрограмма шифрования C #, что мне нужно соответствовать в php. Я не могу изменить версию C #, это не вариант (сторонняя организация твердо в этом).

Вот код C #:

//In C#
// Console.WriteLine(ApiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl"));
// Results in: 
//     XvHbR/CsLTo=
public static string ApiEncode(string data, string secret)
{
  byte[] clear;

  var encoding = new UTF8Encoding();
  var md5 = new MD5CryptoServiceProvider();

  byte[] key = md5.ComputeHash(encoding.GetBytes(secret));

  TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
  des.Key = key;
  des.Mode = CipherMode.ECB;
  des.Padding = PaddingMode.PKCS7;

  byte[] input = encoding.GetBytes(data);
  try { clear = des.CreateEncryptor().TransformFinalBlock(input, 0, input.Length); }
  finally
  {
    des.Clear();
    md5.Clear();
  }

  return Convert.ToBase64String(clear);
}

Вот лучшее из того, что я придумал в PHP:

//In PHP
// echo apiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl");
// Results in: 
//    5aqvY6q1T54=
function apiEncode($data, $secret)
{    
  //Generate a key from a hash
  $key = md5(utf8_encode($secret), true);
  //Create init vector  
  $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ecb), MCRYPT_RAND); 

  //Pad for PKCS7
  $blockSize = mcrypt_get_block_size('tripledes', 'ecb');
  $len = strlen($data);
  $pad = $blockSize - ($len % $blockSize);
  $data .= str_repeat(chr($pad), $pad);

  //Encrypt data
  $encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb'); //, $iv);
  return base64_encode($encData);
}

Насколько я знаю, я правильно обрабатываю заполнение PKCS7 на стороне PHP. Я не уверен, что еще попробовать.

Следует отметить, что C # происходит в Windows, а PHP в Linux - не уверен, что это должно измениться.

Ответы [ 4 ]

10 голосов
/ 14 января 2011

Длина отступа в вашей версии PHP зависит от длины пароля.Это неверноВместо этого оно должно основываться на длине вашего сообщения.

Попробуйте заменить strlen($password) на strlen($data).


Вторая проблема заключается в том, что для библиотеки mcrypt требуется 24-байтовые ключи.Triple DES применяет обычный DES три раза, поэтому вы можете вызывать 8-байтовый ключ, используемый в каждом раунде, из DES K 1 , K 2 и K 3 ,Есть разные способы выбрать эти ключи.Наиболее безопасным является выбор трех разных ключей.Другой способ - установить K 3 равным K 1 .Наименее безопасный метод (эквивалентный DES) - сделать K 1 = K 2 = K 3 .

Большинство библиотек "умны"«достаточно, чтобы интерпретировать 16-байтовый ключ 3DES как второй вариант выше: K 3 = K 1 .Реализация .NET делает это за вас, а библиотека mcrypt - нет;вместо этого он устанавливает K 3 = 0. Вам нужно исправить это самостоятельно и передать mcrypt 24-байтовый ключ.

После вычисления хеша MD5 возьмите первый8 байтов $key и добавьте их в конец $key, чтобы у вас было 24-байтовое значение для передачи в mcrypt_encrypt().

1 голос
/ 31 января 2012

Я нашел решение, проверь эту ссылку, может тебе помочь.http://sanity -free.com / 131 / triple_des_between_php_and_csharp.html

А вот функция расшифровки на всякий случай:

    public static string Decrypt(string cypherString)
    {

        byte[] key = Encoding.ASCII.GetBytes("icatalogDR0wSS@P6660juht");
        byte[] iv = Encoding.ASCII.GetBytes("iCatalog");
        byte[] data = Convert.FromBase64String(cypherString);
        byte[] enc = new byte[0];
        TripleDES tdes = TripleDES.Create();
        tdes.IV = iv;
        tdes.Key = key;
        tdes.Mode = CipherMode.CBC;
        tdes.Padding = PaddingMode.Zeros;
        ICryptoTransform ict = tdes.CreateDecryptor();
        enc = ict.TransformFinalBlock(data, 0, data.Length);
        return UTF8Encoding.UTF8.GetString(enc, 0, enc.Length);
    }
0 голосов
/ 14 января 2011

Взгляните на encoding.getBytes, вам нужен секретный ключ Bytes от UTF8 ...

0 голосов
/ 14 января 2011

Похоже, что версия C # не устанавливает IV .Это может быть проблемой, если вы не знаете, что это такое, потому что msdn говорит:

Свойству IV автоматически присваивается новое случайное значение, когда вы создаете новый экземпляр одного из классов SymmetricAlgorithm или когдаВы вручную вызываете метод GenerateIV.

Похоже, что в версии PHP вы используете IV .Вы можете попытаться не указывать IV и надеяться, что в версии C # также используются нули.

Редактировать: похоже на ECB, IV игнорируется.

Возможно, вам также потребуется кодироватьключ, как в версии C #, используя utf8-encode

...