http://ulmt.ru/sites/default/files/adfiles/article02

Page 1

Введение в криптографию на PHP В этот кратком обзоре-руководстве мы рассмотрим, как найти, инсталлировать и использовать различные криптографические пакеты, чтобы более надежно защитить PHP приложения. Можно представить себе идеальный мир, в котором вообще не нужны такие слова как «криптография» и «безопасность», но, поскольку наш реальный мир далек от совершенства, разработчики программного обеспечения вынуждены тратить немало времени, встраивая элементы безопасности в создаваемые приложения. Криптография − это один из подходов в области безопасности в ряду таких, как SSL/TLS, сертификаты, цифровые подписи и т.п. В этой статье разъясняется, как использовать PHP в реализации наиболее часто используемых криптографических алгоритмов. В дополнение к описываемым здесь изначально присущим PHP (по умолчанию) функциям шифрования мы рассмотрим также, как задействовать все многообразие криптографических библиотек и пакетов. В приводимых далее примерах кода используется небольшой текстовый файл textfile.txt, который содержит в себе приведенный далее текстовый контент: For every difficult and complicated question there is an answer that is simple, easily understood, and wrong. H.L. Mencken

1 Криптографические функции в PHP по умолчанию PHP содержит три встроенных функции шифрования: md5(), crypt() и sha1(). Прототип функции md5(): string md5(string $str [, bool $raw_output ])

Эта функция вычисляет хэш MD5 строки-аргумента, используя MD5 (Message-Digest) алгоритм. Аргумент $str представляет собой строку, которую нужно зашифровать. Если аргумент $raw_output передается как FALSE (значение по умолчанию), то функция возвращает хэш как 32-символьное шестнадцатеричное число. Если передать TRUE, то функции возвращает 16-байтное необработанное двоичное значение (raw binary). Функция PHP crypt() − это однонаправленная функция шифрования, которая позволяет подтвердить соответствие введенного пароля сохраненному зашифрованному значению − без необходимости каких-либо дешифровок. Прототип функции crypt(): string crypt (string $str [, string $salt ])

Она возвращает зашифрованную строку, используя стандартный для Unix алгоритм шифрования, основанный на DES, (или альтернативные алгоритмы, доступные в системе). Аргумент $str представляет собой подлежащую шифрованию строку, а необязательный аргумент $salt − это строка, на основе которой производится шифрование. Если не ввести salt-строку, то PHP генерирует ее случайным образом каждый раз при вызове этой функции. Функция PHP sha1() вычисляет SHA-1 хэш строки. Прототип функции sha1(): string sha1 (string $str [, bool $raw_output ])

Функция возвращает SHA-1 хэш как строку. И здесь тоже аргумент $str представляет собой входную строку. Если необязательный аргумент $raw_output установить в TRUE, то функция возвратит хэш sha1 в формате raw binary длиной в 20 символов; если аргумент установлен в FALSE, функция возвращает 40значное 16-ричное число. В приведенном ниже коде показан пример использования встроенных в PHP функций для шифрования содержимого файла texfile.txt с записью результата в файл encrypted.txt (см. рисунок 1): <?php $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ $password = 'OctaviaAnghel';


//Подсчитываем md5 хэш $md5_data = md5($password); //Шифруем данные $crypt = crypt($password); // Подсчитываем sha1 хэш $sha1 = sha1($password); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file,'md5: '. $md5_data."\r\n".'crypt: '.$crypt."\r\n".'sha1: '.$sha1); if($ok_encrypt){ echo 'The encrypted code was succesfully created'. ' in encrypted_file.txt!!!'.' '; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); } ?>

