2014-08-23 1 views
0

Я нашел скрипт, который содержит соли, хеши, а затем некоторые, но мой $password возвращает исходную строку при отправке моей формы. Это кажется выше моего «уровня оплаты» ... Моя цель - вставить возвращенную соль, хеш и другие выходы из сценария в мой db. Я даже не уверен, какие значения столбцов мне нужны в db (MYSQLi). Сценарий в if($valid) до SQL:Функции соления и хэширования, возвращающие ничего

<?php 
if ($_SERVER["REQUEST_METHOD"] == "POST") 
{$valid = true; 

if (empty($_POST["password"])) 
{$passwordErr = "Password must be set!"; $Epassword = "nope"; $valid = false;} 
if (strpos($_POST["password"], " ") !== false) 
{$passwordErr = "No spaces are allowed"; $Epassword = "nope"; $valid = false;} 
if(strlen(utf8_decode($_POST['password'])) < 10 || strlen(utf8_decode($_POST['password'])) > 30) 
{$passwordErr = "Password must be between 10 and 30 characters"; $Epassword = "nope"; $valid = false;} 
$password = htmlspecialchars($_POST['password']); 

$tod = date("Y-m-d H:i:s"); 
$setdate = date("Y-m-d H:i:s", strtotime("-4 hours", strtotime($tod))); 
$today = date("Y-m-d", strtotime("-4 hours", strtotime($tod))); 

} 

if($valid){ 

/* 
* Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm). 
* Copyright (c) 2013, Taylor Hornby 
* All rights reserved. 
* 
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions are met: 
* 
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer. 
* 
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation 
* and/or other materials provided with the distribution. 
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
* POSSIBILITY OF SUCH DAMAGE. 
*/ 

// These constants may be changed without breaking existing hashes. 
define("PBKDF2_HASH_ALGORITHM", "sha256"); 
define("PBKDF2_ITERATIONS", 1000); 
define("PBKDF2_SALT_BYTE_SIZE", 24); 
define("PBKDF2_HASH_BYTE_SIZE", 24); 

define("HASH_SECTIONS", 4); 
define("HASH_ALGORITHM_INDEX", 0); 
define("HASH_ITERATION_INDEX", 1); 
define("HASH_SALT_INDEX", 2); 
define("HASH_PBKDF2_INDEX", 3); 

function create_hash($password) 
{ 
// format: algorithm:iterations:salt:hash 
$salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTE_SIZE, MCRYPT_DEV_URANDOM)); 
return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" . $salt . ":" . 
    base64_encode(pbkdf2(
     PBKDF2_HASH_ALGORITHM, 
     $password, 
     $salt, 
     PBKDF2_ITERATIONS, 
     PBKDF2_HASH_BYTE_SIZE, 
     true 
    )); 
} 

function validate_password($password, $correct_hash) 
{ 
$params = explode(":", $correct_hash); 
if(count($params) < HASH_SECTIONS) 
    return false; 
$pbkdf2 = base64_decode($params[HASH_PBKDF2_INDEX]); 
return slow_equals(
    $pbkdf2, 
    pbkdf2(
     $params[HASH_ALGORITHM_INDEX], 
     $password, 
     $params[HASH_SALT_INDEX], 
     (int)$params[HASH_ITERATION_INDEX], 
     strlen($pbkdf2), 
     true 
    ) 
); 
} 

// Compares two strings $a and $b in length-constant time. 
function slow_equals($a, $b) 
{ 
$diff = strlen($a)^strlen($b); 
for($i = 0; $i < strlen($a) && $i < strlen($b); $i++) 
{ 
    $diff |= ord($a[$i])^ord($b[$i]); 
} 
return $diff === 0; 
} 

/* 
* PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt 
* $algorithm - The hash algorithm to use. Recommended: SHA256 
* $password - The password. 
* $salt - A salt that is unique to the password. 
* $count - Iteration count. Higher is better, but slower. Recommended: At least 1000. 
* $key_length - The length of the derived key in bytes. 
* $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise. 
* Returns: A $key_length-byte key derived from the password and salt. 
* 
* Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt 
* 
* This implementation of PBKDF2 was originally created by https://defuse.ca 
* With improvements by http://www.variations-of-shadow.com 
*/ 
function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) 
{ 
$algorithm = strtolower($algorithm); 
if(!in_array($algorithm, hash_algos(), true)) 
    trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR); 
if($count <= 0 || $key_length <= 0) 
    trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR); 

if (function_exists("hash_pbkdf2")) { 
    // The output length is in NIBBLES (4-bits) if $raw_output is false! 
    if (!$raw_output) { 
     $key_length = $key_length * 2; 
    } 
    return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output); 
} 

$hash_length = strlen(hash($algorithm, "", true)); 
$block_count = ceil($key_length/$hash_length); 

$output = ""; 
for($i = 1; $i <= $block_count; $i++) { 
    // $i encoded as 4 bytes, big endian. 
    $last = $salt . pack("N", $i); 
    // first iteration 
    $last = $xorsum = hash_hmac($algorithm, $last, $password, true); 
    // perform the other $count - 1 iterations 
    for ($j = 1; $j < $count; $j++) { 
     $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true)); 
    } 
    $output .= $xorsum; 
} 

