Por que não é possível ler tr / dev / urandom no OSX?


35

Um colega sugeriu a criação de uma chave aleatória por meio do seguinte comando:

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

Isso me deu o erro:

tr: sequência de bytes ilegal

Estou preocupado que eu não tenho /dev/urandomno meu sistema. Tentei pesquisar no Google para descobrir como instalar esse arquivo, mas acabei vazio. Eu tentei locate urandome também vim vazio. (na verdade, ele encontrou a página de manual, mas isso não ajuda)

Como urandomdisponibilizo no meu sistema Mac OSX? (Leão)


3
Uso interessante de xargs...
sendmoreinfo 16/05

Respostas:


49

Com base na mensagem de erro que você recebe, não acho que / dev / urandom seja o problema. Se assim fosse, esperaria um erro como "nenhum arquivo ou diretório".

Procurei a mensagem de erro que você recebeu e a encontrou, o que parece ser relevante para o seu problema: http://nerdbynature.de/s9y/2010/04/11/11/tr-Illegal-byte-sequence

Basicamente, especifique o código do idioma acrescentando o trcomando com LC_CTYPE=C:

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

Obrigado, isso realmente fez o truque. Alguma idéia de por que não consigo encontrar urandomou random? Eles são "arquivos" mágicos especiais que não existem no sistema de arquivos real? (Também sugeri uma edição para ajudar a mitigar link-rot)
Kirk Woll

11
Acredito locateque não pesquisa diretamente seu sistema de arquivos, mas consulta sua consulta usando um banco de dados pré-criado. Este banco de dados provavelmente está configurado para ignorar o / dev / e outros sistemas de arquivos 'especiais'.
lk-

justo o suficiente, mas não vejo quando olho diretamente para dentro /dev. Vai saber. Mas obrigado novamente pela ajuda.
Kirk Woll

11
parece não funcionar no 10.9; ainda falha com a mesma mensagem de erro. LC_ALL=Cfaz o truque tho.
Erik Allik

11
Altere esse link para nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte-sequence, pois atualmente ele aponta para a página mais recente do blog que não contém as trinformações.
Jeroen Wiert Pluimers

11

Suas trtentativas de interpretar sua entrada como texto na codificação UTF-8. Portanto, ele irá reclamar e interromper a sequência de primeiro byte que não é válida UTF-8. Prefixar trcom LC_ALL=Cou LC_CTYPE=Cvai exportar essa variável no ambiente de tr, mudando assim a sua ideia do conjunto de caracteres local para o padrão C, ou seja, tudo é apenas uma seqüência de bytes opacos.

A propósito, a sequência \)-+em seu comando é intencional? Isso inclui *também o que você já incluiu, mas não inclui a -si próprio como você poderia ter planejado. Melhor escrever um destes:

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

6

Como outros já indicaram, seu problema não é o que /dev/urandomestá faltando, mas como trfunciona no OS X. Em vez de brincar com o ambiente varialbes, use perlno lugar de tr:

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

Isso tem a vantagem de ser portátil no OS X, Redhat e Ubuntu.

(Também removi o tubo para xargs, substituindo o bruxo echo, para obter uma nova linha no final da saída.)


Cedo ou tarde, espero que o Perl faça o binmode ":utf8"padrão; nesse momento, sua solução Perl terá o mesmo problema que trele.
Mark

Resolvido o problema de Mark adicionando binmode (STDIN, ": bytes") ao exemplo de código.
Trenton

2

Em primeiro lugar, você pretendia incluir -ou *na lista de caracteres válidos? O parâmetro para trinclui a sequência, )-+que significa "o intervalo de bytes que começa )e termina com +, o que é realmente )*+.

Em segundo lugar, em vez de ler muitos kilobytes do pool de entropia do kernel (e, assim, marcar todo o pool como inseguro, o que afetará qualquer outro processo que precise de entropia segura), considere ler apenas quantos bits forem necessários: use head -c...como a primeira etapa, e depois traduza em vez de descartar caracteres indesejados.

