¿Por qué no puedo leer tr / dev / urandom en OSX?

35

Un colega sugirió crear una clave aleatoria mediante el siguiente comando:

tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs

Me dio el error:

tr: secuencia de bytes ilegal

Me preocupa que no tenga /dev/urandomen mi sistema. Intenté buscar en Google cómo instalar este archivo, pero he quedado vacío. Lo intenté locate urandomy también salió vacío. (bueno, en realidad, encontró la página de manual, pero eso no ayuda)

¿Cómo hago urandomdisponible en mi sistema Mac OSX? (León)

Kirk Woll
fuente
3
Uso interesante de xargs...
sendmoreinfo

Respuestas:

49

Según el mensaje de error que recibe, no creo que / dev / urandom sea el problema. Si lo fuera, esperaría un error como "no existe tal archivo o directorio".

Busqué el mensaje de error que recibiste y encontré esto, que parece ser relevante para tu problema: http://nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte-sequence

Básicamente, especifique la configuración regional anteponiendo el trcomando con LC_CTYPE=C:

LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs
lk-
fuente
Gracias, eso hizo el truco. ¿Alguna idea de por qué no puedo encontrar urandomo random? ¿Son "archivos" mágicos especiales que no existen en el sistema de archivos real? (También sugerí una edición para ayudar a mitigar la rotura de enlaces)
Kirk Woll
1
Creo locateque no busca directamente en su sistema de archivos, sino que busca su consulta utilizando una base de datos preconstruida. Es probable que esta base de datos esté configurada para ignorar / dev / y otros sistemas de archivos 'especiales'.
lk-
es justo, pero no lo veo cuando miro directamente /dev. Imagínate. Pero gracias de nuevo por la ayuda.
Kirk Woll
1
no parece funcionar en 10.9; Todavía falla con el mismo mensaje de error. LC_ALL=Chace el truco aunque.
Erik Kaplun
1
Cambie ese enlace a nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte-sequence ya que actualmente apunta a la página de blog más reciente que no contiene la trinformación.
Jeroen Wiert Pluimers
11

Sus trintentos de interpretar su entrada como texto en codificación UTF-8. Por lo tanto, se quejará y abortará en la primera secuencia de bytes que no es válida UTF-8. Prefijar trcon LC_ALL=Co LC_CTYPE=Cexportará esa variable al entorno de tr, cambiando así su idea del juego de caracteres local al estándar C, es decir, todo es solo una secuencia de bytes opacos.

Por cierto, ¿es la secuencia \)-+en su comando intencional? Esto también incluye *, lo que ya incluyó, pero no se incluye a -sí mismo como podría haber pensado. Mejor escribir uno de estos en su lugar:

LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()\-+=' < /dev/urandom
LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)\\-+= < /dev/urandom
MvG
fuente
6

Como otros han indicado, su problema no es que /dev/urandomfalte, sino cómo trfunciona en OS X. En lugar de perder el tiempo con el entorno varialbes, use perlen lugar de tr:

perl -pe 'binmode(STDIN, ":bytes"); tr/A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+=//dc;' < /dev/urandom | head -c 32; echo

Esto tiene la ventaja de ser portátil en OS X, Redhat y Ubuntu.

(También quité la tubería xargs, reemplazando a la bruja echo, para obtener una nueva línea al final de la salida).

Trenton
fuente
Tarde o temprano, espero que Perl haga binmode ":utf8"estándar, momento en el cual su solución Perl tendrá el mismo problema tr.
Mark
Se solucionó la preocupación de Mark agregando binmode (STDIN, ": bytes") a la muestra de código.
Trenton
2

En primer lugar, ¿pretendía incluir -o *en la lista de caracteres válidos? El parámetro a trincluye la secuencia )-+que significa "el rango de bytes que comienza )y termina con +, que en realidad es )*+.

En segundo lugar, en lugar de leer muchos kilobytes del grupo de entropía del núcleo (y así marcar todo el grupo como inseguro, lo que afectará a cualquier otro proceso que necesite entropía segura), considere leer solo la cantidad de bits que necesite: use head -c...como primer paso, y luego traduce en lugar de descartar caracteres no deseados.

