Как вычислить правильное значение KCV для ключа шифрования 3des?


Я пытаюсь вычислить KCV для шифрования DES.

$data = 'F337CE3C64E02D96C61A9EC69E051D5A';
$transport = '4B4D3733504D3735';
$encData = bin2hex(mcrypt_encrypt(MCRYPT_DES, pack('H*', $transport),         
$data, MCRYPT_MODE_ECB));

Все в порядке, данные шифруются должным образом.

Теперь я хочу вычислить KCV.

$key = 'F337CE3C64E02D96C61A9EC69E051D5A';
$zeroBytes = 00000000;
$kcv = bin2hex(mcrypt_encrypt(MCRYPT_3DES, $key, $zeroBytes, MCRYPT_MODE_ECB));
var_dump($kcv);

Это возвращает неправильное значение: 953f34d098f996f9 и оно должно быть (конечное kcv) 53173F.

2 2

2 ответа:

Я вижу две проблемы с вашим кодом: 1. Ключ должен быть двоичным, 2. Следует использовать нулевые байты, а не целочисленные нули.

$key = pack('H*', '0123456789ABCDEF');
$data = "\0\0\0\0\0\0\0\0";

$kcv = strtoupper(bin2hex(mcrypt_encrypt(MCRYPT_3DES, $key, $data, MCRYPT_MODE_ECB)));
var_dump($kcv);

Это выводит D5D44FF720683D0D как ожидалось (KCV для ключа 0123456789ABCDEF является D5D44FF720683D0D).

EDIT: в вашем случае вам нужно добавить первые 16 символов в конец ключа, чтобы получить правильный KCV:

$key = 'F337CE3C64E02D96C61A9EC69E051D5A';
$key .= substr($key, 0, 16);
$key = pack('H*', $key);

$data = "\0\0\0\0\0\0\0\0";

$kcv = strtoupper(bin2hex(mcrypt_encrypt(MCRYPT_3DES, $key, $data, MCRYPT_MODE_ECB)));
var_dump($kcv);

Это выводит 53173F8B139F34FE. Дополнительные сведения см. В разделе параметры ввода:

Стандарты определяют три варианта манипулирования ключами:

  • Вариант 1: Все три ключа независимы.
  • Вариант 2: K1 и K2 независимы, а K3 = K1. Вариант 3: Все три ключа идентичны, т. е. K1 = K2 = K3.

Я не криптограф, но быстрый поиск в Google говорит, что 3DES KCV должен быть вычислен по "строке двоичных нулей", а $zeroBytes = 00000000; - это не так.

PHP прочитает это как 0, а затем введет его в нулевой символ ASCII, он же 0x30.

Я думаю, что вы хотите:

$zeroBytes = "\0\0\0\0\0\0\0\0";

Который даст вам восемь нулевых байт, он же 0x00.