Рисунок 1. Зашифрованный txt-файл содержит пароль, зашифрованный с помощью встроенных в PHP функций md5, crypt и sha1. В дополнение к встроенным функциям PHP поддерживает шифрование посредством внешних библиотек и пакетов. В таблице 1 представлены те из них, которые рассматриваются далее в этой статье. Таблица 1. Криптография в PHP: перечень описанных в статье пакетов и библиотек, которые работают с PHP, реализуя множество типов шифрования и дешифрования. Пакет/Библиотека Описание MCrypt MCrypt используется для шифрования крупных файлов или потоков данных с применением большого количества различных функций шифрования. Более подробную информацию можно найти на http://mcrypt.sourceforge.net/. MHash Библиотека MHash используется для получения хэшей. Она поддерживает наиболее популярные алгоритмы и реализации, такие как SHA, MD5 и CRC. Эти алгоритмы находят применение в вычислении контрольных сумм, дайджестов сообщений и в создании других сигнатур. MHash часто используется при получении хэшей для паролей, введенных в поля HTML. Более подробную информацию можно найти на http://mhash.sourceforge.net/. Crypt_Blowfish Crypt_Blowfish предназначен для быстрого двунаправленного шифрования как с секретным ключом, так и без него. Для использования Crypt_Blowfish не требуется расширение MCrypt PHP; однако этот пакет может использовать Mcrypt, если тот инсталлирован. Более подробную информацию можно найти на: http://pear.php.net/package/Crypt_Blowfish. Crypt_RSA Crypt_RSA поддерживает RSA-подобную генерацию ключей, шифрование/дешифрование, сопоставление подписей и сигнатур. Более подробную информацию см. на http://pear.php.net/package/Crypt_RSA. Crypt_ HMAC Этот класс вычисляет RFC 2104-совместимые хэши. Подробную информацию можно найти на http://pear.php.net/package/Crypt_HMAC. Crypt_DiffieHellman Этот пакет представляет собой реализацию криптографического протокола Diffie-Hellman Key Exchange в PHP5. Более подробную информацию можно найти на http://pear.php.net/package/Crypt_DiffieHellman.


2 Шифрование данных большого объема с помощью MCrypt MCrypt предоставляет разработчикам большой выбор функций для шифрования файлов или потоков данных, не требуя профессиональной подготовки в области криптографии. MCrypt поддерживает множество разнообразных блочных алгоритмов, таких как Blowfish, DES, TripleDES, SAFER-SK128, TWOFISH, TEA, RC2, 3-WAY, SAFER-SK64 и несколько "modes of operation." Как правило, MCrypt оперирует блоками данных фиксированной длины (часто 64 или 128 битов). Но поскольку сообщения могут быть разной длины и поскольку шифрование одного и того же простого текста при использовании одного и того же ключа всегда производит один и тот же вывод, придумали решения, позволяющие реализовать блочное шифрование, обеспечивающее конфиденциальность для сообщений любой длины. Эти решения известны как modes of operation. В режимы, поддерживаемые Mcrypt, входят CBC, CFB, CTR, ECB, OFB и NCFB. Сопутствующей библиотекой для MCrypt является Libmcrypt, в которой содержатся сами функции шифрования. Пользователи Windows могут загрузить ее с http://files.edin.dk/php/win32/mcrypt/, тогда как для пользователей Linux она доступна на http://mcrypt.sourceforge.net/. Инсталляция Libmcrypt: 1. Загрузите libmcrypt.dll с http://files.edin.dk/php/win32/mcrypt/. 2. Скопируйте файл libmcrypt.dll в {php_home}/ext и в {Windows_home}/System32. 3. В php.ini активируйте строку extension=php_mcrypt.dll, для чего удалите метку комментария (";"). 4. Сохраните обновленный файл php.ini. MCrypt может работать с четырьмя режимами шифрования: CBC, OFB, CFB и ECB. Если используется версия, начиная с libmcrypt-2.4.x, то функции MCrypt работают также с режимами nOFB и STREAM. В таблице 2 приведены наиболее часто используемые режимы шифрования вместе с краткими указаниями, когда применять какой режим.

Примечание [A.A.1]: Если вы используете PHP 5.0.0, то потребуется libmcrypt версии не ниже 2.5.6. Примечание [A.A.2]: Для Linux необходимо загрузить файл libmcrypt-x.x.tar.gz с http://mcrypt.sourceforge.net/ и следовать приведенным там инструкциям по инсталляции.

Таблица 2. Наиболее часто используемые режимы в MCrypt, которые применяются в различных случаях. Режим шифрования MCRYPT_MODE_ECB MCRYPT_MODE_CBC MCRYPT_MODE_CFB MCRYPT_MODE_OFB MCRYPT_MODE_NOFB MCRYPT_MODE_STREAM

Описание Используется со случайными данными. Можно применять этот режим для шифрования различных ключей. Применим для шифрования файлов. Рекомендуется для шифрования байтовых потоков. Используется специально для тех приложений, где не допускается распространение ошибки. Аналогично OFB, но с большей степенью защиты. Применяется, когда нужны потоковые алгоритмы, такие как WAKE или RC4.

В дополнение к приведенным режимам в таблице 2 в MCrypt в настоящее время поддерживаются и другие режимы, перечисленные ниже:          

