Neden / dev / random'dan dd farklı dosya boyutları veriyor?


26

Bir ubuntu sisteminde aşağıdaki komutu çalıştırıyorum:

dd if=/dev/random of=rand bs=1K count=2

Ancak, her çalıştırdığımda farklı boyutta bir dosyayla bitirdim. Bu neden? Rasgele verilerle dolu bir boyutta bir dosyayı nasıl oluşturabilirim?


1
/dev/randomİstediğiniz basamak sayısını oluşturmak için yeterli entropi yoksa engeller. sadece bu kadar yüksek kalitede psuedo rasgele "rastgelelik" miktarı toplamak için zaman alır ... Ya /dev/urandomdaha az rastgele "rastgele" bir değer kullanın ya da entropi havuzunuzu kontrol edin (bir döngüde ve gerektiği gibi bekleyin)
Peter.O

Ayrıca bu soruya bakınız .
Keith Thompson,

3
sadece ekleyiniflag=fullblock
frostschutz 23:15

Yanıtlar:


31

Kendine ddözgü davranışının Linux'ların kendine özgü davranışıyla bir kombinasyonunu gözlemliyorsunuz /dev/random. Her ikisi de, bu arada, nadiren iş için doğru araçtır.

Linux /dev/randomveriyi azar azar geri veriyor. Sözde rasgele sayı üretecindeki entropinin çok hızlı bir şekilde söndüğü varsayımına dayanmaktadır. Yeni entropi toplamak yavaş olduğundan, /dev/randomtipik olarak bir seferde sadece birkaç bayt bırakılır.

ddbaşlangıçta teyp cihazlarında çalışması amaçlanan eski, huysuz bir programdır. 1kB'lik bir bloğu okumasını söylediğinizde, bir bloğu okumaya çalışır. Okuma, 1024 bayttan daha az döndürürse, zor, tüm elde ettiğiniz budur. Böylece dd if=/dev/random bs=1K count=2iki read(2)arama yapar . Okuduğundan beri /dev/random, iki readçağrı genellikle mevcut entropiye bağlı olarak değişen sayılarda yalnızca birkaç bayt döndürür. Ayrıca bakınız Veri kopyalamak için ne zaman uygun? (veya okunduğunda () ve (() kısmi yazdığında)

Bir işletim sistemi yükleyicisi veya klonlayıcı tasarlamadığınız sürece, hiçbir /dev/randomzaman Linux altında kullanmamalısınız /dev/urandom. urandomAdam sayfası biraz yanıltıcıdır; /dev/urandomaslında uzun ömürlü anahtarlar üretmek için bile kriptografi için uygundur. Tek sınırlama /dev/urandom, yeterli entropi ile tedarik edilmesi gerektiği; Linux dağıtımları normalde yeniden başlatmalar arasındaki entropiyi korur, bu nedenle yeterli entropiye sahip olmadığınız tek zaman yeni bir kurulumdadır. Entropi pratik anlamda aşınmaz. Daha fazla bilgi için, bkz. Giriş anahtarı için / dev / urandom'dan bir rand güvenli midir? ve Beslenme / dev / rastgele entropi havuzu? .

Kullanımlarının çoğu, veya ddgibi araçlarla daha iyi ifade edilir . 2kB rasgele bayt istiyorsanız, çalıştırınheadtail

head -c 2k </dev/urandom >rand

Eski Linux çekirdeği ile, uzaklaşabilirsiniz

dd if=/dev/urandom of=rand bs=1k count=2

çünkü /dev/urandommutlu bir şekilde istenildiği kadar çok bayt döndürdü. Ancak bu, 3.16 çekirdeğinden bu yana artık doğru değil, şimdi 32 MB ile sınırlandırıldı .

Genel olarak, ddsabit sayıda bayt ayıklamak için kullanmanız gerektiğinde ve girişi normal bir dosyadan veya blok cihazdan gelmiyorsa, bayt: byte okumalısınız dd bs=1 count=2048.


