Generare una password casuale; perché non è portatile?


21

Voglio generare una password casuale e lo sto facendo in questo modo:

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

Sul mio laptop, che esegue Ubuntu, questo produce solo caratteri stampabili, come previsto. Ma quando inserisco il server della mia scuola, che esegue Red Hat Enterprise Linux, e lo eseguo lì, ottengo output simili 3!ri�b�GrӴ��1�H�<�oM����&�nMC[�Pb�|L%MP�����9��fL2q���IFmsd|l�K, che non funzioneranno affatto. Cosa potrebbe andare storto qui?

Risposte:


34

È il tuo problema locale e tr .

Attualmente, GNU tr supporta completamente solo caratteri a byte singolo. Quindi, nelle versioni locali che utilizzano codifiche multibyte, l'output può essere strano:

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

La shell stamperà correttamente i caratteri multibyte, ma GNU trrimuoverà i byte che ritiene non stampabili.

Se vuoi che sia stabile, devi impostare le impostazioni locali:

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

14
+1 perché questo mi ha fatto capire (avendo usato shell su Unix / Linux solo per circa 30 anni), che il reindirizzamento stdin / stdout / stderr non deve essere posizionato dopo il comando a cui si applica.
Anthon,

Solo un commento, se è impostata una strana locale, la shell non dovrebbe essere ancora in grado di stampare correttamente i caratteri, anche se non sono ascii? Almeno una shell competente (escluso ovviamente xterm)?
Orione,

2
@orion: la shell stamperà correttamente i caratteri. In questo caso, questo è un problema. Ha rimosso i byte che ritiene non stampabili, rendono strano il risultato.
cuonglm

@orion Un flusso di byte uniformemente casuale non sarà, in generale, un flusso uniformemente casuale di codifiche di caratteri UTF-8 ben formati .
zwol,

Inoltre, a meno che tu non abbia spazio nella tua password, dovresti usare :graph:invece di :print::</dev/urandom LC_ALL=C tr -dc '[:graph:]' | head -c 64
edan,

11

Considerare invece

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

Questo ha due vantaggi:

  • Leggi solo 48 byte dal dispositivo casuale, non ~ 8 KB; se altri processi sullo stesso host richiedono numeri casuali, 8 KB scaricati tutti in una volta possono essere un problema serio. (Sì, probabilmente nessuno dovrebbe usare il dispositivo di blocco casuale, ma la gente lo fa .)

  • L'output di non base64contiene quasi caratteri con significati speciali. (Per nessuna, tack | tr +/ -_sull'estremità, e (come nell'esempio) assicurarsi che il numero di byte di ingresso a base64è un multiplo di 3.)

Una password generata in questo modo ha esattamente 384 bit di entropia, che è in qualche modo inferiore a quello che stavi facendo (log 2 96 64 ≈ 421.4), ma più che sufficiente per la maggior parte degli scopi (256 bit di entropia sono "indovinabili" quando indovinando ancora Il sole brucia "territorio ad eccezione delle chiavi RSA, AFAIK).


3

Altre persone hanno già sottolineato che la localizzazione determina cosa [:print:]significa. Tuttavia, non tutti i caratteri stampabili sono adatti per le password (nemmeno in ascii). Davvero non vuoi spazi, tabulazioni e # $% ^? nella tua password - non è solo difficile da ricordare, è anche potenzialmente pericoloso per il sistema di autenticazione sottostante, potrebbe essere impossibile entrare in un campo di input e così via. In questo caso, devi semplicemente selezionare manualmente i caratteri "sani":

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

o semplicemente

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

O ancora meglio, usa base64come suggerito in altre risposte.


La password in questione non verrà mai inserita dagli umani (se invece dovessi usare Diceware) e sono abbastanza sicuro che il sistema sottostante possa gestire caratteri speciali senza problemi. Grazie comunque.
Taymon,

4
Quello che dici è assolutamente sbagliato. Forzare gli utenti a usare solo lettere ASCII, cifre e caratteri di sottolineatura riduce considerevolmente le dimensioni dell'alfabeto, rendendo molto più semplice la violazione delle password per gli aggressori. Un sistema di autenticazione che non può nemmeno gestire ?o ^è semplicemente troppo male per essere preso sul serio.
Bakuriu,

2
Se il tuo sistema di autenticazione o i campi di input soffocano sui normali simboli ASCII ... allora stai facendo qualcosa di sbagliato e non ti devi fidare delle mie informazioni private. Non c'è assolutamente alcun motivo per non accettare tutti i tipi di caratteri (compresi gli spazi) nelle password.
nzifnab,

2
Sembra che questo non sia il caso qui, ma quando si tratta di input umani, è molto più facile ricordare una lunga password alfanumerica che ha un significato unico per il proprietario di un miscuglio più breve di simboli. C'è anche il problema di inserire questi caratteri su varie tastiere (non tutti hanno ^ al primo livello e la maggior parte delle persone non sa nemmeno dove o cosa sia un backtick), quasi sicuramente le caselle di input non sono in grado di gestire il carattere di tabulazione, e un un numero sorprendente di moduli web disponibili è ancora suscettibile di errori di convalida, iniezione sql o persino incertezza sulla distinzione tra maiuscole e minuscole.
Orione,

1
Solo una nota: in C la [:print:]classe locale non include le schede. È solo [:alnum:]+ [:punct:]+ spazio (spazio singolo, non [:space:] ).
jimmij,

2

Che dire

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

le stringhe dovrebbero stampare l'output di urandom in un formato stampabile


Questo dà-bash: /dev/urandom: Permission denied
Anthon il

scusa
ho

2

Non so se c'è qualche motivo per cui usi /dev/randomper generare la password, ma ti consiglierei di usare pwgen per alleviare il dolore.

$ pwgen -s 10 1

Dove 10 è la lunghezza della password.

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

Questo metodo IMHO è più intelligente quando si consumano dati da / dev / urandom La stringa incollata come $ P $ P $ P ... deve essere lunga almeno 256 caratteri.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.