Вопрос

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

Это было полезно?

Решение

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

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


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

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

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

Другие советы

Я нашел решение, проверьте эту ссылку, может вам помочь. http://sanity-free.com/131/triple_des_betweed_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);
    }

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

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

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

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

РЕДАКТИРОВАТЬ: Похоже на ECB, IV игнорируется.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top