Gd yerine kafa kullandığınız için teşekkür ederiz. İsterseniz hala / dev / random kullanmama izin veriyor. Her ne kadar / dev / urandom, bahsettiğiniz gibi muhtemelen yeterli olsa da, ihtiyaç duyulduğunda / dev / random'ı nasıl kullanacağınızı bilmek güzel.
Daniel,

3.16'dan beri çekirdekler /dev/urandom başına 32m döndürürread() .
mikeserv 23.03

Alternatif olarak, POSIX uyumlu bir komuta ihtiyacınız varsa, buradaki püf noktasını kullanabilirsiniz: unix.stackexchange.com/a/192114dd if=/dev/urandom ibs=1k obs=1k | dd bs=1k count=2
Rufflewind

11

Gönderen man 4 randombir RHEL 5 kutuyu:

Okunduğunda, / dev / random cihazı sadece entropi havuzundaki tahmini gürültü bit sayısı içindeki rastgele baytları döndürür.

Bu makinede 213 bayt boyutunda dosyalar alıyorum. 4. adama geri dön:

Okunduğunda, / dev / urandom cihazı istenildiği kadar bayt döndürecektir.

Her çağrımda 2048 bayt alıyorum dd if=/dev/urandom of=rand bs=1K count=2

Aradaki farkın, makinenizin çağrıları arasında ne kadar entropi oluşturduğu nedeniyle ortaya çıkar dd if=/dev/random ...


Evet, pratik olarak, gerçek bir şifreleme uygulaması olmadığı sürece, @Daniel / dev / urandom kullanmalıdır. Ancak dd if=/dev/random bs=1K count=2entropi havuzu görünüşte boşaltıldığında neden durduğuna şaşırmıştım . Belgelerde, daha entropi olana kadar engellemesi gerekir, bu nedenle dddosya, yalnızca mevcut havuzu boşaltmak ve çıkmak yerine yavaşça yazacaktır.
cjc

Bunu da merak ettim, ama RHEL, Slackware 13.1 ve oldukça güncel bir Arch ile tutarlı. RHEL x86_64, diğerleri 32-bit idi. Maalesef dd belgeleri GNU bilgi biçiminde, bu yüzden hepsini okumamıştım.
Bruce Ediger,

Aynı zamanda Gentoo'da da tutarlı.
Matthew Scharley

4
@cjc: Engelleyici bir FD'yi çağırdığınızda read(fd, mybuf, 1024), temel alınan cihaz bazı verileri döndürdüğü anda döner . Okunacak 1024 bayt varsa, bunu döndürür. Yalnızca 201 bayt varsa, 201 değerini döndürür. Kullanılabilir 0 bayt varsa, en az bir bayt kullanılabilir duruma gelinceye kadar engeller, sonra onu döndürür.
Warren Young,

@WarrenYoung / dev / random'den okuma mu içeriğini boşaltır? Sanırım öyle.
Michael Martinez,

5

