Mengapa tr tidak dapat membaca dari / dev / urandom di OSX?

35

Seorang kolega menyarankan untuk membuat kunci acak melalui perintah berikut:

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

Itu memberi saya kesalahan:

tr: Urutan byte ilegal

Saya khawatir bahwa saya tidak memiliki /dev/urandomsistem saya. Saya mencoba googling untuk mencari tahu cara menginstal file ini, tetapi saya sudah kosong. Saya mencoba locate urandomdan juga muncul kosong. (Yah, sebenarnya, itu menemukan halaman manual, tapi itu tidak membantu)

Bagaimana cara saya membuat urandomtersedia di sistem Mac OSX saya? (Singa)

Kirk Woll
sumber
3
Penggunaan yang menarik dari xargs...
sendmoreinfo

Jawaban:

49

Berdasarkan pesan kesalahan yang Anda dapatkan, saya tidak berpikir / dev / urandom adalah masalahnya. Jika ya, saya akan mengharapkan kesalahan seperti "tidak ada file atau direktori".

Saya mencari pesan kesalahan yang Anda dapatkan dan menemukan ini, yang sepertinya relevan dengan masalah Anda: http://nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte- berikutnyaence

Pada dasarnya, tentukan lokal dengan menambahkan trperintah dengan LC_CTYPE=C:

LC_CTYPE=C tr -dc A-Za-z0-9_\!\@\#\$\%\^\&\*\(\)-+= < /dev/urandom | head -c 32 | xargs
lk-
sumber
Terima kasih, itu memang berhasil. Adakah gagasan mengapa saya tidak dapat menemukan urandomatau random? Apakah mereka "file" magis khusus yang tidak ada pada sistem file yang sebenarnya? (Juga saya menyarankan edit untuk membantu mengurangi tautan-busuk)
Kirk Woll
1
Saya percaya locatetidak secara langsung mencari sistem file Anda, tetapi mencari permintaan Anda menggunakan database yang sudah dibuat sebelumnya. Basis data ini kemungkinan besar dikonfigurasi untuk mengabaikan / dev / dan sistem file 'khusus' lainnya.
lk-
cukup adil, tapi saya tidak melihatnya ketika saya melihat langsung di /dev. Sosok pergi. Tapi sekali lagi terima kasih atas bantuannya.
Kirk Woll
1
sepertinya tidak bekerja pada 10.9; masih gagal dengan pesan kesalahan yang sama. LC_ALL=Cmelakukan trik tho.
Erik Allik
1
Silakan ubah tautan itu ke nerdbynature.de/s9y/2010/04/11/tr-Illegal-byte- berikutnya karena saat ini menunjuk ke halaman blog terbaru yang tidak mengandung trinformasi.
Jeroen Wiert Pluimers
11

trUpaya Anda untuk menafsirkan inputnya sebagai teks dalam pengkodean UTF-8. Jadi itu akan mengeluh dan membatalkan urutan byte pertama yang tidak valid UTF-8. Awalan trdengan LC_ALL=Catau LC_CTYPE=Cakan mengekspor variabel itu ke lingkungan tr, sehingga mengubah idenya tentang karakter lokal diatur ke standar C, yaitu semuanya hanya urutan byte buram.

Omong-omong, apakah urutan \)-+perintah Anda disengaja? Ini termasuk *juga, yang sudah Anda sertakan, tetapi tidak termasuk -itu sendiri seperti yang Anda maksudkan. Lebih baik menulis salah satu dari ini sebagai gantinya:

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

Seperti yang telah ditunjukkan orang lain, masalah Anda bukanlah yang /dev/urandomhilang, melainkan bagaimana cara trkerjanya pada OS X. Alih-alih bermain-main dengan enviornment varialbes, gunakan perlsebagai pengganti tr:

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

Ini memiliki keuntungan menjadi portabel di OS X, Redhat dan Ubuntu.

(Saya juga melepas pipa untuk xargs, mengganti penyihir echo, untuk mendapatkan baris baru di akhir output.)

Trenton
sumber
Cepat atau lambat, saya berharap Perl membuat binmode ":utf8"standar, pada titik mana solusi Perl Anda akan memiliki masalah yang trsama.
Tandai
Mengatasi masalah Mark dengan menambahkan binmode (STDIN, ": bytes") ke contoh kode.
Trenton
2

Pertama, apakah Anda bermaksud untuk memasukkan -atau *dalam daftar karakter yang valid? Parameter untuk trmemasukkan urutan )-+yang berarti "kisaran byte dimulai dengan )dan diakhiri dengan +, yang sebenarnya )*+.