MCRYPT_3DES MCRYPT_ARCFOUR MCRYPT_BLOWFISH MCRYPT_ENIGMA MCRYPT_GOST MCRYPT_IDEA (non-free) MCRYPT_LOKI97 MCRYPT_MARS MCRYPT_PANAMA MCRYPT_RIJNDAEL_128

3 Пример использования MCrypt В приведенном ниже примере показано, как зашифровать и дешифровать содержимое текстового файла с помощью MCrypt. Как и в предыдущем примере, шифруется содержимое файла textfile.txt с сохранением результата шифрования в файле encrypted.txt. Кроме того, в этом примере результирующий файл дешифруется с сохранением расшифрованного текста в новом файле newfile.txt:

Примечание [A.A.3]: Так как список поддерживаемых режимов может со временем меняться, необходимо периодически просматривать их перечень на сайте http://www.php.net/manual/en/ mcrypt.ciphers.php.


// Listing file_encrypt.php <?php $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ //Открываем необходимый модуль с необходимым режимом $td = mcrypt_module_open('tripledes', '', 'ecb', ''); //Создаем вектор инициализации (IV) из случайного источника $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); // Эта функция инициализирует все необходимые буферы mcrypt_generic_init($td, $initial_contents, $iv); //Кодируем данные $encrypted_data = mcrypt_generic($td, $initial_contents); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file,$encrypted_data); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); mcrypt_generic_init($td, $initial_contents, $iv); //Декодируем данные $p_t = mdecrypt_generic($td, $encrypted_data); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$p_t); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); //Деинициализируем модуль кодирования mcrypt_generic_deinit($td); //Закрываем mcrypt модуль mcrypt_module_close($td); } ?>