Neden ddveri düşüyor? ... Gilles , şu ilgi çekici soruyu sordu dd:
Ne zaman veri kopyalamak için uygun? (veya okunduğunda () ve (() kısmi yazdığında)
İşte bu sorudan alıntı

    * ... dd'yi hataya sokmak zor değil; örneğin bu kodu deneyin: **
        yes | dd of=out bs=1024k count=10
    ve çıkış dosyasının boyutunu kontrol edin (10 MB'ın altında olması muhtemeldir).


Yorumumun yanı sıra (sorunuzun sonunda), bunun gibi bir şey izlemek çok ilginç ... Baytlarınızı dosyada yakalar $trnd. Yarı-rasgele seçtim bs = 8

Farenizi hareket ettirin ve hızlanmasını izleyin.
Bilgisayarım boştayken (AFK ve Ağ etkinliği yok) ve entropi havuzunu tükettikten sonra, yalnızca 1192 bayt toplaması 2 saat 12 dakika sürdü , bu noktada iptal ettim.

Sonra, fareyi sürekli hareket ettirdiğimde , aynı sayıda baytı toplamak için 1 dakika 15 saniye daha kısa sürdü .

Bu, entropi toplamanın CPU hızına dayalı olmadığını, aksine rasgele olaylara dayalı olduğunu ve Ubuntu sistemimin fareyi önemli rastgele faktörlerinden biri olarak kullandığını açıkça göstermektedir .

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"

1

ddolduğu tasarlanmış engelleme için - genellikle emrinde iyi araçtır değişken büyüklükte girdilerden okumak için siz tamam gerekirse derhal çünkü ddakım tampon olmaz bazı geleceğe okur write() (eğer çok açık bir şekilde ibs daha büyük obs ile bu şekilde yapılandırmak sürece) ama olacak yerine write()her şeyi o en kısa sürede okur read()bunu s (ve isteğe bunu işler) .

İşte bazı önemli tanımlar :

  • ibs=expr
    • Giriş bloğu boyutunu bayt olarak belirtin (varsayılan 512) .expr
  • obs=expr
    • Çıktı bloğu boyutunu bayt olarak belirtin (varsayılan 512) .expr
  • bs=expr
    • İçin hem giriş hem de çıkış bloğu boyutlarını ayarlama exprbayt yerine geçer ibs=ve obs=. Daha dönüşüm için diğer ise sync, noerrorve notruncbelirtilen her bir giriş bloğu kısa blok yığılmasma neden olmadan tek bir blok olarak çıkışına kopyalanmalıdır.

Gördüğünüz Yani, ne zaman ibsve obsolarak birlikte tanımlanır bssonra ibsya sonra, özel olup olmadığını, aksi ama - önceliklidir obsveya cbsyok.

İşte ibsen önemli olan bir örnek . /dev/randomHavuzun ne kadar sürede dolduğunu izlemek istersen böyle bir şey yapabilirsin ...

dd "ibs=$size" conv=sync "count=$lmt" \ 
    if=/dev/random of="$somefile"

if=Hedefi hiç okunabildiği sürece , her zaman aynı boyutta bir çıktı dosyasına ddyol syncaçacaktır , çünkü boş değerlerde okunan blokları tıkar. Başka bir deyişle, dd read()bir giriş bloğu için s ise $((size=10)) $((count=5))ve read()dosya 2 byte, sonra 8 byte, sonra 12 byte, sonra 2 byte, sonra 4 byte döndürürse, bunun yerine bir dosya ddyazacaktır.

 2 read bytes 8NULs \
 8 read bytes 2NULs \
10 read bytes 0NULs \
 4 read bytes 6NULs \
 4 read bytes 6NULs

... çünkü ddvarsayılan olarak gelmez, değil geciktirir. Dolayısıyla yayın içi akışı izlemeniz ve başka bir işlemin yazılarını sınırlandırmanız gerekirse, ddsizin için bir araçtır.

Eğer sadece bir miktar veriyi düzenli bir dosyaya yazarsanız, burada yapılan diğer ifadelerin aksine, ddbunun için de kullanabilirsiniz - ve oldukça kolay - ama birden fazla ve güvenilir bir engelleme faktörüne ihtiyacınız olacak .

Örneğin, eğer yaptıysanız:

{   dd ibs="$size" obs="${size}x$block_factor" |
    dd bs="${size}x$blockfactor" "count=$lmt"
}  <infile >outfile

... birincisi dd, her ibs="$size"biri ile ikincisi arasındaki boruya en az bir obs="${size}x$block_factor"çıkış bloğunu doldurmak için gereken sayıda giriş bloğu tamponlar . Bu, ikincisinin çıkışı güvenli bir şekilde sınırlayabileceği anlamına gelir; çünkü ilk yapanların tümü, bunu yapmak için ilk önce ne kadar yapmaları gerektiğine bakılmaksızın , giriş / çıkışları ile aynı olacaktır .write()ddddcount="$lmt"write()read()dd

Ve budd şekilde, küçük bir matematik dersi ile boruları veya diğer özel dosya türlerini güvenilir bir şekilde okumak için kullanabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.