Различия в шифровании AES между php mcrypt и компонентом Delphi

1

Я использую компонент Delphi от chillkat, который шифрует AES для меня. Он работает как шарм, и сервер принимает мои зашифрованные запросы. Поэтому я попытался создать php-кулон с помощью mcrypt. Но результат PHP mcypt отличается от результата Delphi Chillcat - даже если все параметры одинаковы. Поэтому сервер отклоняет запросы php.

Все настройки шифрования одинаковы:

  • Шифр Название: AES 128
  • Режим шифрования: ECB
  • Схема прокладки: Pad с NULL
  • Длина ключа: 128
  • Ключ: 1234567890ABE1234567890ABE1234DB
  • Строка для шифрования: это действительно классная тестовая строка

Это небольшой скрипт php:

<?php 
    $key = '1234567890ABE1234567890ABE1234DB';
    function string_encrypt($string, $key) {
        $crypted_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_ECB);
        return $crypted_text;
    }

    function string_decrypt($encrypted_string, $key) {
        $decrypted_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_string, MCRYPT_MODE_ECB);
        return trim($decrypted_text);
    }

    echo $test_str = 'This is a really cool teststring';   echo '<br />';
    $enc_str = string_encrypt($test_str, $key);
    echo bin2hex($enc_str);                                     echo '<br />';
    echo string_decrypt($enc_str, $key);                        echo '<br />';

    ?>

Выход php: e355fbcd91ada4b835e1b030cc9741759219f59fe441ba62e628eca2e8289eb3

Это код Delphi:

function encrypt(s:PWideChar;mode,padding:integer;algo,cipher,keylength:string):string;
var
crypt: HCkCrypt2;
success: Boolean;
ivHex: PWideChar;
keyHex: PWideChar;
encStr: PWideChar;
decStr: PWideChar;

begin
crypt := CkCrypt2_Create();

//  AES is also known as Rijndael.
CkCrypt2_putCryptAlgorithm('aes');
// "pki", "aes", "blowfish", "blowfish2", "des", "3des", "rc2", "arc4", "twofish", "pbes1" and "pbes2"

//  CipherMode may be "ecb" or "cbc"
CkCrypt2_putCipherMode(crypt,'ecb');

//  KeyLength may be 128, 192, 256
try
  CkCrypt2_putKeyLength(crypt,128);
Except
  showmessage('The encryption key you have used seems to be invalid');
end;


//  The padding scheme determines the contents of the bytes
//  that are added to pad the result to a multiple of the
//  encryption algorithm block size.  AES has a block
//  size of 16 bytes, so encrypted output is always
//  a multiple of 16.

{
Possible values are:

0 = RFC 1423 padding scheme: Each padding byte is set to the number of padding bytes.
If the data is already a multiple of algorithm block size bytes, an extra block is
appended each having a value equal to the block size. (for example, if the algorithm's
block size is 16, then 16 bytes having the value 0x10 are added.). (This is also known as
PKCS5 padding: PKCS #5 padding string consists of a sequence of bytes, each of which
is equal to the total number of padding bytes added. )

1 = FIPS81 (Federal Information Processing Standards 81) where the last byte contains
the number of padding bytes, including itself, and the other padding bytes are set to random values.

2 = Each padding byte is set to a random value. The decryptor must know
how many bytes are in the original unencrypted data.

3 = Pad with NULLs. (If already a multiple of the algorithm block size,
no padding is added).

4 = Pad with SPACE chars(0x20). (If already a multiple of algorithm block size, no padding is added).
}
CkCrypt2_putPaddingScheme(crypt,3);

//  EncodingMode specifies the encoding of the output for
//  encryption, and the input for decryption.
//  It may be "hex", "url", "base64", or "quoted-printable".
CkCrypt2_putEncodingMode(crypt,'hex');

//  An initialization vector is required if using CBC mode.
//  ECB mode does not use an IV.
//  The length of the IV is equal to the algorithm block size.
//  It is NOT equal to the length of the key.
ivHex := '';
CkCrypt2_SetEncodedIV(crypt,ivHex,'hex');

//  The secret key must equal the size of the key.  For
//  256-bit encryption, the binary secret key is 32 bytes.
//  For 128-bit encryption, the binary secret key is 16 bytes.

keyHex := '1234567890ABE1234567890ABE1234DB';
CkCrypt2_SetEncodedKey(crypt,keyHex,'hex');

//  Encrypt a string...
//  The input string is 44 ANSI characters (i.e. 44 bytes), so
//  the output should be 48 bytes (a multiple of 16).
//  Because the output is a hex string, it should
//  be 96 characters long (2 chars per byte).


 //encryption
 if mode = 0 then
 begin
   encStr := CkCrypt2__encryptStringENC(crypt,s);
   result := encStr;
 end
 else
 begin
  result := CkCrypt2__decryptStringENC(crypt,s);
 end;


CkCrypt2_Dispose(crypt);
End;

Выход компонента Chillkat Delphi: 780F849AB30690433409D4FB7B3357735296A6E76D3AA6B6D6C769BE99F32041

Я думал, что оба выхода должны иметь одинаковое значение, так как все входные параметры равны, верно?

  • 0
    Вы видели все это ?
  • 0
    Я только что красный их. Было несколько подсказок, которые я пытался реализовать, но это не работает. Хотя в одной теме упоминался этот сайт: ссылка и этот сайт может зашифровать мой код Delphi и наоборот.
Теги:
encryption

2 ответа

2
Лучший ответ

MCrypt ожидает, что ключ является двоичной строкой, но вы передаете в нее шестнадцатеричную кодированную строку.

использование

$key = hex2bin($key);

или

$key = pack('H*', $key);

в зависимости от поддержки PHP. Это необходимо сделать до вызова mcrypt_encrypt().


Безопасность:

Никогда не используйте режим ECB. Это не семантически безопасно. Существует много того, что злоумышленник может получить от зашифрованных текстов без их расшифровки. Вам нужно использовать по крайней мере режим CBC со случайным IV. У вас также должен быть тег проверки подлинности ваших зашифрованных текстов.

Этот ответ дает вам все, что вам нужно знать об этом. Осталось одно: не используйте MCrypt. Это старая невоспитанная библиотека.

Этот ответ также очень полезен в этом отношении другим способом достижения того же.

  • 0
    Вывод не меняется, если я добавлю эту строку. Кроме того, мне пришлось добавить функцию hex2bin вручную, поскольку ее не удалось найти на моем сервере.
  • 0
    Это невозможно. Ключ другой, поэтому результат должен быть другим. В любом случае, я добавил альтернативный способ декодирования hex.
Показать ещё 5 комментариев
0

благодаря вашим хорошим входам, я смог получить положительный ответ с сервера со следующими четырьмя строками кода:

$key = pack('H*', "*5DB");
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key,$mytxt, MCRYPT_MODE_ECB);
$hex2 = bin2hex($ciphertext);
echo strtoupper($hex2);

Однако я узнал, что

  • ЕЦБ небезопасен
  • mcrypt старен и не поддерживается

Я буду проверять альтернативы и обновлять свой код соответственно. Еще раз спасибо !

Ещё вопросы

Сообщество Overcoder
Наверх
Меню