Generando una contraseña aleatoria; ¿Por qué no es esto portátil?

21

Quiero generar una contraseña aleatoria, y lo estoy haciendo así:

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

En mi computadora portátil, que ejecuta Ubuntu, esto produce solo caracteres imprimibles, según lo previsto. Pero cuando entro en el servidor de mi escuela, que ejecuta Red Hat Enterprise Linux, y lo ejecuto allí, obtengo resultados como 3!ri�b�GrӴ��1�H�<�oM����&�nMC[�Pb�|L%MP�����9��fL2q���IFmsd|l�K, lo que no funcionará en absoluto. ¿Qué podría estar yendo mal aquí?

Taymon
fuente

Respuestas:

34

Es su problema local y tr .

Actualmente, GNU tr solo admite caracteres de un solo byte. Entonces, en entornos locales que usan codificaciones multibyte, la salida puede ser extraña:

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

El shell imprimirá los caracteres de varios bytes correctamente, pero GNU treliminará los bytes que considere no imprimibles.

Si desea que sea estable, debe establecer la configuración regional:

$ </dev/urandom LC_ALL=C tr -dc '[:print:]' | head -c 64
RSmuiFH+537z+iY4ySz`{Pv6mJg::RB;/-2^{QnKkImpGuMSq92D(6N8QF?Y9Co@
Cuonglm
fuente
14
+1 porque esto me hizo darme cuenta (al usar shells en Unix / Linux durante solo 30 años), que la redirección stdin / stdout / stderr no tiene que colocarse después del comando al que se aplica.
Anthon
Solo un comentario, si se establece un entorno local extraño, ¿no debería el shell aún poder imprimir los caracteres correctamente, incluso si no son ascii? ¿Al menos un caparazón competente (excluyendo xterm, por supuesto)?
orion
2
@orion: el shell imprimirá los caracteres correctamente. En este caso, ese es un problema tr. Eliminó bytes que cree que no se pueden imprimir, hacen que el resultado sea extraño.
Cuonglm 02 de
@orion Una secuencia de bytes aleatoria uniforme no será, en general, una secuencia aleatoria uniforme de codificaciones de caracteres UTF-8 bien formadas .
zwol
Además, a menos que sepa qué espacios en su contraseña, debe usar en :graph:lugar de :print::</dev/urandom LC_ALL=C tr -dc '[:graph:]' | head -c 64
edan
11

Considere en su lugar

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

Esto tiene dos ventajas:

  • Usted lee solo 48 bytes del dispositivo aleatorio, no ~ 8 KB; Si otros procesos en el mismo host necesitan números aleatorios, 8 KB agotados de una vez puede ser un problema grave. (Sí, podría decirse que nadie debería estar usando el dispositivo aleatorio de bloqueo , pero la gente ).

  • La salida de base64casi no contiene caracteres con significados especiales. (Para ninguno en absoluto, tachuela | tr +/ -_en el extremo, y (como en el ejemplo) asegurarse de que el número de bytes de entrada a base64es un múltiplo de 3.)

Una contraseña generada de esta manera tiene exactamente 384 bits de entropía, que es algo menor que lo que estaba haciendo (log 2 96 64 ≈ 421.4), pero más que suficiente para la mayoría de los propósitos (256 bits de entropía es seguro "todavía adivinando cuando El sol quema "territorio excepto para las claves RSA, AFAIK).

zwol
fuente
3

Otras personas ya señalaron que la configuración regional determina lo que [:print:]significa. Sin embargo, no todos los caracteres imprimibles son adecuados para contraseñas (ni siquiera en ascii). ¿Realmente no quieres espacios, pestañas y # $% ^? en su contraseña: no solo es difícil de recordar, también es potencialmente peligroso para el sistema de autenticación subyacente, puede ser imposible ingresar en un campo de entrada, etc. En este caso, debe seleccionar manualmente los caracteres "sanos":

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

o simplemente

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

O incluso mejor, use base64como se sugiere en otras respuestas.

Orión
fuente
Los humanos nunca ingresarán la contraseña en cuestión (si lo fuera, estaría usando Diceware) y estoy bastante seguro de que el sistema subyacente puede manejar caracteres especiales sin problemas. Gracias de cualquier manera.
Taymon
44
Lo que dices está completamente mal. Obligar a los usuarios a usar solo letras ascii, dígitos y guiones bajos reduce considerablemente el tamaño del alfabeto, lo que hace que sea mucho más fácil descifrar las contraseñas de los atacantes. Un sistema de autenticación que ni siquiera puede manejar ?o ^es demasiado malo para ser tomado en serio.
Bakuriu
2
Si su sistema de autenticación o los campos de entrada se ahogan con los símbolos ASCII normales ... entonces está haciendo algo mal y no se puede confiar en mi información privada. No hay absolutamente ninguna razón para no aceptar todo tipo de caracteres (incluidos los espacios) en sus contraseñas.
nzifnab
2
Parece que este no es el caso aquí, pero cuando se trata de información humana, es mucho más fácil recordar una contraseña alfanumérica larga que tiene un significado único para el propietario que una mezcla más corta de símbolos. También está el problema de ingresar estos caracteres en varios teclados (no todo el mundo tiene ^ en el primer nivel y la mayoría de las personas ni siquiera saben dónde o qué es una tecla de retroceso), los cuadros de entrada casi seguramente no pueden manejar el carácter de tabulación, y un sorprendente número de formularios web disponibles todavía son susceptibles a errores de validación, inyección de sql o incluso mayúsculas y minúsculas inciertas.
orion
1
Solo una nota: en C la [:print:]clase locale no incluye pestañas. Es solo [:alnum:]+ [:punct:]+ espacio (espacio único, no [:space:] ).
jimmij
2

Qué pasa

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

las cadenas deben imprimir la salida de urandom en un formato imprimible

Ladrón de ciegos
fuente
Esto da-bash: /dev/urandom: Permission denied
Anthon
lo siento olvidé al gato principal
Blindstealer 02 de
2

No sé si hay alguna razón por la que usas /dev/randompara generar la contraseña, pero te recomendaría usar pwgen para aliviar tu dolor.

$ pwgen -s 10 1

Donde 10 es la longitud de la contraseña.

http://man.cx/pwgen

Daniel
fuente
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

Este método en mi humilde opinión es más inteligente cuando se consumen datos de / dev / urandom. La cadena pegada como $ P $ P $ P ... debe tener al menos 256 caracteres de longitud.

Alexander Kelner
fuente