Membaca dari / dev / acak tidak menghasilkan data apa pun

19

Saya sering menggunakan perintah

cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' | head --bytes 32

untuk menghasilkan kata sandi pseudo-acak. Ini tidak berfungsi /dev/random.

Secara khusus

  • cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' menghasilkan output
  • cat /dev/random | strings --bytes 1 menghasilkan output
  • cat /dev/random | strings --bytes 1 | tr -d '\n\t ' tidak menghasilkan output

NB: Saat menggunakan, /dev/randomAnda mungkin harus menggoyangkan mouse atau menekan tombol (mis. Ctrl, shift, dll.) Untuk menghasilkan entropi.

Mengapa contoh terakhir tidak berfungsi? Apakah trmemiliki semacam buffer internal besar yang /dev/urandommengisi dengan cepat tetapi /dev/randomtidak?

PS Saya menggunakan CentOS 6.5

cat /proc/version
Linux version 2.6.32-431.3.1.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Jan 3 21:39:27 UTC 2014
Aaron J Lang
sumber
apa distribusi Anda, versi kernel Anda? pada Cygwin keduanya mengembalikan nilai.
Kiwy
@ Kiwy Lihat edit.
Aaron J Lang
1
Anda tahu pwgen, khususnya pwgen -s?
MvG
2
The -sswitch membuat mereka kurang berkesan, lebih benar-benar acak. @ Boy: apakah makepasswd tersedia luas di luar distro berbasis Debian? Cara saya melihatnya, pwgen tersedia untuk CentOS sedangkan makepasswd tidak .
MvG
1
@BoydStephenSmithJr. Saya setuju dengan @ MvG yang makepasswdtidak tersedia di platform saya, terima kasih
Aaron J Lang

Jawaban:

27

Akhirnya akan.

Di:

cat /dev/random | strings --bytes 1 | tr -d '\n\t '

cat tidak akan pernah buffer, tapi itu berlebihan karena tidak ada yang digabungkan di sini.

< /dev/random strings --bytes 1 | tr -d '\n\t '

stringsmeskipun, karena outputnya tidak lagi terminal akan buffer outputnya dengan blok (sekitar 4 atau 8kB) sebagai lawan dari garis ketika output pergi ke terminal.

Jadi itu hanya akan mulai menulis ke stdout ketika telah mengumpulkan karakter senilai 4kB untuk output, yang /dev/randomakan memakan waktu cukup lama.

troutput masuk ke terminal (jika Anda menjalankannya pada prompt shell di terminal), sehingga output akan buffer-line. Karena Anda menghapusnya \n, itu tidak akan pernah memiliki baris penuh untuk ditulis, jadi alih-alih, itu akan menulis begitu blok penuh telah terakumulasi (seperti ketika output tidak pergi ke terminal).

Jadi, trkemungkinan tidak akan menulis apa pun sampai stringscukup membaca dari /dev/randomsehingga dapat menulis 8kB (2 blok mungkin lebih banyak) data (karena blok pertama mungkin akan berisi beberapa baris baru atau tab atau karakter spasi).

Pada sistem ini saya mencoba ini, saya bisa mendapatkan rata-rata 3 byte per detik dari /dev/random(dibandingkan dengan 12MiB pada /dev/urandom), jadi dalam skenario kasus terbaik (4096 byte pertama dari /dev/randomsemua yang dapat dicetak), kami berbicara 22 menit sebelum trmulai mengeluarkan apa pun. Tapi itu lebih cenderung berjam-jam (dalam tes cepat, saya bisa melihat stringsmenulis blok setiap 1 hingga 2 blok dibaca, dan blok keluaran berisi sekitar 30% dari karakter baris baru, jadi saya berharap itu akan perlu dibaca setidaknya 3 blok sebelumnya trmemiliki 4096 karakter untuk ditampilkan).

Untuk menghindarinya, Anda bisa melakukan:

< /dev/random stdbuf -o0 strings --bytes 1 | stdbuf -o0 tr -d '\n\t '

stdbuf adalah perintah GNU (juga ditemukan pada beberapa BSD) yang mengubah buffering perintah stdio melalui trik LD_PRELOAD.

Perhatikan bahwa alih-alih strings, Anda dapat menggunakan tr -cd '[:graph:]'yang juga akan mengecualikan tab, baris baru, dan spasi.

Anda mungkin ingin memperbaiki lokasi Cjuga untuk menghindari kemungkinan kejutan di masa mendatang dengan karakter UTF-8.