4 Построение хэшей посредством MHash MHash – это свободно распространяемая библиотека (http://www.php.net/manual/en/mcrypt.ciphers.php), которая предоставляет разработчикам богатый выбор хэш-алгоритмов. Эти алгоритмы можно использовать для вычисления контрольных сумм, дайджестов сообщений и для создания других сигнатур. Инсталляция Libmhash: 1. Загрузите Libmhash с http://sourceforge.net/projects/mhash/. 2. Скопируйте файл libmhash.dll в {php_home}/ext и в {Windows_home}/System32. 3. В php.ini активируйте строку extension=php_mhash.dll, для чего удалите метку комментария (";"). 4. Сохраните измененный файл php.ini.


Поддерживаемые хэши Рассматриваемая здесь библиотека MHash поддерживает такие хэши:                

MHASH_ADLER32 MHASH_CRC32 MHASH_CRC32B MHASH_GOST MHASH_HAVAL128 MHASH_HAVAL160 MHASH_HAVAL192 MHASH_HAVAL256 MHASH_MD4 MHASH_MD5 MHASH_RIPEMD160 MHASH_SHA1 MHASH_SHA256 MHASH_TIGER MHASH_TIGER128 MHASH_TIGER160

В приведенном ниже примере MHash используется для шифрования содержимого текстового файла texfile.txt и записи результата шифрования в файл encrypted.txt: <?php $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ // mhash () применяет хэш функцию, определенную MHASH_MD5 для $initial_contents $encrypted = mhash(MHASH_MD5, $initial_contents); // получаем текущее время в Unix формате даты $current = time(); $salt = $current; $password = "Octavia"; // mhash_keygen_s2k создает ключ согласно данной хэш функции // и пароля, предоставленного пользователем. $hash = mhash_keygen_s2k(MHASH_GOST, $password, $salt, 20); //связываем $salt с $hash $key = $salt . "|" . bin2hex($hash); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file, 'mhash: '.bin2hex($encrypted).' mhash_keygen_s2k: '.$key); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt !!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); } ?>

5 Crypt_Blowfish и секретные ключи В криптографии в симметричных системах с секретным ключом используется единственный ключ, как для шифрования так и для дешифрования, — так называемый симметричный ключ. В качестве примера алгоритма с секретным ключом можно привести широко используемый DES-алгоритм. Пакет Crypt_Blowfish


PEAR основан на блочном шифре Blowfish и поддерживает два вида шифрования: с секретным ключом и без него. Для этого пакета не требуется MCrypt, однако Crypt_Blowfish может использовать Mcrypt, если тот инсталлирован. Последняя релиз-версия Crypt_Blowfish (http://pear.php.net/package/Crypt_Blowfish) 1.0.1 (stable) инсталлируется подобно другим пакетам PEAR: > pear install pear_package_name

В этом пакете используются два класса, определенные в файле Blowfish.php, их нужно включить во все скрипты, которые используют пакет Crypt_Blowfish: require_once 'Crypt/Blowfish.php';

Далее приведен код примера для шифрования с использованием Crypt_Blowfish: <?php require_once 'Crypt/Blowfish.php'; $file = 'textfile.txt'; $initial_contents = file_get_contents($file); if($initial_contents){ $bf = new Crypt_Blowfish('some secret key!'); // Кодируем строку $encrypted = $bf->encrypt($initial_contents); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = @fwrite($encrypted_file,$encrypted); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); // Декодируем скроку $plaintext = $bf->decrypt($encrypted); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$plaintext); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); } ?>

6 Применение пакета Crypt_RSA PEAR для шифрования данных с использованием ключа произвольной длины Этот пакет производит двунаправленное шифрование и основан на блочном шифре RSA. Crypt_RSA поддерживает шифрование и дешифрование, используя ключ произвольной длины. Можно загрузить последнюю стабильную версию 1.0.0 с http://pear.php.net/package/Crypt_RSA и инсталлировать подобно другим пакетам PEAR: pear install pear_package_name

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


  

PECL big_int расширение (http://pecl.php.net/package/big_int) — требуется версия не ниже 1.0.3. PHP GMP расширение (http://ua2.php.net/gmp). PHP BCMath расширение (http://php.net/manual/en/ref.bc.php) для PHP4/PHP5. Требуется, поскольку libbcmath связан с PHP 4.0.4.

Пример использования этого пакета: <?php require_once 'Crypt/RSA.php'; //Генерируем пару ключей function generate_key_pair() { global $public_key,$private_key; $key_pair = new Crypt_RSA_KeyPair(32); //Возвращаем открытый ключ пары $public_key = $key_pair->getPublicKey(); //Возвращаем закрытый ключ пары $private_key = $key_pair->getPrivateKey(); } //Проверяем на ошибки времени запуска function check_error(&$obj) { if ($obj->isError()){ $error = $obj->getLastError(); switch ($error->getCode()) { case CRYPT_RSA_ERROR_WRONG_TAIL : // nothing to do break; default: // echo error message and exit echo 'error: ', $error->getMessage(); exit; } } } $file = 'textfile.txt'; generate_key_pair(); $plain_text = file_get_contents($file); //Получаем строку представления для открытого ключа $key = Crypt_RSA_Key::fromString($public_key->toString()); $rsa_obj = new Crypt_RSA; check_error($rsa_obj); //Кодируем $plain_text с помощью ключа $key. $encrypted = $rsa_obj->encrypt($plain_text, $key); $encrypted_file = @fopen('encrypted.txt','w'); $ok_encrypt = fwrite($encrypted_file,$encrypted); if($ok_encrypt){ echo 'The encrypted code was succesfully created '. 'in encrypted_file.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($encrypted_file); $enc_text = $encrypted; // Получаем строку представления для закрытого ключа


$key2 = Crypt_RSA_Key::fromString($private_key->toString()); check_error($key2); //Проверяем характеристики функций кодирования/декодирования $rsa_obj->setParams(array('dec_key' => $key2)); check_error($rsa_obj); //Декодируем $enc_text $decrypted = $rsa_obj->decrypt($enc_text); $newfile = @fopen('newfile.txt','w'); $ok_decrypt = @fwrite($newfile,$decrypted); if($ok_decrypt){ echo 'The decrypted code was succesfully created '. 'in newfile.txt!!!'.'<br />'; } else{ echo ("The write of this file failed!"); } @fclose($newfile); ?>

7 Генерация хэшей с помощью Crypt_HMAC Пакет Crypt HMAC PEAR (http://pear.php.net/package/Crypt_HMAC) содержит класс, который можно использовать для вычисления RFC 2104-совместимых хэшей (http://rfc.net/rfc2104.html). Crypt_HMAC прост в использовании; требуется лишь задать секретный ключ, один из хэш-методов и простую текстовую строку. Crypt_HMAC поддерживает как MD5 так и SHA-1 алгоритмы. Последний релиз версии 1.0.0 инсталлируется подобно другим пакетам PEAR: pear install pear_package_name

Ниже приведен простой пример создания хэша с использованием Crypt_HMAC: <?php require_once 'Crypt/HMAC.php'; //Создаем ключ повторением символа "0x0b" 20 раз $key = str_repeat(chr(0x0b), 20); //Создаем экземпляр Crypt_HMAC класса //$crypt = new Crypt_HMAC($key, 'md5'); $crypt = new Crypt_HMAC($key, 'md5'); //Вычисляем хэш echo $crypt->hash('Hello')."<br />"; $key = str_repeat(chr(0xaa), 10); $data = str_repeat(chr(0xdd), 50); //Устанавливаем ключ для использования с хэшем $crypt->setKey($key); echo $crypt->hash($data)."\n"; ?>

8 Генерация секретных ключей с помощью пакета Crypt_DiffieHellman PEAR Этот PEAR-пакет реализует криптографический протокол Diffie-Hellman Key Exchange в PHP5. Можно использовать этот протокол при генерации секретного ключа для двух участников, которые могут применить его для передачи информации даже через незащищенные каналы. Последний релиз, версию 0.2.1 (beta), можно загрузить с http://pear.php.net/package/Crypt_DiffieHellman, а затем инсталлировать аналогично другим PEAR-пакетам. pear install pear_package_name


В двух приведенных ниже примерах кода показаны два приложения, генерирующие секретный ключ для связи между двумя участниками: subject_1 и subject_2. Первый пример демонстрирует самый простой способ получения секретного ключа, основанного на Diffie Hellman алгоритме: <?php //подключаем функции Diffie Hellman require_once 'Crypt/DiffieHellman.php'; //устанавливаем запрашиваемые свойства для двух предметов $subject_1 = array('prime'=>'123', 'generator'=>'7', 'private'=>'3'); $subject_2 = array('prime'=>'123', 'generator'=>'7', 'private'=>'34'); //применяем алгоритм Diffie Hellman $subject_1_GK = new Crypt_DiffieHellman( $subject_1['prime'], $subject_1['generator'], $subject_1['private']); $subject_2_GK = new Crypt_DiffieHellman( $subject_2['prime'], $subject_2['generator'], $subject_2['private']); //генерируем ключи $subject_1_GK->generateKeys(); $subject_2_GK->generateKeys(); //подсчитываем секретные ключи $subject_1_SK = $subject_1_GK->computeSecretKey( $subject_2_GK->getPublicKey())->getSharedSecretKey(); $subject_2_SK = $subject_2_GK->computeSecretKey( $subject_1_GK->getPublicKey())->getSharedSecretKey(); //отображаем секретные ключи echo('Subject_1_SK:'.$subject_1_SK.'<br />'); echo('Subject_2_SK:'.$subject_2_SK); ?>

Второй пример демонстрирует, как сгенерировать секретный ключ, используя режим BINARY алгоритма Diffie Hellman. <?php // подключаем функции Diffie Hellman require_once 'Crypt/DiffieHellman.php'; // устанавливаем запрашиваемые свойства для двух предметов $subject_1 = array('prime' => '9568094558049898340935098349053', 'generator'=>'2', 'private' => '2232370277237628823279273723742872289398723'); $subject_2 = array('prime' => '9568094558049898340935098349053', 'generator'=>'2', 'private' => '0389237288721323987429834389298232433363463'); // применяем алгоритм Diffie Hellman $subject_1_GK = new Crypt_DiffieHellman( $subject_1['prime'], $subject_1['generator'], $subject_1['private']); $subject_2_GK = new Crypt_DiffieHellman( $subject_2['prime'], $subject_2['generator'], $subject_2['private']); // генерируем ключи $subject_1_GK->generateKeys(); $subject_2_GK->generateKeys(); // подсчитываем секретные ключи, используя BINARY режим $subject_1_SK = $subject_1_GK->computeSecretKey( $subject_2_GK->getPublicKey(Crypt_DiffieHellman::BINARY), Crypt_DiffieHellman::BINARY)->


В этой статье показано, что можно решить многие проблемы шифрования, используя широкое разнообразие криптографических опций. Криптография сама по себе является одной из «тонких» областей в теории безопасности, и, как мы видели, в ней существует много решений и реализаций. Информация из этой статьи поможет вам быстрее освоить эту область, но помимо этого, только опыт и серьезная работа с системами безопасности позволят выбирать криптографические решения, оптимальные по безопасности, скорости и времени реализации. Статью подготовили Рувинская Виктория и Беркович Леонид


Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.