Pull to refresh

Использование шифрования Blowfish для авторизации на сайте (Javascript и PHP)

В процессе работы над очередным проектом возникли вопросы связанные с авторизацией пользователя на сайте. «Стандартные» схемы отправки пароля в виде md5-хеша приправленного солью не устраивали. Плюсы и минусы такого способа неоднократно обсуждались на Хабре. Основным минусом являлось то, что login пользователя все равно оставался открытым. Пришлось копать в сторону двустороннего шифрования с использованием ключей. Предлагаемая схема авторизации реализована с использованием алгоритма Blowfish и позволяет организовать шифрованную передачу данных между клиентом и сервером.

Постановка задачи

Нужна такая схема авторизации, которая максимально усложняет отслеживание пользователя по его логину и делает невозможным (лучше сказать «практически невозможным») перехват пароля как в процессе авторизации так и в случае изменения пароля. Нет возможности использования SSL.

Для реализации схемы на стороне клиента используются библиотеки blowfish.js и md5.js. На сервере PHP с модулем mcrypt.

В общих чертах схема выглядит следующим образом:

Предполагается, что клиент уже зарегистрирован в базе данных сервера и сведения о нем хранятся в следующем виде:
1. md5(login)
2. md5(password)
3.…

При подключении клиента на сервере открывается сессия, генерируется случайный ключ, сохраняется в сессию и передается клиенту. Примерный код:
<?php
session_start();
$publickey = md5(microtime()); // любой возможный способ генерации случайного ключа
$_SESSION['publickey'] = $publickey; // сохраняем ключ в сессию
echo $publickey; // передаем ключ клиенту
.....
?>


На стороне клиента шифруем данные:


Данные зашифрованы. MD5-хеш логина пользователя зашифрован с помощью открытого ключа и шифр будет изменяться каждый раз при авторизации. Это усложнит отслеживание пользователя по его логину. Даже если злоумышленник перехватит открытый ключ и расшифрует данные он получит только md5-хеш а не реальный логин пользователя. Пароль сначала упаковывается стандартным способом md5(md5(pass)+соль), а затем шифруется в Blowfish с помощью ключа md5(pass) (т.е. закрытый ключ известный только пользователю и серверу).

Теперь можно отправлять данные на сервер. На сервере данные расшифровываются PHP функцией mcrypt_decrypt();
<?php
..........
$bf_login = 'зашифрованный логин';
$bf_password = 'зашифрованный пароль';
$md5_login = mcrypt_decrypt(MCRYPT_BLOWFISH, $_SESSION['publickey'], pack('H*',$bf_login), MCRYPT_MODE_ECB);
// теперь мы знаем md5-хеш логина и можем выбрать из базы хеш его пароля
$md5_passwd = 'выбранный из базы хеш пароля';
$cript_passwd = mcrypt_decrypt(MCRYPT_BLOWFISH, $md5_passwd, pack('H*',$bf_password), MCRYPT_MODE_ECB);
// и проверяем правильность пароля
if ($crypt_passwd == md5($md5_passwd + $_SESSION['publickey']) {
// проверка прошла успешно
}
..........
?>


Таким же способом можно реализовать изменение пароля. Спрашиваем у пользователя старый пароль и новый пароль. Шифруем новый пароль с помощью ключа, полученного из старого и отправляем на сервер. Там расшифровываем и помещаем в базу.

В итоге, мы получаем схему, при которой логин и пароль «светятся» в сети только один раз при регистрации на сайте (если она реализована в открытом доступе). При всех остальных обращениях данные достаточно надежно зашифрованы.

Основным минусом данной схемы авторизации является высокая нагрузка на стороне клиента при выполнении шифрования, что может поставить под вопрос использование данной схемы авторизации в мобильных версиях браузеров. В остальном, хотелось бы выслушать содержательные замечания по реализации описанной схемы.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.