Портирование TripleDESCryptoServiceProvider из C # в переполнение стека

Я пытаюсь перенести следующий метод C # на PHP, но я не могу получить правильный вывод.

public static string Encrypt()
{
String text = "123456";
String key = "1r1ppl3x";
byte[] arrText = UTF8Encoding.UTF8.GetBytes(text);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = (new UnicodeEncoding()).GetBytes(key);
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(arrText, 0, arrText.Length);
tdes.Clear();
String encrypted = Convert.ToBase64String(resultArray, 0, resultArray.Length);
return encrypted;}

Моя попытка в PHP до сих пор:

function encrypt()
{
$key = utf8_encode("1r1ppl3x\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
$data = utf8_encode("123456");
$blocksize = mcrypt_get_block_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB);
$tripleKey = substr($key, 0, mcrypt_get_key_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB));
$paddingSize = $blocksize - (strlen($data) % $blocksize);
$data .= str_repeat(chr($paddingSize), $paddingSize);
$encodedText = mcrypt_encrypt(MCRYPT_TRIPLEDES, $tripleKey, $data, MCRYPT_MODE_ECB);
return base64_encode($encodedText);
}

по какой-то причине я не могу получить вывод кода PHP так же, как в C #.

Также я знаю mcrypt_get_block_size и другие mcrypt связанные методы не рекомендуются в PHP 7.1, и его не рекомендуется использовать.

0

Решение

tdes.Key = (new UnicodeEncoding()).GetBytes(key);

Тот UnicodeEncoding Конструктор для UTF-16, с прямым порядком байтов, «с спецификацией». «С спецификации» не имеет значения, потому что ничего не называется GetPreamble(), так что для всех намерений и целей это UTF-16LE.

Это значит твой ключ ("1r1ppl3x") на самом деле:

31 00 72 00 31 00 70 00 70 00 6C 00 33 00 78 00

Который является ключом 2DEA с

  • k1 знак равно { 31 00 72 00 31 00 70 00 }
  • k2 знак равно { 70 00 6C 00 33 00 78 00 }

Что незаконно. За исключением того, что .NET, как и все остальное, не заботятся о битах четности DES, поэтому он просто делает вид, что младший значащий бит каждого байта был правильным. Любая библиотека в PHP, вероятно, будет делать то же самое. Если нет, вы можете исправить соотношение вручную.

Ключ 2DEA имеет эквивалентный ключ 3DEA k3знак равноk1, Поэтому, если ваша PHP-библиотека не поддерживает 2DEA-ключи, вы можете искусственно расширить ее (после правильного использования UTF-16LE вместо UTF-8), скопировав первые 8 байтов до конца, создав 24-байтовое значение.

Если utf8_encode лучше всего «превратить текст в двоичные данные» в PHP, тогда вы хотите использовать строку ввода "1\0r\01\0p\0p\0l\03\0x\01\0r\01\0p\0",

Похоже, вы уже нашли Как добавить / удалить заполнение PKCS7 из зашифрованной строки AES?, поэтому исправление ключа должно привести вас в состояние «эквивалентной функциональности».

Теперь все ваши проблемы в том, что вы используете 56-битный ключ (все эти нули довольно легко угадать), как если бы это был 168-битный ключ, и используете режим ECB, и используете устаревшую библиотеку, и (возможно) что вы используете 3DES вместо AES и (личное мнение) переходите от строго типизированного языка к языку сценариев.

2

Другие решения

  1. Код C # использует заполнение PKCS # 7, код PHP MCRYPT использует заполнение нулями.

  2. Существует предположение, что ключ должен быть расширен с нулями.

  3. Нет смысла использовать Triple DES с одним ключом DES из 8 байтов. Кроме того, используются только 56-битные 8-битные ключи DES. 56-битный ключ не считается безопасным.

0

По вопросам рекламы [email protected]