Stéphane Chazelas
sumber
wow penjelasan yang mengesankan.
Kiwy
2
Luar biasa! Penjelasan dan solusi hebat. Saya selalu menggunakan cat'sia-sia' karena saya tidak pernah suka mengarahkan ulang stdin di akhir pipa, sekarang saya bisa 'menyimpan proses' dan masih memiliki perintah yang dapat dibaca. Solusi terakhir saya adalah< /dev/random stdbuf -o0 tr -Cd '[:graph:]' | stdbuf -o0 head --bytes 32
Aaron J Lang
@ AaronJLang, poin bagus tentang [:graph:]. Saya sudah lupa tentang itu.
Stéphane Chazelas
@AaronJLang, Anda tidak perlu stdbufuntuk head -c32kecuali Anda ingin mengizinkannya untuk menulis data begitu mendapatkannya (seperti dalam beberapa potongan bukannya satu potongan 32byte segera setelah itu mendapatkannya)
Stéphane Chazelas
2
Menurut pendapat saya, / dev / urandom cukup memadai untuk digunakan penulis. Jika seseorang penasaran bagaimana, secara khusus, urandom berfungsi dibandingkan dengan acak, saya sarankan membaca komentar di bagian atas driver di driver / char / random.c dari pohon kode sumber kernel. Komentar tersebut menyebutkan analisis PRNG dan implementasinya. Mudah-mudahan, makalah ini akan menjawab pertanyaan "seberapa banyak kurang lebih acak adalah urandom dibandingkan dengan acak?" Tersedia di sini: eprint.iacr.org/2012/251.pdf
etherfish
5

Menghasilkan angka acak untuk banyak aplikasi keamanan memerlukan entropi yang cukup - tindakan entropi seberapa tidak dapat diprediksinya keacakan. Prosesor deterministik tidak dapat menghasilkan entropi, sehingga entropi harus berasal dari luar - baik dari komponen perangkat keras dengan perilaku non-deterministik, atau dari faktor lain yang cukup sulit untuk direproduksi, seperti waktu tindakan pengguna (di situlah menggoyangkan mouse) masuk). Setelah cukup entropi tersedia, kriptografi dapat digunakan untuk menghasilkan aliran angka acak yang praktis tak terbatas.

Linux bekerja dengan mengakumulasi entropi dalam kumpulan, kemudian menggunakan kriptografi untuk menghasilkan angka acak yang dapat diterima baik melalui /dev/randomdan /dev/urandom. Perbedaannya adalah bahwa /dev/randommenerapkan perhitungan entropi yang sangat konservatif yang mengurangi estimasi entropi di pool untuk setiap byte yang dihasilkannya, sedangkan /dev/urandomtidak mementingkan dirinya sendiri dengan jumlah entropi di pool.

Jika estimasi entropi di pool terlalu rendah, /dev/randomblok sampai lebih banyak entropi dapat diakumulasikan. Ini dapat sangat melumpuhkan tingkat di mana /dev/randomdapat menghasilkan output. Inilah yang Anda amati di sini. Itu tidak ada hubungannya dengan tr; tetapi stringsmembaca output dengan buffering, sehingga harus membaca buffer penuh (beberapa KB) dari /dev/randomhanya untuk menghasilkan setidaknya satu byte input.

/dev/urandomsangat dapat diterima untuk menghasilkan kunci kriptografi , karena entropi sebenarnya tidak menurun dengan cara apa pun yang terlihat. (Jika Anda menjaga mesin Anda berjalan lebih lama dari yang ada di dunia, Anda tidak dapat mengabaikan pertimbangan ini, tetapi jika tidak, Anda baik.) Hanya ada satu kasus di mana /dev/urandomtidak baik, yaitu pada sistem yang baru diinstal yang tidak memiliki belum punya waktu untuk membuat entropi, atau sistem yang baru saja di-boot yang boot dari media read-only.

Menghilangkan stringsdari rantai boot Anda mungkin akan mempercepat proses Anda. Di bawah ini trakan menyaring karakter non-cetak:

</dev/random LC_ALL=C tr -dc '!-~'

Tetapi Anda dapat menggunakan di /dev/urandomsini , selama Anda berhati-hati untuk tidak menghasilkan kata sandi pada sistem yang belum punya waktu untuk mengakumulasikan entropi yang memadai. Anda dapat memeriksa level pool entropi Linux /proc/sys/kernel/random/entropy_avail(jika Anda menggunakan /dev/random, gambar dalam file ini akan konservatif, mungkin sangat banyak).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
1

Anda harus menggunakan /dev/urandomuntuk mendapatkan nomor acak berkualitas tinggi (semu), dan /dev/randomhanya ketika Anda benar-benar membutuhkan nomor acak yang benar-benar tidak dapat diprediksi. Seorang penyerang di bawah sumber daya NSA akan memiliki waktu yang sangat sulit untuk retak /dev/urandom(dan jangan lupa tentang kriptografi selang karet ). Kernel mengisi buffer dengan byte "benar-benar acak", itulah yang /dev/randommemberi. Sayangnya tingkat di mana mereka dihasilkan rendah, jadi membaca banyak dari dari /dev/random akan menunda menunggu keacakan.

Anda dapat mempertimbangkan untuk menggunakan random.org atau pembuat kata sandinya , atau salah satu dari banyak, banyak pembuat kata sandi acak yang beredar, lihat misalnya halaman ini untuk beberapa tips baris perintah (bukan karena saya akan merekomendasikan semuanya) , tetapi mereka harus memberi Anda ide), atau Anda dapat menggunakan sesuatu seperti mkpasswd(1)(di sini di bagian Fedora 19 expect-5.45-8.fc19.x86_64).

vonbrand
sumber