Вам необходимо извлечь ключ из парольной фразы так же, как это делает код C # в PasswordDeriveBytes . Это задокументировано для получения ключа PBKDF1 согласно RFC2898 :
Этот класс использует расширение
Алгоритм PBKDF1, определенный в PKCS # 5
Стандарт v2.0 для получения байтов подходит
для использования в качестве ключевого материала из
пароль. Стандарт задокументирован
в IETF RRC 2898.
Существуют PHP-библиотеки, которые реализуют PBKDF1, но действительно просто написать одну с нуля на основе RFC:
PBKDF1 (P, S, c, dkLen)
Опции: Hash
основная хеш-функция
Ввод: P
пароль, строка октетов
Соль S, восьмиоктетная строка
c счетчик итераций, положительное целое число
dkLen предполагаемая длина в октетах производного ключа,
положительное целое число, максимум 16 для MD2
или же
MD5 и 20 для SHA-1
Вывод: получено в DK
ключ, строка dkLen-октет
Шаги:
1. If dkLen > 16 for MD2 and MD5, or dkLen > 20 for SHA-1, output
"derived key too long" and stop.
2. Apply the underlying hash function Hash for c iterations to the
concatenation of the password P and the salt S, then extract
the first dkLen octets to produce a derived key DK:
T_1 = Hash (P || S) ,
T_2 = Hash (T_1) ,
...
T_c = Hash (T_{c-1}) ,
DK = Tc<0..dkLen-1>
3. Output the derived key DK.
Обновлено
Когда вы попадаете в эту ситуацию, вы обычно ищете пример реализации, который показывает значения на каждом шаге. например, на http://www.di -mgt.com.au / cryptoKDFs.html # examplespbkdf :
Password = "password"
= (0x)70617373776F7264
Salt = (0x)78578E5A5D63CB06
Count = 1000
kLen = 16
Key = PBKDF1(Password, Salt, Count, kLen)
= (0x)DC19847E05C64D2FAF10EBFB4A3D2A20
P || S = 70617373776F726478578E5A5D63CB06
T_1= D1F94C4D447039B034494400F2E7DF9DCB67C308
T_2= 2BB479C1D369EA74BB976BBA2629744E8259C6F5
...
T_999= 6663F4611D61571068B5DA168974C6FF2C9775AC
T_1000= DC19847E05C64D2FAF10EBFB4A3D2A20B4E35EFE
Key= DC19847E05C64D2FAF10EBFB4A3D2A20
Итак, теперь давайте напишем функцию PHP, которая делает это:
function PBKDF1($pass,$salt,$count,$dklen) {
$t = $pass.$salt;
//echo 'S||P: '.bin2hex($t).'<br/>';
$t = sha1($t, true);
//echo 'T1:' . bin2hex($t) . '<br/>';
for($i=2; $i <= $count; $i++) {
$t = sha1($t, true);
//echo 'T'.$i.':' . bin2hex($t) . '<br/>';
}
$t = substr($t,0,$dklen);
return $t;
}
Теперь вы можете видеть ошибки ваших путей: вы не указали все важные параметры raw=true
для sha1
. Давайте посмотрим, что наша функция вывода:
$HashPassPhrase = pack("H*","70617373776F7264");
$HashSalt = pack("H*","78578E5A5D63CB06");
$HashIterations = 1000;
$devkeylength = 16;
$devkey = PBKDF1($HashPassPhrase,$HashSalt,$HashIterations,$devkeylength);
echo 'Key:' . bin2hex(substr($devkey, 0, 8)) . '<br/>';
echo 'IV:' . bin2hex(substr($devkey, 8, 8)) .'<br/>';
echo 'Expected: DC19847E05C64D2FAF10EBFB4A3D2A20<br/>';
это выводит в точности ожидаемый результат:
Key:dc19847e05c64d2f
IV:af10ebfb4a3d2a20
Expected: DC19847E05C64D2FAF10EBFB4A3D2A20
Далее мы можем проверить, что функция C # делает то же самое:
byte[] password = Encoding.ASCII.GetBytes("password");
byte[] salt = new byte[] { 0x78, 0x57, 0x8e, 0x5a, 0x5d, 0x63, 0xcb, 0x06};
PasswordDeriveBytes pdb = new PasswordDeriveBytes(
password, salt, "SHA1", 1000);
byte[] key = pdb.GetBytes(8);
byte[] iv = pdb.GetBytes(8);
Console.Out.Write("Key: ");
foreach (byte b in key)
{
Console.Out.Write("{0:x} ", b);
}
Console.Out.WriteLine();
Console.Out.Write("IV: ");
foreach (byte b in iv)
{
Console.Out.Write("{0:x} ", b);
}
Console.Out.WriteLine();
это выдает тот же результат:
Key: dc 19 84 7e 5 c6 4d 2f
IV: af 10 eb fb 4a 3d 2a 20
QED
объяснение бонуса
Пожалуйста, не используйте криптографию, если вы не знаете точно , что вы делаете. Даже после того, как вы получите правильную реализацию PHP, у вашего опубликованного кода C # есть некоторые серьезные проблемы. Вы смешиваете байтовые массивы с перемешиванием, представляющим шестнадцатеричные дампы, вы используете жестко закодированный IV вместо того, чтобы извлекать его из ключевой фразы и соли, это просто в целом неправильно. Пожалуйста, используйте готовую схему шифрования, такую как SSL или S-MIME, и не изобретайте заново свою собственную. Вы получите это неправильно .