Profruit banner

Умен звънец в openHAB

16 декември 2023

Телефонът е винаги с мен и сега, където и да се намирам получавам известие от openHAB, че някой е позвънил и чака пред вратата. А ако ме няма вкъщи става ясно часа и датата на последното позвъняване.

Tasmota Multipress

30 септември 2023

Идеята е Sonoff Touch T1 US 2 в салона, да управлява освен своето осветление и това в кухнята, а още вентилатора.

DIY 12V 1A WiFi Router UPS

22 април 2023

При поредно прекъсване на захранването вкъщи, батерията на нoтбука и двата UPS автоматично превключват на аварийно захранване и едновременно полита съобщение за конфуза

Zigbee2MQTT клониране

21 януари 2023

... как да клонираме съществуваща настройка на Zigbee2MQTT без да се налага последвало интервю на zigbee-устройствата.

LD2410 - бюджетен датчик присъствие в openHAB

11 февруари 2023

Цената на HLK-LD2410 зададе име на поредната тема в моя блог. С негова помощ се постига "народен" датчик присъствие в домашната автоматизация. . ...



PHP 5.5 предлага нов начин за хеширане на пароли с сол. Тази техника се използва отдавна, но за получаване на желан резултат се изискваше много действия или прибягване до допълнителни библиотеки. Разработчиците идват на помощ, като въвеждат две нови функции в PHP 5.5 за целта.
  • password_hash
  • password_verify
Нека разгледаме как работят.

Действията се свеждат до създаване на лаконична база данни и подобен php-код.


Създаване на база данни и таблица

-- изтриване на test, ако съществува
-- DROP DATABASE `test`;

-- създаване на test
CREATE DATABASE IF NOT EXISTS `test` 
CHARACTER SET utf8 
COLLATE utf8_general_ci;

