Я пытаюсь перенести следующий метод 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, и его не рекомендуется использовать.
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 и (личное мнение) переходите от строго типизированного языка к языку сценариев.
Код C # использует заполнение PKCS # 7, код PHP MCRYPT использует заполнение нулями.
Существует предположение, что ключ должен быть расширен с нулями.
Нет смысла использовать Triple DES с одним ключом DES из 8 байтов. Кроме того, используются только 56-битные 8-битные ключи DES. 56-битный ключ не считается безопасным.