Essa versão específica do problema é um pouco incomum, pois usa 76 símbolos diferentes; a maioria quer apenas alfanuméricos; portanto, se você estiver satisfeito com apenas 64 símbolos, o uso do base64utilitário minimizará o consumo do pool de entropia (observe que 24 é 6/8 de 32):

head -c24 < /dev/random | base64

1

A codificação de caracteres da localidade (com a qual você pode contar locale charmap) é de vários bytes por caractere.

Atualmente, o mais comum é o UTF-8, onde os caracteres podem ser codificados com mais de 1 a 4 bytes. Nem todas as seqüências de bytes formam caracteres válidos em UTF-8. Todo caractere não ASCII do UTF-8 começa com um byte com os dois bits mais altos definidos e informa quantos bytes com o conjunto de bits mais alto (mas não o segundo mais alto) a seguir.

/dev/urandomcontém um fluxo aleatório de bytes. trtranslitera caracteres, portanto, é necessário decodificar esses bytes como caracteres. Esses caracteres ASCII no seu intervalo são todos codificados em um caractere em UTF-8, mas trainda precisam decodificar todos os caracteres. Por exemplo, existem outras codificações de vários bytes em que alguns caracteres que não Acontêm o byte 0x41 (o código para A).

Como esse fluxo aleatório de bytes deve conter sequências inválidas (por exemplo, um byte de 0x80 é inválido em UTF-8, pois um caractere não ASCII deve iniciar com um byte maior que 0xc1 (0xc0 e 0xc1 não possui UTF- 8 caracteres)), então trretorna com um erro quando isso acontece.

O que você deseja aqui é considerar esse fluxo de bytes como caracteres em uma codificação que possui um byte por caractere. Seja qual você escolher não é importante como todos os personagens em sua faixa (assumindo por AZ, você significou ABCDEFGHIJKLMNOPQRSTUVWXYZ e não coisas como Ý, Ê) fazem parte do conjunto de caracteres portátil para ser codificado o mesmo em todos os conjuntos de caracteres suportados no sistema.

Para isso, você deve definir a LC_CTYPEvariável localização, que é a que decide qual charset é usado eo que coisas como blank, alphaclasses de personagens conter. Mas para a definição do intervalo AZ, você também desejará definir a LC_COLLATEvariável (a que decide a ordem das strings).

O Ccódigo de POSIXidioma aka é aquele que garante que os caracteres sejam bytes únicos e AZ é ABCDEFGHIJKLMNOPQRSTUVWXYZ. Você poderia fazer:

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

(aqui, mover o -para o final, caso contrário, )-+seria aceito como um intervalo A-Z)

Mas observe que a LC_ALLvariável substitui todas as outras LC_*e LANGvariáveis. Portanto, se LC_ALLjá estiver definido de outra forma, o acima não terá efeito. Então, você pode simplesmente fazer:

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

Isso afetará outras coisas, como o idioma das mensagens de erro, mas, de qualquer maneira, alterar LC_CTYPE já pode ter sido um problema para mensagens de erro (por exemplo, nenhuma maneira de expressar mensagens de erro em russo ou japonês no conjunto de caracteres do código de idioma C).


0

De acordo com a página de manual , / dev / random provavelmente será suficiente para suas necessidades. Talvez a Apple tenha deixado de criar o / dev / urandom porque é desnecessário?


Eu também não tenho /dev/random.
22412 Kirk Woll

O MacOSX deve ter / dev / random e / dev / urandom. Talvez a Apple não inclua mais esses arquivos especiais? Ou talvez só esteja lá se você instalar o XCode?
Jsbillings

11
FWIW, ambos os dispositivos estão presentes na minha estação de trabalho Lion-upgrade-to-Mountain Lion. Eu acredito que estava presente no Lion também. Os nós são diferentes, bem como (13,0 vs 13,1)
MRB
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.