web-dev-qa-db-fra.com

Génération d'un jeton impossible à deviner pour les e-mails de confirmation

Je génère un jeton à utiliser lorsque je clique sur le lien dans un e-mail de vérification. Je prévois d'utiliser niqid () mais la sortie sera prévisible permettant à un attaquant de contourner les e-mails de confirmation. Ma solution est de le hacher. Mais cela ne suffit toujours pas, car si le hachage que j'utilise est découvert, il sera toujours prévisible. La solution est de le saler. Que je ne sais pas comment faire parce que si j'utilise une fonction pour donner du sel variable (par exemple dans le pseudocode hash(uniqid()+time())), alors l'unicité du hachage n'est-elle plus garantie? Dois-je utiliser un hachage constant et ce serait suffisant (par exemple hash(uniqid()+asd741))

Je pense que toutes les réponses manquent un point important. Elle doit être unique. Que faire si openssl_random_pseudo_bytes() produit deux fois le même nombre? Ensuite, un utilisateur ne pourrait pas activer son compte. Le contre-argument des gens est-il qu'il est peu probable qu'il produise deux fois le même nombre? C'est pourquoi je considérais uniqid() parce que sa sortie est unique.

Je suppose que je pourrais utiliser les deux et les ajouter ensemble.

13
Celeritas

Vous voulez un caractère aléatoire impossible à deviner. Ensuite, utilisez un caractère aléatoire non devinable. Utilisez openssl_random_pseudo_bytes() qui se connectera au local PRNG cryptographiquement fort . N'utilisez pas Rand() ou mt_Rand() , car ceux-ci sont prévisibles (mt_Rand() est statistiquement bon mais il ne tient pas contre les attaquants sensibles). Ne faites pas de compromis, utilisez un bon PRNG. N'essayez pas de créer vous-même quelque chose en lançant une fonction de hachage et autres; seul le chagrin est au bout de ce chemin.

Générez 16 octets, puis encodez-les dans une chaîne si vous avez besoin d'une chaîne. bin2hex() code en hexadécimal; 16 octets deviennent 32 caractères. base64_encode() code dans Base64; 16 octets deviennent 24 caractères (les deux derniers étant des signes "=").

16 octets est 128 bits, c'est la "valeur sûre" rendant les collisions si improbables que vous n'avez pas à vous en préoccuper. Ne descendez pas en dessous de cela, sauf si vous avez une bonne raison (et, même dans ce cas, ne descendez pas en dessous de 16 de toute façon).

25
Tom Leek

Assurez-vous d'avoir support OpenSSL , et vous ne vous tromperez jamais avec ce one-liner

$token = bin2hex(openssl_random_pseudo_bytes(16));
18
Adi

Dans PHP 7, vous pouvez simplement utiliser random_bytes :

Génère une chaîne de longueur arbitraire d'octets aléatoires cryptographiques qui conviennent à une utilisation cryptographique, comme lors de la génération de sels, de clés ou de vecteurs d'initialisation.

Donc, pour générer un jeton hexadécimal de 16 octets, vous feriez:

$token = bin2hex(random_bytes(16));

Officiellement, rien ne garantit que tous les numéros seront uniques. Mais une collision est si improbable que vous feriez mieux de vous inquiéter d'être touché par une météorite.

1
Anders