Générer un mot de passe aléatoire; pourquoi n'est-ce pas portable?


21

Je veux générer un mot de passe aléatoire, et je le fais comme ceci:

</dev/urandom tr -dc [:print:] | head -c 64

Sur mon ordinateur portable, qui exécute Ubuntu, cela ne produit que des caractères imprimables, comme prévu. Mais quand je ssh sur le serveur de mon école, qui exécute Red Hat Enterprise Linux, et que je l'exécute là-bas, j'obtiens des sorties comme 3!ri�b�GrӴ��1�H�<�oM����&�nMC[�Pb�|L%MP�����9��fL2q���IFmsd|l�K, ce qui ne fonctionnera pas du tout. Qu'est-ce qui pourrait mal tourner ici?

Réponses:


34

C'est votre problème local et tr .

Actuellement, GNU tr ne prend entièrement en charge que les caractères codés sur un octet. Donc, dans les environnements locaux utilisant des encodages multi-octets, la sortie peut être bizarre:

$ </dev/urandom LC_ALL=vi_VN.tcvn tr -dc '[:print:]' | head -c 64
`�pv���Z����c�ox"�O���%�YR��F�>��췔��ovȪ������^,<H ���>

Le shell imprimera correctement les caractères multi-octets, mais GNU trsupprimera les octets qu'il pense non imprimables.

Si vous voulez qu'il soit stable, vous devez définir les paramètres régionaux:

$ </dev/urandom LC_ALL=C tr -dc '[:print:]' | head -c 64
RSmuiFH+537z+iY4ySz`{Pv6mJg::RB;/-2^{QnKkImpGuMSq92D(6N8QF?Y9Co@

14
+1 parce que cela m'a fait réaliser (après avoir utilisé des shells sur Unix / Linux pendant seulement environ 30 ans), que la redirection stdin / stdout / stderr n'a pas besoin d'être positionnée après la commande à laquelle elle s'applique.
Anthon

Juste un commentaire, si des paramètres régionaux étranges sont définis, le shell ne devrait-il pas toujours être capable d'imprimer les caractères correctement, même s'ils ne sont pas ascii? Au moins un shell compétent (hors xterm bien sûr)?
orion

2
@orion: le shell imprimera correctement les caractères. Dans ce cas, c'est tr problème. Il a supprimé les octets qu'il pense non imprimables, ce qui rend le résultat étrange.
cuonglm

@orion Un flux d'octets uniformément aléatoire ne sera généralement pas un flux uniformément aléatoire d' encodages de caractères UTF-8 bien formés .
2015

De plus, à moins que vous ne :graph::print:</dev/urandom LC_ALL=C tr -dc '[:graph:]' | head -c 64
spécifiiez

11

Considérez plutôt

$ dd if=/dev/urandom bs=48 count=1 status=none | base64
imW/X60Sk9TQzl+mdS5PL7sfMy9k/qFBWWkzZjbYJttREsYpzIguWr/uRIhyisR7

Cela présente deux avantages:

  • Vous ne lisez que 48 octets à partir du périphérique aléatoire, pas ~ 8 Ko; si d'autres processus sur le même hôte nécessitent des nombres aléatoires, 8 Ko drainés en même temps peuvent être un problème grave. (Oui, sans doute personne ne devrait utiliser le dispositif aléatoire de blocage , mais les gens le font .)

  • La sortie de base64contient presque aucun caractère avec des significations spéciales. (Pour rien du tout, amure | tr +/ -_à la fin, et (comme dans l'exemple) assurez - vous que le nombre d'octets d' entrée à base64est un multiple de 3.)

Un mot de passe généré de cette façon a exactement 384 bits d'entropie, ce qui est un peu moins que ce que vous faisiez (journal 2 96 64 ≈ 421.4), mais plus que suffisant pour la plupart des fins (256 bits d'entropie sont en toute sécurité dans "toujours en devinant quand le Soleil brûle "territoire à l' exception des clés RSA, AFAIK).


3

D'autres personnes ont déjà souligné que les paramètres régionaux déterminent ce que cela [:print:]signifie. Cependant, tous les caractères imprimables ne conviennent pas aux mots de passe (même pas en ascii). Vous ne voulez vraiment pas d'espaces, de tabulations et de # $% ^? dans votre mot de passe - ce n'est pas seulement difficile à retenir, il est également potentiellement dangereux pour le système d'authentification sous-jacent, il peut être impossible d'entrer dans un champ de saisie, etc. Dans ce cas, vous devez simplement sélectionner manuellement les caractères "sains":

LC_ALL=C </dev/urandom tr -dc '[:alnum:]_' | head -c 64

ou simplement

</dev/urandom tr -dc 'A-Za-z0-9_' | head -c 64

Ou encore mieux, utilisez base64comme suggéré dans d'autres réponses.


Le mot de passe en question ne sera jamais entré par les humains (si c'était le cas, j'utiliserais Diceware à la place) et je suis sûr que le système sous-jacent peut gérer les caractères spéciaux sans problème. Merci quand même.
Taymon

4
Ce que vous dites est totalement faux. Forcer les utilisateurs à utiliser uniquement des lettres ascii, des chiffres et des traits de soulignement réduit considérablement la taille de l'alphabet, ce qui facilite considérablement la rupture des mots de passe pour les attaquants. Un système d'authentification qui ne peut même pas gérer ?ou ^est tout simplement trop mauvais pour être pris au sérieux.
Bakuriu

2
Si votre système d'authentification ou vos champs de saisie s'étouffent avec des symboles ASCII normaux ... alors vous faites quelque chose de mal et vous ne devez pas faire confiance à mes informations privées. Il n'y a absolument aucune raison de ne pas accepter toutes sortes de caractères (y compris les espaces) dans vos mots de passe.
nzifnab

2
Il semble que ce ne soit pas le cas ici, mais en ce qui concerne la saisie humaine, il est beaucoup plus facile de se souvenir d'un long mot de passe alphanumérique qui a une signification unique pour le propriétaire qu'un mélange de symboles plus court. Il y a aussi le problème de la saisie de ces caractères sur divers claviers (tout le monde n'a pas ^ au premier niveau et la plupart des gens ne savent même pas où ou ce qu'est un backtick), les zones de saisie ne peuvent presque certainement pas gérer le caractère de tabulation, et un un nombre surprenant de formulaires Web sont toujours sensibles aux erreurs de validation, à l'injection SQL ou même à une sensibilité à la casse incertaine.
orion

1
Juste une note: en C, la [:print:]classe locale ne comprend pas d'onglets. C'est seulement [:alnum:]+ [:punct:]+ espace (espace unique, pas [:space:] ).
jimmij

2

Qu'en est-il de

tr -dc [:print:] < /dev/urandom | head -c 64 | strings

les chaînes doivent imprimer la sortie d'urandom dans un format imprimable


Cela donne-bash: /dev/urandom: Permission denied
Anthon

désolé oublié le chat leader
Blindstealer

2

Je ne sais pas s'il y a une raison pour laquelle vous utilisez /dev/randompour générer le mot de passe, mais je vous recommanderais d'utiliser pwgen afin de soulager votre douleur.

$ pwgen -s 10 1

Où 10 est la longueur du mot de passe.

http://man.cx/pwgen


1
#Chars allowed in password (I don't like l,o,O, etc):
P="0123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz"

#Or such:
#P="a-zA-Z0-9"

head -c 8 < /dev/urandom | tr '\000-\377' "$P$P$P$P$P"
echo

Cette méthode à mon humble avis est plus intelligente lorsque vous consommez des données de / dev / urandom La chaîne collée comme $ P $ P $ P ... doit être d'au moins 256 caractères.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.