Kedua, daripada membaca banyak kilobyte dari kumpulan entropi kernel (dan dengan demikian menandai keseluruhan kumpulan sebagai tidak aman, yang akan memengaruhi proses lain yang memerlukan entropi aman), pertimbangkan untuk membaca hanya sebanyak mungkin bit yang Anda butuhkan: gunakan head -c...sebagai langkah pertama , dan kemudian menerjemahkan alih-alih membuang karakter yang tidak diinginkan.

Versi khusus masalah ini agak tidak biasa karena menggunakan 76 simbol yang berbeda; kebanyakan hanya ingin alfanumerik, jadi jika Anda akan puas hanya dengan 64 simbol, maka menggunakan base64utilitas akan meminimalkan konsumsi kumpulan entropi (perhatikan bahwa 24 adalah 6/8 dari 32):

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

Pengkodean karakter lokal Anda (yang dapat Anda ketahui locale charmap) adalah multi-byte per karakter.

Yang paling umum saat ini adalah UTF-8 di mana karakter dapat dikodekan lebih dari 1 hingga 4 byte. Tidak semua urutan byte membentuk karakter yang valid di UTF-8. Setiap karakter non-ASCII dalam UTF-8 mulai dengan satu byte yang memiliki dua bit tertinggi yang ditetapkan dan memberi tahu berapa banyak byte dengan set bit tertinggi (tetapi bukan yang tertinggi kedua) diikuti.

/dev/urandomberisi aliran byte acak. trmentransliterasi karakter, sehingga perlu mendekode byte tersebut sebagai karakter. Semua karakter ASCII dalam jangkauan Anda semua dikodekan pada satu karakter di UTF-8, tetapi trmasih perlu mendekodekan semua karakter. Misalnya ada pengkodean multi-byte lainnya di mana beberapa karakter selain Aberisi 0x41 byte (kode untuk A).

Karena aliran byte acak itu pasti mengandung urutan yang tidak valid (misalnya 0x80 byte dengan sendirinya tidak valid dalam UTF-8 karena karakter non-ASCII harus dimulai dengan byte yang lebih besar dari 0xc1 (0xc0 dan 0xc1 tidak ada dalam UTF- 8 karakter)), jadi trkembali dengan kesalahan saat itu terjadi.

Apa yang Anda inginkan di sini adalah mempertimbangkan aliran byte sebagai karakter dalam penyandian yang memiliki satu byte per karakter. Apa pun yang Anda pilih tidak penting karena semua karakter dalam rentang Anda (dengan asumsi oleh AZ, yang Anda maksud adalah ABCDEFGHIJKLMNOPQRSTUVWXYZ dan bukan hal-hal seperti Ý, Ê) adalah bagian dari rangkaian karakter portabel sehingga dikodekan sama di semua rangkaian karakter yang didukung pada sistem Anda.

Untuk itu, Anda akan menetapkan LC_CTYPEvariabel lokalisasi yang merupakan variabel yang menentukan charset yang digunakan dan hal-hal seperti apa blank, alphakelas karakter berisi. Tetapi untuk definisi rentang AZ, Anda juga ingin mengatur LC_COLLATEvariabel (variabel yang menentukan urutan string).

The Calias POSIXlokal adalah salah satu yang jaminan karakter single-byte dan AZ adalah ABCDEFGHIJKLMNOPQRSTUVWXYZ. Anda bisa melakukannya:

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

(di sini memindahkan -ke ujung, jika tidak, )-+akan diambil sebagai rentang seperti A-Z)

Tetapi perhatikan bahwa LC_ALLvariabel menimpa semua variabel LC_*dan lainnya LANG. Jadi, jika LC_ALLsudah ditentukan, hal di atas tidak akan berpengaruh. Jadi, alih-alih, Anda cukup melakukannya:

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

Itu akan memengaruhi hal-hal lain seperti bahasa pesan kesalahan, tetapi bagaimanapun, mengubah LC_CTYPE bisa saja menjadi masalah untuk pesan kesalahan (misalnya, tidak ada cara untuk mengekspresikan pesan kesalahan Rusia atau Jepang di charset dari lokal C).

Stéphane Chazelas
sumber
0

Menurut halaman manual , / dev / random mungkin akan cukup untuk kebutuhan Anda. Mungkin Apple berhenti membuat / dev / urandom karena itu tidak perlu?

jsbillings
sumber
Saya juga tidak punya /dev/random.
Kirk Woll
MacOSX harus memiliki / dev / random dan / dev / urandom. Mungkin Apple tidak lagi memasukkan file-file khusus itu lagi? Atau mungkin itu hanya ada jika Anda menginstal XCode?
jsbillings
1
FWIW, kedua perangkat hadir di workstation Lion-upgrade-ke-Mountain Lion saya. Saya percaya itu ada di Lion, juga. Node juga berbeda (13,0 vs 13,1)
mrb