Anda mengamati kombinasi dari perilaku aneh dd
dengan perilaku aneh /dev/random
Linux . Ngomong-ngomong, keduanya jarang menjadi alat yang tepat untuk pekerjaan itu.
/dev/random
Linux mengembalikan data dengan hemat. Ini didasarkan pada asumsi bahwa entropi dalam generator bilangan acak semu dipadamkan dengan sangat cepat. Karena mengumpulkan entropi baru lambat, /dev/random
biasanya melepaskan hanya beberapa byte dalam satu waktu.
dd
adalah program lama dan rewel yang awalnya dimaksudkan untuk beroperasi pada perangkat pita. Saat Anda menyuruhnya membaca satu blok 1kB, ia mencoba membaca satu blok. Jika pembacaan mengembalikan kurang dari 1024 byte, sulit, hanya itu yang Anda dapatkan. Jadi dd if=/dev/random bs=1K count=2
buat dua read(2)
panggilan. Karena membaca dari /dev/random
, kedua read
panggilan biasanya mengembalikan hanya beberapa byte, dalam jumlah yang bervariasi tergantung pada entropi yang tersedia. Lihat juga Kapan dd cocok untuk menyalin data? (atau, kapan read() dan write() parsial)
Kecuali jika Anda merancang installer atau cloner OS, Anda tidak boleh menggunakan /dev/random
di Linux, selalu /dev/urandom
. urandom
halaman manual agak menyesatkan; /dev/urandom
sebenarnya cocok untuk kriptografi, bahkan untuk menghasilkan kunci berumur panjang. Satu-satunya batasan dengan /dev/urandom
apakah itu harus dilengkapi dengan entropi yang cukup; Distribusi Linux biasanya menyimpan entropi di antara reboot, jadi satu-satunya saat Anda mungkin tidak memiliki cukup entropi adalah pada instalasi baru. Entropi tidak luntur dalam istilah praktis. Untuk informasi selengkapnya, baca Apakah rand dari /dev/urandom aman untuk kunci login? dan Feeding /dev/random entropy pool?.
Sebagian besar menggunakan dd
lebih baik diekspresikan dengan alat seperti head
atau tail
. Jika Anda ingin 2 kB byte acak, jalankan
head -c 2k </dev/urandom >rand
Dengan kernel Linux yang lebih lama, Anda dapat menggunakan
dd if=/dev/urandom of=rand bs=1k count=2
karena /dev/urandom
dengan senang hati mengembalikan byte sebanyak yang diminta. Tapi ini tidak berlaku lagi sejak kernel 3.16, sekarang dibatasi hingga 32MB.
Secara umum, saat Anda perlu menggunakan dd
untuk mengekstrak jumlah byte tetap dan inputnya tidak berasal dari file biasa atau perangkat blok, Anda perlu membaca byte demi byte:dd bs=1 count=2048
.
Dari man 4 random
pada kotak RHEL 5:
Saat dibaca, perangkat /dev/random hanya akan mengembalikan byte acak dalam perkiraan jumlah bit derau di kumpulan entropi.
Saya mendapatkan file berukuran 213 byte di mesin itu. Kembali ke man 4 acak:
Saat dibaca, perangkat /dev/urandom akan mengembalikan byte sebanyak yang diminta.
Saya mendapatkan 2048 byte dari setiap pemanggilan dd if=/dev/urandom of=rand bs=1K count=2
Saya menyimpulkan bahwa perbedaannya adalah karena berapa banyak entropi yang dihasilkan mesin Anda antara pemanggilan dd if=/dev/random ...
Mengapa dd
jatuhkan datanya? ... Gilles telah mengajukan pertanyaan menarik tentang dd
:
Kapan dd cocok untuk menyalin data? (atau, kapan read() dan write() sebagian)
Berikut kutipan dari pertanyaan itu:
*... tidak sulit untuk menyalahkan dd; misalnya coba kode ini:**
yes | dd of=out bs=1024k count=10
dan periksa ukuran file keluar (kemungkinan di bawah 10 MB).
Selain dari komentar saya (di akhir pertanyaan Anda), hal seperti ini menarik untuk ditonton ... Ini menangkap byte Anda dalam file $trnd
. Saya telah memilih secara semi-sewenang-wenang bs=8
Gerakkan mouse Anda dan lihat kecepatannya.
Dengan komputer saya menganggur (AFK dan tidak ada aktivitas Jaringan), dan setelah menghabiskan kumpulan entropi, butuh waktu 2 jam 12 menit untuk mengumpulkan hanya 1192 byte, pada saat itu saya membatalkannya.
Kemudian, dengan saya menggerakkan mouse terus menerus, waktu yang dibutuhkan relatif lebih singkat 1 menit 15 detik untuk mengumpulkan jumlah byte yang sama.
Ini menunjukkan dengan sangat jelas bahwa mengumpulkan entropi bukan berdasarkan kecepatan CPU, melainkan peristiwa acak berbasis, dan bahwa sistem Ubuntu saya menggunakan mouse sebagai salah satu signifikan faktor acak.
get=2048
trnd=/tmp/$USER.rnd; >"$trnd"
while (( $(wc -c <"$trnd") < $get )) ;do
dd if=/dev/random bs=8 count=1 2>/dev/null >>"$trnd"
echo -n "itt: $((i+=1)) ct: "; wc -c <"$trnd"
done
truncate -s $get "$trnd"
echo -e "\nfinal count: "; wc -c <"$trnd"