if($raw_output) 
    return substr($output, 0, $key_length); 
else 
    return bin2hex(substr($output, 0, $key_length)); 
} 

$sqli = @mysqli_connect("host", "db", "pass","empty"); 
if (mysqli_connect_errno($sqli)) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); } 

mysqli_query($sqli, "INSERT INTO `table`(`password`) VALUES ('$password')"); 
?> 

Примечание: запрос вставляет исходную $password значение в дБ.

Запрос вставляет исходное значение $password в db.

[Примечание] @Masoud ответил на мой вопрос, но я в конечном итоге с помощью `password_hash ($ _ POST [ 'пароль'], PASSWORD_DEFAULT)» предложил @martinstoeckli следующим образом:

if($valid){ 

$hashed_password = password_hash($_POST['password'], PASSWORD_DEFAULT); 

mysqli_query($sqli, "INSERT INTO `table`(`password`) VALUES ('$hashed_password')"); 

} 
+0

Можете ли вы разместить код, в котором вы используете это? – SamT

ответ

1

It должен вставить исходный пароль $ password в базу данных, потому что вы не изменяете $ password от начала до конца вашего кода. один способ вызвать функцию «PBKDF2», как это раньше последней строке кода (до «mysqli_query (...»):

<?php 
$hashed_password = pbkdf2(PBKDF2_HASH_ALGORITHM,$password,'dsafdsa',10,5,false) 
?> 

И изменить последнюю строку кода, как это:

mysqli_query($sqli, "INSERT INTO `table`(`password`) VALUES ('$hashed_password')"); 
+0

Использование этого параметра изменило пароль, но это всего лишь 10 символов. Не могли бы вы объяснить, почему это не так много. Я ожидал, что это будет не менее 256 символов. Примечание. Я добавил точку с запятой на вызов pbhdf2. – bcintegrity

+1

Четвертый параметр функции «pbkdf2()» получает длину пароля, и я устанавливаю его на 10, вы можете изменить его на 256. Например: $ hashed_password = pbkdf2 (PBKDF2_HASH_ALGORITHM, $ password, 'dsafdsa', 256, 5, false) – Masoud

+0

Есть ли какие-либо преимущества или недостатки в использовании более длинных/коротких длин паролей? Это меня озадачивает, как можно сохранить исходное значение пароля независимо от его длины. Кроме того, в вашем предлагаемом вызове, что означает «5»? Я не совсем понимаю pbkdf2. – bcintegrity

1

Эта проблема может быть решена намного проще с помощью функции PHP password_hash(). Эта функция вернет 60-значную строку, включая хеш, соль и фактор затрат, вы можете сохранить эту строку в одном поле в своей базе данных. проверьте на сохраненный хэш, вы должны использовать функцию password_verify().

// Hash a new password for storing in the database. 
// The function automatically generates a cryptographically safe salt. 
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT); 

// Check if the hash of the entered login password, matches the stored hash. 
// The salt and the cost factor will be extracted from $existingHashFromDb. 
$isPasswordCorrect = password_verify($password, $existingHashFromDb); 

В вашем коде вы также проверяете определенные условия и избегаете пароля с помощью htmlspecialchars(). Это необязательно и не должно быть сделано, единственное требование, которое имеет смысл для паролей, - это минимальная длина. Escaping не требуется, потому что вы будете передавать контент хеш-функции, и его вывод всегда будет безопасным (однако это нужно сделать для SQL, а не для вывода HTML). Переменные в $ _POST уже будут декодированы PHP.

if (!isset($_POST["password"]) || strlen($_POST["password"]) < 10) 
{ 
    // password is invalid show error message 
} 

Чтобы предотвратить серверную недоразумение, пароль хеширования всегда, так что пароль будет транспортироваться простой текст между клиентом и сервером. Обычным решением для решения этой проблемы является использование HTTPS, SSL затем шифрует пароль перед отправкой через Интернет.

+0

Это выглядит намного проще. Если я правильно прочитал документацию, 'PASSWORD_BCRYPT' выдаст результат длиной 60 символов.Какой тип поля и длина рекомендуется хранить в mysqldb? Я заметил, что когда я использую двоичные или varbinary типы полей, результат, кажется, «re-hashed» при вставке. Что касается htmlspecialchars(), я вторил паролю в значение (да, как noob), и я забыл его удалить! : D – bcintegrity

+1

@bcintegrity - для хранения хэша пароля вы можете создать поле типа varchar (60). Чтобы быть готовым к будущим улучшениям, вы можете выбрать длину varchar (255) и использовать алгоритм по умолчанию 'password_hash ($ password, PASSWORD_DEFAULT)'. – martinstoeckli

+0

Слово «по умолчанию» делает звук «PASSWORD_DEFAULT» субпараметром, но после прочтения документов снова кажется лучшим вариантом. Спасибо! Я выбрал ответ Масуда, потому что он ответил на исходный вопрос. В следующие несколько дней я внесу свое предложение и отредактирую свое оригинальное сообщение, чтобы отразить ваш вклад :) – bcintegrity