Шифрование PHP 3DES

это мой код

 $key = pack('H*', "11223344556677881122334455667788");
 $plaintext = pack('H*', "0000000000000000");

 $ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $plaintext, MCRYPT_MODE_ECB);
 echo bin2hex($ciphertext);

but the result I got is 8ca64de9c1b123a7 was different from этот сайт

6FB23EAD0534752B именно то, что я хочу

Кто-нибудь может объяснить, почему я получаю зашифрованный текст, отличный от этого сайта?


person Thanh    schedule 18.05.2017    source источник
comment
Согласно этому комментарию на php.net, только 3DES mcrypt принимает 192-битные ключи. Ваш ключ 128 бит. После $key = pack('H*', "11223344556677881122334455667788"); попробуйте добавить $key .= substr($key,0,8); и посмотрите, поможет ли это. (Я не могу проверить, так как у меня нигде не установлен mcrypt.)   -  person r3mainer    schedule 19.05.2017
comment
@squeamishossifrage Протестировано на Java, я получил результат, используя ключ 112233445566778811223344556677880000000000000000. mcrypt, безусловно, самая испорченная библиотека, с которой я когда-либо сталкивался.   -  person Maarten Bodewes    schedule 19.05.2017
comment
Я пытаюсь зашифровать в DES и получить правильный зашифрованный текст, но получил предупреждение PHP: размер ключа слишком велик для этого алгоритма. Так как же эта сторона делает то?   -  person Thanh    schedule 19.05.2017


Ответы (1)


У mcrypt есть — или, скорее, была — неприятная привычка дополнять все нулями, если размер неверен. Хуже того, он также обрезает ключи до нужного размера, удаляя байты.

Как прокомментировал брезгливый ossifrage, mcrypt поддерживает только тройной DES с тремя ключами. Это не так уж и плохо, пока вы не заметите, что он с радостью примет 16-байтовый тройной ключ DES с двумя ключами, а затем дополнит его нулями, чтобы сделать его тройным ключом DES с тремя ключами. Конечно, это должно привести к сбою, и более новые версии mcrypt действительно должны это сделать.

Однако вы можете получить тот же результат, используя тройной DES с тремя ключами. Тройной DES с двумя ключами просто повторно использует первый ключ для последнего ключа, поэтому копирование первых 8 байтов и добавление их в конец ключа даст вам правильный результат (опять же, как уже отмечалось).

Лучше используйте другую криптографическую библиотеку, чтобы получить правильные результаты. mcrypt (лежащая в основе библиотека C) не поддерживалась в течение 8 лет или около того (и продолжает расти) и чертовски дерьмовая.


Пример на Java (который также не полностью поддерживает 2-х ключевой тройной DES):

    byte[] pt = new byte[16];
    SecretKeyFactory fact = SecretKeyFactory.getInstance("DESede");
    Cipher desEDE = Cipher.getInstance("DESede/ECB/NoPadding");

    {
        // usual 2-key triple DES:
        byte[] keyData = Hex.decode("112233445566778811223344556677881122334455667788");
        SecretKey generatedSecret = fact.generateSecret(new SecretKeySpec(keyData, "DESede"));
        desEDE.init(Cipher.ENCRYPT_MODE, generatedSecret);
        byte[] ct = desEDE.doFinal(pt);
        System.out.println(Hex.toHexString(ct)); // result: 6FB23EAD0534752B 
    }

    {
        // "zero padded" 2-key triple DES:
        byte[] keyData = Hex.decode("112233445566778811223344556677880000000000000000");
        SecretKey generatedSecret = fact.generateSecret(new SecretKeySpec(keyData, "DESede"));
        desEDE.init(Cipher.ENCRYPT_MODE, generatedSecret);
        byte[] ct = desEDE.doFinal(pt);
        System.out.println(Hex.toHexString(ct)); // result: 8ca64de9c1b123a7 
    }

Заметки:

  • ваши ключи DES не полностью действительны, поскольку биты четности каждого байта установлены неправильно (они, однако, не используются в вычислениях DES);
  • лучше использовать AES и аутентифицированный режим шифрования, а не небезопасный режим ECB.
person Maarten Bodewes    schedule 18.05.2017
comment
Спасибо, что объяснили мне это. Теперь я понял. - person Thanh; 19.05.2017
comment
новее в более новых версиях mcrypt следует заключать в кавычки. :) - person Artjom B.; 19.05.2017
comment
@ArtjomB. Да, ну, по крайней мере, в настоящее время они требуют правильного размера ключа в PHP mcrypt wrapper. - person Maarten Bodewes; 20.05.2017