les meilleures pratiques pour générer au hasard un jeton pour mot de passe oublié
Je veux générer identifiant mot de passe oublié . J'ai lu, je peux le faire en utilisant le timestamp avec la fonction mt_rand(), mais certaines personnes disent qu'horodatage peut ne pas être unique à chaque fois. Donc je suis un peu confus ici. Puis-je le faire avec l'aide d'horodatage avec cette ?
Question
Quelle est la meilleure pratique pour générer au hasard/unique jetons de longueur personnalisée?
Je sais qu'il ya beaucoup de questions qui sont posées ici, mais je suis plus confus après avoir lu les différents avis de différentes personnes.
- Un ordinateur ne peut pas diviser le temps illimité.
- désolé, ne reçoivent pas que.
- Vous obtiendrez la même heure si vous l'appelez par exemple d'une nano-seconde d'intervalle. Certaines fonctions de temps par exemple ne peut revenir de temps en 100ns étapes, certaines n'en secondes.
- ah, que. Oui. Je l'ai mentionné plus "classique" timestamp avec secondes seulement. Mais si la loi comme vous l'avez dit - oui (qui ne nous laisse plus que d'une option avec time machine pour obtenir des non-unique timestamp)
- essayé de générer 2 jetons en une seconde.
- Tête de en place, de la accepté de répondre à ne pas tirer parti d'une CSPRNG.
InformationsquelleAutor keen | 2013-09-20
Vous devez vous connecter pour publier un commentaire.
En PHP, l'utilisation
random_bytes()
. Raison: vous êtes à la recherche de la façon d'obtenir un rappel de mot de passe jeton, et, si c'est une seule fois vos identifiants de connexion, puis vous avez réellement des données à protéger (qui est - tout compte d'utilisateur)Donc, le code sera comme suit:
Mise à jour: les versions précédentes de cette réponse faisait allusion
uniqid()
et c'est incorrect si il y a une question de sécurité et pas seulement l'unicité.uniqid()
est essentiellement justemicrotime()
avec certains d'encodage. Il existe des moyens simples pour obtenir des prévisions précises de lamicrotime()
sur votre serveur. Un attaquant peut émettre une demande de réinitialisation de mot de passe, puis essayez à travers un couple de probablement les jetons. C'est aussi possible si more_entropy est utilisé, l'accroissement de l'entropie est de même faible. Grâce à @NikiC et @ScottArciszewski pour le rappeler.Pour plus de détails, voir
random_bytes()
n'est disponible que de PHP7. Pour les versions plus anciennes, la réponse par @yesitsme semble être la meilleure option.$length
? L'id de l'utilisateur? Ou quoi?Ceci répond à la " meilleure aléatoire de la demande:
Adi répondre1 de la Sécurité.StackExchange a une solution pour cela:
1. Adi, Lun Nov 12 2018, Celeritas, "Génération d'un impossible à deviner jeton pour les e-mails de confirmation", Sep 20 '13 à 7:06, https://security.stackexchange.com/a/40314/
openssl_random_pseudo_bytes($length)
- support: PHP 5 >= 5.3.0 , .......................................................... (Pour PHP 7, utilisationrandom_bytes($length)
) .......................................... (Pour PHP 5.3 ci-dessous - ne pas utiliser de PHP 5.3 ci-dessous)La version antérieure de la accepté de répondre (
md5(uniqid(mt_rand(), true))
) est incertain et ne propose qu'environ 2^60 sorties possibles, bien au sein de la gamme d'une attaque par force brute dans environ une semaine, pour un faible budget de l'attaquant:la fonction mt_rand()
est prévisible (et seulement ajoute jusqu'à 31 bits d'entropie)uniqid()
n'ajoute que jusqu'à 29 bits d'entropiemd5()
ne pas ajouter de l'entropie, c'est juste le mélange de façon déterministeDepuis un DES 56 bits de la clé peut être brute-force dans environ 24 heures, et un moyen serait d'environ 59 bits d'entropie, on peut calculer 2^59 /2^56 = 8 jours environ. En fonction de la façon dont ce jeton de vérification est mis en œuvre, il pourrait être possible de pratiquement fuite des informations de synchronisation et d'en déduire les N premiers octets d'un token valide.
Depuis que la question est à propos de "meilleures pratiques" et s'ouvre avec...
...on peut en déduire que ce jeton est implicite en matière de sécurité. Et lorsque vous ajoutez des exigences de sécurité à un générateur de nombres aléatoires, la meilleure pratique est de toujours utiliser un cryptographique sécurisé générateur de nombres pseudo-aléatoires (en abrégé CSPRNG).
À l'aide d'un CSPRNG
En PHP 7, vous pouvez utiliser
bin2hex(random_bytes($n))
(où$n
est un entier supérieur à 15).En PHP 5, vous pouvez utiliser
random_compat
pour exposer la même API.Sinon,
bin2hex(mcrypt_create_iv($n, MCRYPT_DEV_URANDOM))
si vous avezext/mcrypt
installé. Une autre bonne-liner estbin2hex(openssl_random_pseudo_bytes($n))
.La séparation de la Recherche dans le programme de validation
Tirant de mon précédent travail sur sécurisée "se souvenir de moi" cookies en PHP, le seul moyen efficace pour atténuer ladite synchronisation de fuite (généralement mis en place par la requête de base de données) est de séparer la recherche de la validation.
Si votre table ressemble à ceci (MySQL)...
... vous avez besoin d'ajouter une autre colonne,
selector
, comme suit:Utiliser un CSPRNG Lorsqu'une réinitialisation de mot de passe est délivré, d'envoyer à la fois des valeurs à l'utilisateur de stocker le sélecteur et un hachage SHA-256 de la hasard un jeton dans la base de données. Utilisez le sélecteur de saisir le hachage et l'ID Utilisateur de calculer le hachage SHA-256 du jeton de l'utilisateur fournit avec celui stocké dans la base de données à l'aide de
hash_equals()
.Exemple De Code
La génération d'un token en PHP 7 (5,6 avec random_compat) avec PDO:
La vérification de l'utilisateur fourni token:
Ces extraits de code ne sont pas des solutions complètes (j'ai évité la validation de l'entrée et du cadre des intégrations), mais ils devraient servir d'exemple de ce à faire.
hash('sha256', bin2hex($token))
, 2) vérifier avecif (hash_equals(hash('sha256', $validator), $results[0]['token'])) {...
? Merci!id
que le sélecteur? Je veux dire, la clé primaire de laaccount_recovery
table. Nous n'avons pas besoin de couche de sécurité supplémentaire pour le sélecteur, faites-nous? Merci!id:secret
est OK.selector:secret
est OK.secret
lui-même ne l'est pas. L'objectif est de séparer la requête de base de données (ce qui est le timing qui fuit) à partir du protocole d'authentification (qui doit être à temps constant).openssl_random_pseudo_bytes
au lieurandom_bytes
si est en cours d'exécution de PHP 5.6? Aussi, ne devriez-vous pas ajouter simplement le sélecteur et pas le validateur dans la querystring du lien?paragonie/random_compat
au lieu de PHP 5.6.Vous pouvez également utiliser DEV_RANDOM, où 128 = 1/2 le jeton généré longueur. Le Code ci-dessous génère 256 jeton.
MCRYPT_DEV_URANDOM
surMCRYPT_DEV_RANDOM
.Cela peut être utile lorsque vous avez besoin d'un très très aléatoire jeton