Я строю свою собственную небольшую структуру для моего последнего года обучения в университете, и я очень запутался в передовой практике здесь. Я прочитал много статей и у меня есть общее представление, но некоторые пояснения были бы лучше.
Мне действительно нравится новое расширение натрия в PHP, но я немного запутался.
Ясоздание функции аутентификации с разделением токенов как для долгосрочных постоянных файлов cookie, так и для сброса пароля.
Я использую Libsodium настолько, насколько это возможно, насколько это кажется очень безопасным, будь то новый и не очень хорошо документированный.
Я создаю разделенный токен, как селектор: валидатор. Что я хочу сделать, так это в основном использовать селектор для запроса к БД:
Затем я хочу либо сравнить два хеша VS Хэш-версию в виде простого текста из файла cookie, а затем сравнить (но последнее означает сохранение ключагде-то, что создает проблему)
Я слышал во многих статьях, особенно с Paragone, предполагающих, что предпочтительнее хранить хешированную версию токена в базе данных, а простую версию - в файле cookie или токене. Есть ли реальная польза от этого?
Я создал простой класс токенов:
class SplitToken extends Token
{
protected $selector;
protected $validator;
function __construct($selector=14, $validator=18)
{
$this->selector = bin2hex(random_bytes($selector));
$this->validator = bin2hex(random_bytes($validator));
$this->key = random_bytes(SODIUM_CRYPTO_AUTH_KEYBYTES);
$this->tokenHash = sodium_crypto_auth($this->validator, $this->key);
}
public function Set()
{
$this->token = $this->selector.':'.$this->validator;
return $this;
}
public function Get()
{
return $this->token;
}
$sptoken = new SplitToken();
$token = $sptoken->set()->Get();
$dt = new DateTime('+ 2 months');
$expiry = $dt->getTimestamp();
//Gets bin2hex version of validator side of token for DB
$validatorHash = $token->GetValidatorHashHex();
$key = $token->GetKey();
//Store token In DB:
$query = "UPDATE Users SET Selector, Validator, Expiry
WHERE Selector = :Selector and Validator = :Validator and Expiry = :Expiry;
$stmt = $pdo->prepare($query);
$stmt->execute(
['Selector' => $token->GetSelector(),
'Validator' => $validatorHash,
'Expiry' => $expiry]);
Теперь, когда временный токен находится в БД. Теперь пришло время установить cookie (То же самое можно применить к сбросу PW с другим сроком действия, конечно. Здесь я запутался, и у меня есть два варианта:
Вариант 1:
//Store the hexed version of selector:validator in the cookie (but not hashed)
setcookie('auth_token', $token, $expiry, '/', 'CONST_DOMAIN', true, true);
//Where do I store the key?
//So far I am using JSON fuNCTION which gets key from the folder where it is stored:
$storedKey = Key::GetFromVault('auth_token');
if(isset($_COOKIE['auth_token')){
$cookie = explode(':', $_COOKIE['auth_token'];
//Gets the User from the DB Where Selector = Selector
$user = DB::SelectUser($user);
//If User exists
if($user){
//*** Checks the Hash separate from the query to avoid timing attack ***
var_dump(sodium_crypto_auth_verify($user->Validator, $cookie[1], $storedKey);
}
}
Вариант 2: Кажется, немного проще и чище, потому что я просто сравниваю два хэша, и нет необходимости беспокоиться о ключе позже, но это означает, что я должен сохранить хешированную версию валидатора в куки:
$hashedToken = $token->GetSelector.':'.$token->GetValidatorHashHex();
setcookie('auth_token', $hashedToken, $expiry, '/', 'CONST_DOMAIN', true, true);
//Now On Request:
if(isset($_COOKIE['auth_token')){
$cookie = explode(':', $_COOKIE['auth_token'];
$user = DB::SelectUser($user);
if($user){
//Checks the Hash separate from the query to avoid timing attack
var_dump(hash_equals($user->Validator, $cookie[1]);
}
}
Я знаю, что это звучит глупо и не имеет особого значения, но в варианте 1 я сравниваю простой текстовый токен с хешированной версией и сравниваю его с функцией натрия. А с вариантом 2 я сравниваю двахэши
Если я сравниваю те же два хэша с функцией натрия, он возвращает false, а если я сравниваю простой текст с хэшем с hash_equals, даже если токен до хеша совпадает, он возвращает false.
Так что в основном:
1) Имеет ли это большое значение? 2) Я хотел бы найти правильное решение для хранения ключей, а затем сохранить обычный файл cookie, но не уверен, как
Буду признателен за любой совет. Рад уточнить мой вопрос Спасибо