Это режим ЕЦБ. Там нет IV.

ратил пару часов, пытаясь понять это, но я просто не могу заставить его работать. У меня есть подпрограмма шифрования 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 - не уверен, что это должно иметь значение.

 netcoder14 янв. 2011 г., 21:20
 Redth14 янв. 2011 г., 21:41
Если я это сделаю: $ strArr = str_split ($ key); foreach ($ strArr as $ strChar) echo ("". ord ($ strChar)); Я получаю: 77 173 222 29 122 78 74 3 80 240 63 130 5 137 93 188 Что совпадает с байтами в моем ключе c # byte [] после вычисления хеша md5. Ключи одинаковые.
 time4tea14 янв. 2011 г., 21:14
может ли это быть другая кодировка символов - это явно utf-8 в c #, но что это такое в php? каковы результаты вызова md5 на обоих языках.
 erickson14 янв. 2011 г., 21:31
@netcoder - Не совсем тот же ответ, поэтому я бы сказал, не дубликат.
 Redth14 янв. 2011 г., 21:35
я видел другой вопрос, и я пытался работать с ним, но я все еще не могу понять, как это работает правильно, поэтому я отправил другой вопрос ..

Ответы на вопрос(4)

Решение Вопроса

Вместо этого оно должно основываться на длине вашего сообщения.

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

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

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

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

 Redth14 янв. 2011 г., 21:43
@erickson нет, вы правы, теперь я получаю один блок зашифрованного текста: 5aqvY6q1T54 = это мой base64_encode ($ encData) результат теперь из PHP
 Redth14 янв. 2011 г., 21:37
Исправлен пример кода выше, и мой код, который я тестировал ... Я до сих пор не получаю одинаковую зашифрованную строку от обоих, так что это не так, по-видимому ...
 SwDevMan8114 янв. 2011 г., 21:30
+1 Хороший улов, вот наверное.
 erickson14 янв. 2011 г., 21:40
@Redth - Что вы получаете в результате сейчас? Вы все еще получаете 2 блока зашифрованного текста (24 символа), когда у вас должен быть только один (12 символов)?
 erickson14 янв. 2011 г., 22:45
@Redth - я провел некоторое тестирование самостоятельно (на Java) и получаю те же результаты, что и ваш .NET при использовании 16-байтового ключа. Кроме того, если я создаю 24-байтовый ключ, как описано (устанавливая последние 8 байтов равными первым 8 байтам), я получаю тот же текстовый результат шифрования (мои результаты не меняются). Похоже, вы говорите, что ваш код .NET дает другой результат, если вы создаете 24-байтовый ключ самостоятельно. Что такое зашифрованный текст тогда? И когда вы создаете 24-байтовый ключ в PHP, какой у вас зашифрованный текст?

IV, Это может быть проблемой, если вы не знаете, что это, потому что msdn говорит:

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

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

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

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

 erickson14 янв. 2011 г., 21:21
Это режим ЕЦБ. Там нет IV.

вам нужен секретный ключ Bytes из UTF8 ...

 Redth14 янв. 2011 г., 21:38
Пробовал явно с использованием utf8_encode ($ secret), и это не имеет значения ...

http://sanity-free.com/131/triple_des_between_php_and_csharp.html

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

    public static string Decrypt(string cypherString)
    {

        byte[] key = Encoding.ASCII.GetBytes("[email protected]");
        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);
    }

Ваш ответ на вопрос