PHP AES шифрование ... не знаю, что я делаю - PullRequest
3 голосов
/ 18 ноября 2010

Я мало что знаю о шифровании, но мне удалось заставить AES работать на PHP ... немного. Вот несколько функций, которые я использую:

function aes_decrypt($val,$ky) 
{ 
    $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    for($a=0;$a<strlen($ky);$a++) 
      $key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a])); 
    $mode = MCRYPT_MODE_ECB; 
    $enc = MCRYPT_RIJNDAEL_128; 
    $dec = @mcrypt_decrypt($enc, $key, $val, $mode, @mcrypt_create_iv( @mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND) ); 
    return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null)); 
} 

function aes_encrypt($val,$ky) 
{ 
    $key="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 
    for($a=0;$a<strlen($ky);$a++) 
      $key[$a%16]=chr(ord($key[$a%16]) ^ ord($ky[$a])); 
    $mode=MCRYPT_MODE_ECB; 
    $enc=MCRYPT_RIJNDAEL_128; 
    $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
    return mcrypt_encrypt($enc, $key, $val, $mode, mcrypt_create_iv( mcrypt_get_iv_size($enc, $mode), MCRYPT_RAND)); 
} 

Они немного изменены из комментария на странице документации PHP для mcrypt . (Я изменил с dev_urandom на rand, так как нахожусь в окне Windows, где dev_urandom недоступен.)

В любом случае ключ, который я использую в этих функциях, определяется следующим образом:

define("PSK", pack("H*", "abcd7b5ca46e12345678a8161fdacee9"));

Я называю свою функцию так:

echo bin2hex(aes_encrypt("wootwootwootwootwootwootwoo", PSK));

Теперь первые 16 байтов (32 цифры) полученной шестнадцатеричной строки в порядке. Следующие 16 байтов не соответствуют ожидаемым.

Видите, я отправляю эти данные на внешний веб-сервис, который затем расшифровывает их. Я (к сожалению) не могу дать один тестовый пример, который у меня есть, не раздавая свой ключ шифрования и данные. Мне ужасно жаль, но я надеюсь, что кто-то, знакомый с mcrypt, сможет взглянуть на это и сказать мне, что я делаю неправильно.

Опять же, извините за отсутствие надежного контрольного примера, но я очень благодарен за любую помощь, которую вы можете оказать!

РЕДАКТИРОВАТЬ: Кажется, мой провайдер, которому я отправляю сообщения, использует нулевой IV. Следуя совету Рука, я переключился в режим CBC и удалил ненужный код, связанный с ключом. Вот мои новые функции:

function aes_decrypt($val,$key)
{
    $mode = MCRYPT_MODE_CBC;
    $enc = MCRYPT_RIJNDAEL_128; 
    $dec = @mcrypt_decrypt($enc, $key, $val, $mode, null); 
    return rtrim($dec,(( ord(substr($dec,strlen($dec)-1,1))>=0 and ord(substr($dec, strlen($dec)-1,1))<=16)? chr(ord( substr($dec,strlen($dec)-1,1))):null)); 
}

function aes_encrypt($val,$key) 
{
    $mode = MCRYPT_MODE_CBC;
    $enc=MCRYPT_RIJNDAEL_128; 
    $val=str_pad($val, (16*(floor(strlen($val) / 16)+(strlen($val) % 16==0?2:1))), chr(16-(strlen($val) % 16))); 
    return mcrypt_encrypt($enc, $key, $val, $mode, null); 
}

Ответы [ 2 ]

5 голосов
/ 18 ноября 2010

Вполне вероятно, что эта служба шифрования использует другой режим работы блочного шифра, такой как CBC. Если в режиме CBC используется нулевое значение iv, то первый блок (в данном случае 16 байтов) ECB и CBC создаст одинаковый зашифрованный текст. Режим ECB никогда не должен использоваться кем-либо по любой причине.

Вот пример зашифрованного сообщения в режиме ECB:

alt text

1 голос
/ 29 января 2014

Я и мой колледж, где пишу приложение для iPhone и использую вышеуказанные методы для шифрования и дешифрования данныхНо мы обнаружили проблему, когда я шифровал данные, которые будут считываться с его iPhone.В iPhone использовалась обивка PKCS7.Приведенный выше код добавляет дополнительные отступы, что приведет к сбою метода расшифровки iPhone.Мы исправили код, чтобы исправить текущую проблему:

public static function  aes128Encrypt($key,$val) 
{
    $mode = MCRYPT_MODE_CBC;
    $enc=MCRYPT_RIJNDAEL_128; 
    $blocksize= mcrypt_get_block_size($enc,$mode);
    $stringLength = strlen($val);
    $paddingLength =$blocksize-($stringLength%$blocksize);
    $val=str_pad($val,$paddingLength+$stringLength,chr($paddingLength));
    return base64_encode(mcrypt_encrypt($enc, $key, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")); 
}
...