odium_crypto_auth_verify против hash_equals для аутентификации токена - PullRequest
0 голосов
/ 23 октября 2019

Я строю свою собственную небольшую структуру для моего последнего года обучения в университете, и я очень запутался в передовой практике здесь. Я прочитал много статей и у меня есть общее представление, но некоторые пояснения были бы лучше.

Мне действительно нравится новое расширение натрия в 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, но не уверен, как

Буду признателен за любой совет. Рад уточнить мой вопрос Спасибо

1 Ответ

0 голосов
/ 24 октября 2019

Это не имеет никакого значения.

Что делает sodium_crypto_auth_verify(), так это вычисляет хэш и сравнивает его с предоставленным.

Пока сравнение выполняется в постоянном времени, нет никакой разницы между этим и выполнением этого самостоятельно.

...