Esta versión particular del problema es un poco inusual ya que utiliza 76 símbolos diferentes; la mayoría solo quiere alfanuméricos, por lo que si está satisfecho con solo 64 símbolos, el uso de la base64utilidad minimizará el consumo del grupo de entropía (tenga en cuenta que 24 es 6/8 de 32):

head -c24 < /dev/random | base64
Martin Kealey
fuente
1

La codificación de caracteres de su localidad (con la que se puede decir locale charmap) es de varios bytes por carácter.

El más común hoy en día es UTF-8, donde los caracteres se pueden codificar de 1 a 4 bytes. No todas las secuencias de bytes forman caracteres válidos en UTF-8. Cada carácter no ASCII en UTF-8 comienza con un byte que tiene los dos bits más altos establecidos y le dice cuántos bytes siguen con el juego de bits más alto (pero no el segundo más alto).

/dev/urandomcontiene una secuencia aleatoria de bytes. trtranslitera el carácter, por lo que necesita decodificar esos bytes como caracteres. Esos caracteres ASCII en su rango están codificados en un solo carácter en UTF-8, pero traún necesita decodificar todos los caracteres. Hay, por ejemplo, otras codificaciones de varios bytes donde algunos caracteres que no Acontienen el byte 0x41 (el código para A).

Debido a que ese flujo aleatorio de bytes está obligado a contener secuencias no válidas (por ejemplo, un byte 0x80 por sí mismo no es válido en UTF-8 ya que un carácter no ASCII tiene que comenzar con un byte mayor que 0xc1 (0xc0 y 0xc1 no están en UTF- 8 caracteres)), por lo que trvuelve con un error cuando eso sucede.

Lo que quiere aquí es considerar esa secuencia de bytes como caracteres en una codificación que tiene un byte por carácter. Lo que elija no es importante ya que todos esos caracteres en su rango (suponiendo que AZ, se refería a ABCDEFGHIJKLMNOPQRSTUVWXYZ y no cosas como Ý, Ê) son parte del conjunto de caracteres portátil, por lo que debe codificarse de la misma manera en todos los conjuntos de caracteres admitidos en su sistema.

Por eso, lo haces con la LC_CTYPEvariable de localización, que es el que decide qué juego de caracteres que se utilizan y qué cosas como blank, alphaclases de personajes contienen. Pero para la definición del rango AZ, también querrá establecer la LC_COLLATEvariable (la que decide el orden de las cadenas).

La configuración regional Caka POSIXes aquella que garantiza que los caracteres son de un solo byte y AZ es ABCDEFGHIJKLMNOPQRSTUVWXYZ. Podrías hacerlo:

 LC_CTYPE=C LC_COLLATE=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'

(aquí mover el -al final, de lo contrario, )-+se tomaría como un rango como A-Z)

Pero tenga en cuenta que la LC_ALLvariable anula todas las demás LC_*y LANGvariables. Entonces, si LC_ALLya está definido de otra manera, lo anterior no tendrá efecto. Entonces, en su lugar, simplemente puede hacer:

 LC_ALL=C tr -dc 'A-Za-z0-9_!@#$%^&*()+=-'

Eso afectará otras cosas como el idioma de los mensajes de error, pero de todos modos, cambiar LC_CTYPE ya podría haber sido un problema para los mensajes de error (por ejemplo, no hay forma de expresar mensajes de error en ruso o japonés en el conjunto de caracteres de la configuración regional C).

Stéphane Chazelas
fuente
0

Según la página de manual , / dev / random probablemente será suficiente para sus necesidades. ¿Quizás Apple dejó de crear / dev / urandom porque es innecesario?

jsbillings
fuente
Yo tampoco tengo /dev/random.
Kirk Woll
MacOSX debe tener tanto / dev / random como / dev / urandom. ¿Quizás Apple ya no incluye esos archivos especiales? ¿O tal vez solo está allí si instala XCode?
jsbillings
1
FWIW, ambos dispositivos están presentes en mi estación de trabajo Lion-actualizado a Mountain Lion. Creo que también estuvo presente en Lion. Los nodos también son diferentes (13,0 vs. 13,1)
mrb