-- създаване на таблица users
CREATE TABLE IF NOT EXISTS `test`.`users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(30) NOT NULL,
  `password` varchar(60) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

-- въвеждане на инфо
INSERT INTO `test`.`users` (`id`, `username`, `password`) 
VALUES (1, 'profruit', 'butterfly');

-- заявка
SELECT * FROM `test`.`users` LIMIT 1;
В резултат на поредицата команди получаваме това.

таблица users

Ясно, че съхранението на пароли в открит вид в базата данни е глупаво. Ела кумчо изяж ме!

Това остава без труд злоумишленик, докопал се до съдържанието на базата. На свой ред ще направим така, че дори паролите да попаднат в ръцете на хакер, те да останат неотключени, като хешираме паролите и добавим към тях ключ с произволен комплект символи.

Създаване на тестови сайт

Копирайте всеки един файл, посочен долу и създайте подобна структура на вашия сървър.

Съдържанието на сайта за придобиване на представа.

сайт отвътре

Файл config.php съдържа константи, а те пък нужните имена и пароли за съединение към конкретната база данни.

config.php
<?php
 // конфигурация на база данни
 define("DB_SERVER", "localhost");
 define("DB_USER", "johnsmith");
 define("DB_PASS", "hackerpassword");
 define("DB_NAME", "test");

Файл convert.php хешира паролата.
Той ще извлече паролата от базата данни. Ще я отпечата в браузъра, след което хешира с помощта на функция password_hash() и отново отпечата в браузъра за съпоставка преди-после. На края ще обнови паролата в хеширан вид в базата данни.

хеширана парола

Солта (YoKo%jOhn&*;!*1234<butt$>?) е произволен набор от символи, не по-малко от 22 на брой. Тя е поместена в константа SALT и е плод на вашето въобръжение. Солта остава в php-файл, далеч от базата данни и това усложнява задача на злоумишленика. А при повишена параноя може да се изнесе в файл зад пределите на root-директорията на сървъра.

PDO e използвано в качеството на пример и всякакви коментари около него се приветсват. За простота на кода се налага ограничение от изпълнение на този файл само веднъж, иначе ще хеширате отново.

Най-отдолу има хиперлинк, който ще ви отведе към файла за сравнение на паролите. Преминете по него.

convert.php
<?php include ('pdo.inc.php'); ?>

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
    <title>конвертитане на паролата</title>
</head>
<body>

 <p>Парола в чист вид: <?= $password?></p>
    <p>Парола с сол: 
  <?php
   // СОЛ - 22 произволни символа
   DEFINE("SALT", "YoKo%jOhn&*;!*1234<butt$>?");
   
   // хеширане на паролата
   echo $hashPassword = password_hash($password, PASSWORD_BCRYPT, ['salt' => SALT]);
  ?>
    </p>
 <?php
  // чист вид
  // UPDATE `test`.`users` SET `password` = 'butterfly' WHERE `users`.`id` =1;
  
  // обновена с сол
  $sql = "UPDATE users SET password = :password WHERE id = :id";
  $istmt = $db->prepare($sql);
  $istmt->execute([':password' => $hashPassword, ':id' => $id]);
 ?>
 
 <a href="./verify.php?password=">сравнение на паролите</a>
</body>
</html>

За елегантност и по-удобна читаемост отделяме файл pdo.inc.php, като самостоятелен. Той се включва в началото на convert.php. Коментарите следва да ви ориентират.

pdo.inc.php
<?php
 // съединение с база данни
 require ('config.php');
 $db = new PDO('mysql:host='.DB_SERVER.';dbname='.DB_NAME, DB_USER, DB_PASS);
 
 // заявка и подготовка
 $sql = "SELECT * FROM users LIMIT 1";
 $stmt = $db->prepare($sql);
 
 // изпълнение
 $stmt->execute();
 
 // подстановка на полетата в променливи
 $stmt->bindColumn('id', $id);
 $stmt->bindColumn('username', $username);
 $stmt->bindColumn('password', $password);

 $stmt->fetch()
?>
Резултат от действието на convert.php.

хеширане на паролата

Забележете адреса в статус бара, към когото ще бъдете пренасочени, а там ви очаква следния прозорец на вид.

сравняване на паролата

Този прозорец се изрисува от файл verify.php.

verify.php

<?php include ('mysqli.inc.php'); ?>

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8" />
    <title>сравнение</title>
</head>
<body>
  <?php if(empty($pass_from_url)): ?>
        <p>въведете парола</p>  
    <?php elseif (password_verify($pass_from_url, $pass_from_db)): ?>
        <i>вярна парола</i>
    <?php else: ?>
        <i>невярна парола</i>
    <?php endif; ?>
</body>
</html>

Файлът съпоставя значенията на хешираната парола от базата данни с въведената в адресното поле на браузъра. Работейки по този начин отпада нужда от форма за въвеждане.

mysqli-драйверът е ползван в качеството на пример, в стил процедурен код. А изяществото налага разделяне на php-кода от html в отделен файл mysqli.inc.php. Коментарите по кода ще ви въведат в обстановката.


mysqli.inc.php
<?php 
 // URL заявка
 $url = @rtrim($_GET['password']);
 $pass_from_url = isset($_REQUEST['password']) ? $url : '';
 
 if(!empty($pass_from_url)){
  
  // съединение с база данни
  require ('config.php');
  $connection = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
 
  // успех на съединението
  if(mysqli_connect_errno()) {
   die("Database connection kaput.");
  }
 
  // DB заявка
  $sql = "SELECT password FROM users LIMIT 1";
  $query = mysqli_query($connection, $sql);
 
  // обработка на резултата
  $result = mysqli_fetch_assoc($query);
  $pass_from_db = $result['password'];
 
  // освобождаване на ресурси
  mysqli_free_result($query);
  mysqli_close($connection);
  
  // въведена парола
  echo "{$url} е: ";
 }
?>

И нека пробваме с произволна парола hacker92. Резултат.

невярна на паролата

А сега въведем вярната парола butterfly.

вярна на паролата

Bingo!

извор:
Password Hashing
Salted Password Hashing





до нови срещи   ^.^
19.10.2013 profruit 
|

0 Response to "Хеширане на пароли с сол в PHP 5.5"

Публикуване на коментар

Този блог е реинкарнация на първите ми опити за споделяне в нета. На времето започнах с къси разкази на преживяното. После се обезсмисли и превърнах блога си в системно радио. Пиша единствено неща, които карат душата ми да живее: openHAB, Ubuntu, Споделено и т.н. Това е моето системно радио, разбирате ли? Моята вълна и вие сте на нея сега.

Архив на блога