Методы и алгоритмы шифрования информации на PHP
Статья уже старовата. Писал я её специально для 4-го выпуска журнала Mazafaka E-zine в сентябре 2005 года, если не ошибаюсь. Но, не смотря на это, решил её разместить и здесь
.
В стандартной установке PHP предоставляет нам некотрые функции для шифрования, например, crypt() и md5(). Остальные нужно явно указывать при компиляции (mcrypt, mhash, cURL).
Функция crypt() выполняет односторонее DES-шифрование. Ей нужно передать обычный текст для шифрования, чтобы получить зашифрованный:
<?php
print crypt («text», «parametr»);
?>
Если второй параметр не указать, то PHP автоматически сгенерирует случайную пару символов для базиса шифрования. При помощи crypt() можно шифровать и по алгоритму md5 ( не только при помощи функции md5() ). Достаточно установить константу CRYPT_MD5 в 1.
Зададим базис, начинающийся с $1$ для использования md5 в функции crypt():
<?php
print crypt («text», «$1$parametr»);
?>
Большой набор алгоритмов и режимов шифрования включает в себя библиотека mcrypt. Итак, зашифруем и расшифруем информацию с помощью алгоритма Blowfish.
<?php
$key = «My cool key»; // просто текст
$data = «My secret data»; // инфа для шифрования
$alg = MCRYPT_BLOWFISH;
$mode = MCRYPT_MODE_CBC;
$iv = mcrypt_create_iv (mcrypt_get_iv_size ($alg, $mode), MCRYPT_DEV_URANDOM);
$encrypted_data = mcrypt_encrypt ($alg, $key, $data, $mode, $iv);
$plain_text = base64_encode ($encrypted_data);
print $plain_text.»\n»;
$decoded = mcrypt_decrypt ($alg, $key, base64_decode($plain_text), $mode, $iv);
print $decoded.»\n»;
?>
Почти ничего не понятно, да
? Сейчас постараюсь объяснить. Все данные шифруются и расшифроввываются с помощью функций mcrypt_encrypt() и mcrypt_decrypt(). Каждая их них принимает пять аргументов.
Первый аргумент – применяемый алгоритм. Все поддерживаемые алгоритмы можно посмотреть, вызвав функцию mcrypt_list_algorithms(). Второй аргумент – это ключ шифрования, третий – данные, которые шужно зашифровать и наоборот.
Четвертый аргумент устанавливает режим шифрование или расшифровки.
Пятый аргумент – вектор инициализации (IV), он используется режимами в качестве составляющей. Первый аргумент функции mcrypt_create_iv() – это длина вектора, второй – источник случайности (в данном случае – /dev/urandom).
Можно применять MCRYPT_DEV_RANDOM и MCRYPT_RAND. Но тогда надо вызывать функцию srand(), т.к. не все ОС поддерживают псевдоустройства случайных генераторов (это касается функции MCRYPT_RAND).
Можно было привести несколько примеров шифрования информации и сохранения в базе данных или файле для дальнейшего использования, но это я решил оставить вам в качестве домашнего задания =). А сейчас поговорим о способах хранения информации (паролей и т.д.) на вашем сайте.
Сколько раз уже было сказано, что не нужно хранить пароли в открытом виде на своих сайтах и директориях, доступных через веб, а большинство почему-то продолжают делать именно так =)!
Допустим, есть пароли для подключения к MySQL. Сохраните их в переменных окружения (не самый лучший вариант, сейчас скажу почему), сервер будет их загружать при старте.
mysql_connect (‘localhost’, $_ENV['MYSQL_USER'],
$_ENV['MYSQL_PASSWORD']);
Минус тут в том, что пароли будут доступны из других мест. Функция phpinfo() выведет все переменные окружения, доступные в скрипте, включая ваши пароли. Если вы работаете с разделенным виртальным хостингом, то нужно установить переменные окружения, чтобы они были
доступны только вашему виртуальному хосту. Сделайте это в отдельном файле:
SetEnv MYSQL_USER «user»
SetEnv MYSQL_PASSWORD «your_pass»
Этот файл нужно включить в директиву <VirtualHost> в главном конфигурационном файле:
Include «/path_to_file/»
Так, теперь немного о проверке данных с помощью хеширования. Допустим, мы отправляем данные в куки или через форму и не хотим, чтобы пользователи смогли их подменить. Можно вместе с данными послать хеш этих данных с каким-либо словом (зашифрованным в md5). При получении информации обратно, вычисляем этот хеш с помощью нашего
слова. Например:
<?php
$word = ’some_word’;
$id = 100;
$hash = md5 ($word . $id);
print<<<_HTML_
<input type=»hidden» name=»id» value=»$id»>
<input type=»hidden» name=»idhash» value=»$hash»>
_HTML_;
?>
После получения обратно проверяем:
<?php
$word = «some_word»;
if (md5($word . $_REQUEST['id']) == $_REQUEST['idhash']) {
$id = $_REQUEST['id'];
} else {
die («Invalid data»);
}
?>
Для использования хеша в cookie изменим немного этот скрипт:
[skip]
….
$cookie_value = ‘m0zg’;
$hash = md5 ($word . $id);
setcookie (‘name’, join(‘ | ‘, array($cookie_value, $hash)));
Проверяем полученное:
<?php
$word = ’some_word’;
list ($cookie_value, $cookie_hash) = explode (‘ | ‘, $_COOKIE['name'], 2);
if (md5($word . $cookie_value) == $cookie_hash) {
$name = $cookie_value;
} else {
die («Invalid data»);
}
?>
Конечно, если кто-то узнает это секретное слово, то вся работа впустую. Тут можно либо менять его постоянно, либо пользоваться переменной $id, т.е. несколько разных слов, выбранных с помощью $id%10 (если 10 слов). Можно использовать модуль mhash, тут вы не будите ограничены хешами в md5. Он поддерживает несколько алгоритмов
хеширования.
А теперь хотелось бы затронуть тему шифрования почты. Использовать будем GPG (ибо Open Source!). Сначала код, а потом пояснения.
<?php
$message = escapeshellarg($message);
$gpg_path = ‘/usr/local/bin/gpg’;
$sender = ‘user@mailserver.com’;
$rcpt = ‘to@someserver.com’;
$home = ‘/home/user’;
$user_env = ‘user’;
$cmd = «echo $msg | HOME=$home USER=$user_env $gpg_path » . ‘–quit–no-secmem-warning –encrypt –sing –armor’ . » –recipient $rcpt –local-user $sender»;
$message = ‘$cmd’; mail($rcpt, ‘GPG Mailer’, $message);
?>
С начала мы вызываем программу GPG, расположенную в
/usr/local/bin/gpg для шифрования сообщения из $message. Она использует закрытый ключ, который принадлежит Вам ($sender), и открытый ключ, принадлежащий $rcpt. Теперь только он сможет расшифровать Ваше сообщение.
Установка переменных окружение HOME и USER указывает GPG, где ей нужно искать свои настройки шифрования ($HOME/.gnupg/secring.gpg).
Параметры –quiet и –no-secmem-warning подавляют предупреждения GPG, которые в противном случае были бы сгенерированы и добавились к тесту сообщения.
Параметры –encrypt и –sing заставляют GPG зашифровать
сообщение и подписать его. Шифрование сообщение закрывает его от любого, кроме адресата. В подписи содержится информация о том, кто составил сообщение и когда.
Параметр –armor генерирует простой текст вместо двоичного кода, для более удобной рассылки.
Обычно закрытые ключи защищаются с помощью идентификационной фразы. Если взломщик скопирует закрытый ключ, защищенный идентификационной фразой, то он ничего не сможет сделать с письмом, т.к. GPG запрашивает её при расшифровке. В этом коде эта фраза не используется.
Очень много можно написать по этой теме, но статью сильно растягивать не хочется =).
Ссылки по теме:
http://www.php.net/md5
http://www.php.net/mhash
http://www.php.net/crypt
http://www.php.net/mcrypt
6 comments so far
Ответить
Давайте больше информации по данной тематике!
Спасибо за прекрасную статью. Желаю побольше подобного материала.
Товарищ курсант! Вы уподобляетесь африканской птице страусу, которая с высоты своего полета не видит генеральной линии партии.
Чем дальше – тем итренеснее. Желаю удачи в развитии!)
Ну, как сказать, понравилось
Хотя я все равно практически ничего не понял.
А какие еще есть системы шифрования кроме етих четырех ?
Как зашифровать методом md4 ?