Ключевые слова:password, php, virtual, crypt, apache, (найти похожие документы)
Date: Sat, 20 Jul 2002 21:36:10 +0400
From: Дмитрий Чертищев <[email protected]>
Newsgroups: apache-talk (http://www.lexa.ru/apache-talk)
Subject: Двусторонее шифрование паролей и переменные окружения в Apache
Дано: Apache с множеством виртуальных хостов и PHP4.
Исторически сложилось, что РНР скрипты должны иметь права 644, т.е.
они доступны для чтения всем, кто есть на этом сервере.
В РНР скриптах может находиться конфиденциальная информация, например,
пароли к БД.
Необходимо эти пароли спрятать, чтобы даже если скрипт похитили, то не
смогли бы узнать пароли.
Долго поломав голову, придумал следующее решение: пароли хранить в РНР
скриптах не в чистом виде, а зашифрованными, например с использованием
РНР функции двустороннего шифрования mcrypt(). А перед использование
пароля, пароль дешифровывать. Понятно, что для шифровки и дешифровки
нужно использовать один и тот же ключ, который и нужно спрятать от
посторонних глаз, иначе похитив ключ, злоумышленник сможет дешифровать
пароль.
Ключ будем хранить в переменной окружения SECRET_KEY в каждом
виртуальном хосте.
Для этого в httpd.conf для каждого виртуального хоста прописываем:
SetEnv SECRET_KEY some_unique_key
Т.е. для каждого хоста прописываем уникальный ключ.
Теперь необходимо с помощью этого ключа зашифровать пароль:
<?
$password = "qwerty";
$key = $HTTP_SERVER_VARS[SECRET_KEY];
$td = mcrypt_module_open ('rijndael-256', '', 'cbc', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
$ks = mcrypt_enc_get_key_size ($td);
$key = substr ($key, 0, $ks);
mcrypt_generic_init ($td, $key, $iv);
$password = mcrypt_generic ($td, $password);
mcrypt_generic_deinit ($td);
$password = bin2hex($password);
print "Зашифрованный пароль: $password<br>";
$hex_iv = bin2hex($iv);
print "Вектор инициализации: $hex_iv<br>";
mcrypt_module_close ($td);
?>
Получаем зашифрованный пароль и вектор инициализации. Теперь этот
зашифрованный пароль можно смело пихать в РНР скрипты. Расшифровываем
пароль так:
<?php
# Полученный зашифрованный пароль
$password = "8b2ef29c465b443585eb78fab8ea71f39be752aff1e1f357ee5913ce488080a5";
# Полученный вектор инициализации (этот вектор не является секретной
информацией, но нужен для расшифровки)
$hex_iv = "ea09567c55fc8f6f354ba3eceba8686d4299a7b4c0c361b7c100527ab915b4b6";
$key = $HTTP_SERVER_VARS[SECRET_CRYPT_KEY];
$password = pack("H*", $password);
$iv = pack("H*", $hex_iv);
$td = mcrypt_module_open ('rijndael-256', '', 'cbc', '');
mcrypt_generic_init ($td, $key, $iv);
$password = mdecrypt_generic ($td, $password);
mcrypt_generic_deinit ($td);
mcrypt_module_close ($td);
print $password;
?>
И получаем в $password дешифрованный пароль, который уже можно
использовать по прямому назначению, например, для подключения к БД.
Вроде вся эта технология работает и попытка расшифровать пароль на
другом виртуальном хосте не приводит к успеху, т.к. исходный ключ
неизвестен.