- Шифрование данных на php с открытым ключом
- Как хранить пароли в БД (PHP). Шифрование, хеширование паролей
- Шифрование и хеширование
- Шифрование паролей
- Хеширование паролей и авторизация
- Алгоритмы MD5 и SHA1
- Шифрование базы данных php
- Хеширование
- Шифрование полей в MySQL
- Хранение данных в БД
- Алгоритм DES
- Алгоритм AES
Шифрование данных на php с открытым ключом
Необходимо решить банальнейшую проблему: написать на php алгоритм шифрования данных (строки), использую ключ.
Например:
$data=«Текст, который надо зашифровать»;
$pass=«Серктный ключ»;
print my_encrypt($data,$pass) выведет зашифрованный текст, расшифровать который можно, только владея ключом.
Разумеется, я бы не стал сломя голову ломиться на хабр, на полазив по форумам и википедиям.
Перерыл довольно много и Я н д е к с а , и википедии
Существует функция mcrypt, но она требует подключения дополнительных библиотек, существует также множество готовых стандартных алгоритмов, но нет их достойной (или не очень) реализации на php. В основном они либо на c (вот пример), либо на perl.
Такжо существуют модули для PEAR, которого также нет.
Также есть классическая «Университетская» реализация при помощи XOR:
function x_crypt($data, $key)
$strlen_key = strlen($key);
$sbuf = »;
for ($i= $n = 0, $strlen_data = strlen($data); $i < $strlen_data; $i++)
if ($n >= $strlen_key) $n = 0;
$sbuf .= chr(ord($key[$n++]) ^ ord($data[$i]));
>
return $sbuf;
>
Шифрование и дешифрование выполняется одной функцией. Явный минус:
Исходная строка: Прривет, товарищи. ключ: «Лоль»
Попытка подобрать ключом «Соль», результат:
ри т ов ищ!
Явно видно, что часть зашифрованного текста видна, поэтому такая реализация не очень хороша.
Красота зашифрованного текста на важна, дополнительно можно использовать конструкции
function x_hex_decode($str)
for ($i = 0, $sbuf = null, $strlen = strlen($str); $i < $strlen; $i= $i + 5)
$sbuf .= chr(hexdec(substr($str, $i+3, 2)));
>
return $sbuf;
>
function x_hex_code($str)
for ($i = 0, $sbuf = null, $strlen = strlen($str); $i < $strlen; $i++)
$sbuf .= chr(rand(65,70)).rand(0,9).chr(rand(65,70)).sprintf(‘%X’, ord(substr($str, $i, 1)));
>
return $sbuf;
>
function decodex($data,$key)
return x_hex_decode(x_crypt(base64_decode(gzinflate($data)),$key));
>
function codex($data,$key)
return gzdeflate(base64_encode(x_crypt(x_hex_code($data),$key)),9);
>
Где x_hex_code добавляет случайный мусор, x_hex_decode его убирает, base64_encode и gzdeflate немного запутывают результат для виду, не неся полезной нагрузки.
В процессе поисков, кстати, нашёл любопытную заметку:
В Российской Федерации коммерческая деятельность, связанная с использованием криптографических средств, подлежит обязательному лицензированию. С 22 января 2008 года действует Постановление Правительства РФ от 29 декабря 2007 N 957 «Об утверждении положений о лицензировании отдельных видов деятельности, связанных с шифровальными (криптографическими) средствами», которым приняты Положения о лицензировании деятельности по:
распространению шифровальных (криптографических) средств
техническому обслуживанию шифровальных (криптографических) средств
предоставлению услуг в области шифрования информации
разработке, производству шифровальных (криптографических) средств, защищенных с использованием шифровальных (криптографических) средств информационных и телекоммуникационных систем
Не потому ли подобный (вроде невинный) код сложно найти?
Прошу помочь найти такой алгоритм/класс/функцию.
Согласно правилам блога «Помогите», обязуюсь выложить работающую функцию и, возможно, описать работу.
Если хабрасообщество посчитает проблему надуманной либо неактуальной, этот хабратопик исчезнет, как будто его и не было.
Спасибо.
Как хранить пароли в БД (PHP). Шифрование, хеширование паролей
Главная причина — минимизация ущерба в случае утечки базы данных.
Если злоумышленник получит только логины и email-адреса пользователей — это плохо, но не критично.
Но если в его руках окажутся логины и пароли, он может попытаться использовать эти данные для входа в почтовые сервисы (Gmail, Яндекс.Почта, Mail.ru и т.д.), социальные сети, мессенджеры, клиент-банки и т.д.
В тот же личный кабинет Пятёрочки, чтобы перевыпустить карту и потратить чужие бонусы.
В общем, пользователи сайта, которые везде используют одни и те же логины и пароли, могут получить кучу проблем.
Некоторые разработчики считают, что их приложение надёжно защищено и никаких утечек быть не может. Есть несколько причин, почему это мнение ошибочно:
- Разработчик — не робот, он не может не совершать ошибок.
- Взлом может произойти со стороны хостинг-провайдера, работу которого не всегда возможно контролировать.
- Некорректная настройка сервера может привести к возможному доступу других пользователей хостинга к вашему сайту (актуально для виртуальных хостингов).
- Бывший коллега по работе может слить базу данных конкурентам. Может в качестве мести, а может просто ради денег.
Короче, пароли в открытом виде хранить нельзя.
Шифрование и хеширование
Шифрование — это обратимое преобразование текста в случайный набор символов.
Хеширование — это необратимое преобразование текста в случайный набор символов.
Разница между этими двумя действиями в том, можем ли мы из случайного набора символов получить исходную строку по какому-то известному алгоритму.
Приведу пример шифрования. У нас есть сообщение:
Зашифруем сообщение по следующему алгоритму: сдвинем каждую букву на 1 в алфавитном порядке, т.е. а превращается в б , г превращается в д , я превращается в а . Так будет выглядеть зашифрованный текст:
Зашифровали. Теперь для расшифровки нужно выполнить обратную операцию, сдвинуть все буквы на 1 символ назад. К слову, этот алгоритм шифрования называется шифр Цезаря (Википедия).
В отличие от шифрования, хеширование не имеет (вернее, не должно иметь) способа «расхешировать» строку обратно:
Шифрование паролей
Не надо шифровать пароли.
Алгоритм дешифровки можно украсть или подобрать. При использовании хеширования неважно, знает ли его алгоритм злоумышленник, это не особо поможет ему в получении исходного пароля из хеша.
Хеширование паролей и авторизация
Для хеширования паролей в PHP существует функция password_hash() :
$password = '123456'; $hash = password_hash($password, PASSWORD_BCRYPT); var_dump($hash); // string(60) "$2y$10$Vb.pry5vRGNrm6Y79UfBsun/RbXq2.XEGCOMpozrDwg.MNpfxvWHK"
Вторым параметром передаётся алгоритм хеширования. По-умолчанию это указанный нами bcrypt, но я рекомендую указывать его вручную, поскольку базовый алгоритм в будущем может поменяться. Будет грустно, если при очередном обновлении версии PHP на сайте отвалится авторизация.
Для проверки корректности введённого пользователем пароля используется функция password_verify() :
Ещё раз. При регистрации пользователя нужно передать пароль в функцию password_hash() , а полученный хеш сохранить в базу данных.
При попытке авторизации получаем пользователя по его логину и проверяем функцией password_verify() , соответствует ли хеш пароля тому паролю, который ввёл пользователь.
Таким образом, хранить исходный пароль больше нет смысла.
Да, разные алгоритмы хеширования генерируют хеш разной длины, поэтому рекомендуется хранить хеш в поле с типом VARCHAR(255).
Алгоритмы MD5 и SHA1
В интернете ещё встречаются статьи, где рекомендуется хешировать пароли функциями md5() и sha1() .
Для хеширования паролей их использовать нельзя!
Эти алгоритмы давно устарели и не являются безопасными (Документация). Вместо этого используйте функцию password_hash() , которую мы разобрали выше.
Шифрование базы данных php
Вы можете установить соединения через SSL для шифрования связи клиент/сервер для повышения безопасности, или вы можете использовать ssh для шифрования сетевого соединения между клиентами и сервером базы данных. Если любой из них используется, то мониторинг вашего трафика и получение информации о вашей базы данных будет трудным для потенциального злоумышленника.
В случае, если взломщик получил непосредственный доступ к БД (в обход веб-сервера), он может извлечь интересующие данные или нарушить их целостность, если информация не защищена на уровне самой БД. Шифрование данных — хороший способ предотвратить такую ситуацию, но лишь незначительное количество БД предоставляют такую возможность.
Наиболее простое решение этой проблемы — установить вначале обыкновенный программный пакет для шифрования данных, а затем использовать его в ваших PHP -скриптах. PHP может вам помочь с этой задачей с помощью таких модулей как OpenSSL и Sodium, реализующих довольно большое число алгоритмов шифрования. При таком подходе скрипт вначале шифрует сохраняемые данные, а затем дешифрует их при запросе. Ниже приведены примеры того, как работает шифрование данных в PHP-скриптах.
Хеширование
В случае работы со скрытыми служебными данными, если не требуется их нешифрованное представление (т.е. его не нужно показывать), то, как следствие, можно использовать хеширование. Хорошо известный пример хеширования — хранение криптографического хеша от пароля в БД, вместо хранения оригинального значения.
Функция password позволяет удобно хешировать конфиденциальные данные и работать с этими хешами.
password_hash() позволяет хешировать заданную строку самым сильным из доступных алгоритмом и password_verify() проверяет, что заданный пароль совпадает с сохранённым в БД хешем.
Пример #1 Хеширование полей с паролями
// Сохраняем хеш пароля
$query = sprintf ( «INSERT INTO users(name,pwd) VALUES(‘%s’,’%s’);» ,
pg_escape_string ( $username ),
password_hash ( $password , PASSWORD_DEFAULT ));
$result = pg_query ( $connection , $query );
// проверка введённого пользователем пароля на корректность
$query = sprintf ( «SELECT pwd FROM users WHERE name=’%s’;» ,
pg_escape_string ( $username ));
$row = pg_fetch_assoc ( pg_query ( $connection , $query ));
Шифрование полей в MySQL
В MySQL есть несколько встроенных функций шифрования, подробное описание на dev.mysql.com. Рассмотрим основные на примерах c использованием PHP PDO.
Пароли и ключи переданные в запросах SQL отправляются сервер MySQL в открытом виде, если не используется SSL-соединение. Кроме того, такие значения будут отображаться в логах. Чтобы этого избежать рекомендуется шифровать значения на стороне клиента или использовать хранимые процедуры.
Хранение данных в БД
Функции шифрования возвращают зашифрованный текст в виде двоичных данных, поэтому хранить их нужно в полях с типом BLOB:
Алгоритм DES
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль'); $sth = $dbh->prepare(" INSERT INTO `table` SET `id` = NULL, `text` = DES_ENCRYPT(:text, :key) "); $sth->execute(array('text' => 'Текст который нужно зашифровать', 'key' => 'пароль'));
DES_DECRYPT(crypt_str, key) – расшифровывает строку, если возникает ошибка, эта функция возвращается NULL.
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль'); $sth = $dbh->prepare(" SELECT *, DES_DECRYPT(`text`, :key) AS `text` FROM `table` WHERE `id` = 1 "); $sth->execute(array('key' => 'пароль')); $array = $sth->fetch(PDO::FETCH_ASSOC); print_r($array['text']);
Алгоритм AES
AES, также известный как Rijndael – симметричный алгоритм блочного шифрования, рекомендуется использовать в место DES. AES_ENCRYPT(str, key) – шифрует строку str ключом key.
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль'); $sth = $dbh->prepare(" INSERT INTO `table` SET `id` = NULL, `text` = AES_ENCRYPT(:text, :key) "); $sth->execute(array('text' => 'Текст который нужно зашифровать', 'key' => 'пароль'));
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль'); $sth = $dbh->prepare(" SELECT *, AES_DECRYPT(`text`, :key) AS `text` FROM `table` WHERE `id` = 1 "); $sth->execute(array('key' => 'пароль')); $array = $sth->fetch(PDO::FETCH_ASSOC); print_r($array['text']);