Odczyt z / dev / random nie generuje żadnych danych


19

Często używam polecenia

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

generować pseudolosowe hasła. To nie działa z /dev/random.

konkretnie

  • cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' produkuje dane wyjściowe
  • cat /dev/random | strings --bytes 1 produkuje dane wyjściowe
  • cat /dev/random | strings --bytes 1 | tr -d '\n\t ' nie wytwarza wyników

Uwaga: Podczas używania /dev/randommoże być konieczne poruszanie myszą lub naciskanie klawiszy (np. Ctrl, Shift itp.), Aby wygenerować entropię.

Dlaczego ostatni przykład nie działa? Czy trma jakiś duży wewnętrzny bufor, który /dev/urandomszybko się zapełnia, ale /dev/randomnie?

PS Używam CentOS 6.5

cat /proc/version
Linux version 2.6.32-431.3.1.el6.x86_64 (mockbuild@c6b10.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Jan 3 21:39:27 UTC 2014

jaka jest twoja dystrybucja, twoja wersja jądra? na Cygwin obie zwracają wartości.
Kiwy,

@Kiwy Zobacz edycję.
Aaron J Lang

1
Wiesz pwgenw szczególności pwgen -s?
MvG

2
-sPrzełącznik czyni je mniej zapamiętania, bardziej prawdziwie losowych. @Boyd: czy makepasswd jest szeroko dostępny poza dystrybucjami opartymi na Debianie? Z mojego punktu widzenia pwgen jest dostępny dla CentOS, podczas gdy makepasswd nie .
MvG

1
@BoydStephenSmithJr. Zgadzam się z @ MvG, który makepasswdnie jest dostępny na mojej platformie, mimo wszystko dzięki
Aaron J Lang

Odpowiedzi:


27

W końcu to nastąpi.

W:

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

cat nigdy nie buforuje, ale i tak jest zbędny, ponieważ nie ma tu nic do połączenia.

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

stringsjednak ponieważ jego sygnał wyjściowy nie jest już dłużej, terminal buforuje dane wyjściowe o bloki (czegoś w rodzaju 4 lub 8 kB), w przeciwieństwie do linii, gdy dane wyjściowe trafiają do terminala.

Zacznie więc zapisywać na standardowe wyjście, gdy zgromadzi znaki o wartości 4kB do wydania, co /dev/randomzajmie trochę czasu.

trdane wyjściowe trafiają do terminala (jeśli uruchamiasz go w wierszu poleceń powłoki w terminalu), więc buforuje dane wyjściowe liniowo. Ponieważ usuwasz \n, nigdy nie będzie miał pełnej linii do zapisu, więc zamiast tego zapisze, gdy tylko pełny blok zostanie zgromadzony (na przykład, gdy wyjście nie trafi do terminala).

Tak więc, trnie jest prawdopodobne, aby napisać coś aż stringsprzeczytał wystarczająca /dev/random, tak aby napisać 8kB (2 bloki prawdopodobnie wiele innych) danych (ponieważ pierwszy blok będzie prawdopodobnie zawierać pewne przełamane lub TAB lub przestrzeni znaków).

W tym systemie, w którym próbuję tego, mogę uzyskać średnio 3 bajty na sekundę /dev/random(w przeciwieństwie do 12 Mb na /dev/urandom), więc w najlepszym przypadku (pierwsze 4096 bajtów /dev/randomto wszystkie do wydrukowania), jesteśmy rozmowa 22 minuty przed tym, jak trzaczyna coś wydawać. Ale najprawdopodobniej będą to godziny (w szybkim teście widzę stringspisanie bloku co 1 do 2 odczytanych bloków, a bloki wyjściowe zawierają około 30% znaków nowego wiersza, więc spodziewam się, że będzie musiał przeczytać co najmniej 3 bloki wcześniej trma 4096 znaków do wydrukowania).

Aby tego uniknąć, możesz:

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

stdbuf to polecenie GNU (występujące również w niektórych BSD), które zmienia buforowanie poleceń stdio za pomocą lewy LD_PRELOAD.

Zauważ, że zamiast stringsmożesz użyć, tr -cd '[:graph:]'co spowoduje również wykluczenie tabulacji, nowej linii i spacji.

Możesz także poprawić ustawienia regionalne, aby Cuniknąć przyszłych niespodzianek ze znakami UTF-8.


wow, imponujące wyjaśnienie.
Kiwy

2
Niesamowity! Świetne wyjaśnienie i rozwiązanie. Zawsze używałem cat„bezużytecznego”, ponieważ nigdy nie lubiłem przekierowywać stdin na końcu potoku, teraz mogę „zapisać proces” i nadal mieć czytelne polecenia. Moje ostateczne rozwiązanie to< /dev/random stdbuf -o0 tr -Cd '[:graph:]' | stdbuf -o0 head --bytes 32
Aaron J Lang

@AaronJLang, dobra uwaga na temat [:graph:]. Zapomniałem o tym.
Stéphane Chazelas

@AaronJLang, nie potrzebne stdbufdla head -c32chyba że chcesz, aby to zapisywać dane tak szybko, jak to ma go (podobnie jak w kilku kawałkach, zamiast jednego kawałka 32byte jak tylko dostał je)
Stéphane Chazelas

2
Moim zdaniem, / dev / urandom jest w zupełności wystarczający do użytku autora. Jeśli ktoś byłby ciekawy, w jaki sposób konkretnie działa urandom w porównaniu do losowego, sugerowałbym przeczytanie komentarzy u góry sterownika w sterownikach / char / random.c drzewa źródeł jądra. W komentarzach wspomniano o analizie PRNG i jego realizacji. Mam nadzieję, że ten artykuł odpowie na pytanie „jak mniej więcej losowa jest przypadek w porównaniu do losowej?” Dostępne tutaj: eprint.iacr.org/2012/251.pdf
Eterfish

5

Generowanie liczb losowych dla wielu aplikacji bezpieczeństwa wymaga wystarczającej entropii - entropia mierzy, jak nieprzewidywalna jest losowość. Procesor deterministyczny nie może wygenerować entropii, więc entropia musi pochodzić z zewnątrz - albo ze składnika sprzętowego o niedeterministycznym zachowaniu, albo z innych czynników, które są wystarczająco trudne do odtworzenia, takich jak czas działania użytkownika (to tam, gdzie porusza się mysz wchodzi). Gdy dostępna jest wystarczająca entropia, można zastosować kryptografię do wygenerowania praktycznie nieograniczonego strumienia liczb losowych.

Linux działa poprzez gromadzenie entropii w puli, a następnie za pomocą kryptografii do generowania akceptowalnych liczb losowych zarówno przez, jak /dev/randomi przez /dev/urandom. Różnica polega na tym, że /dev/randomstosuje się wyjątkowo konserwatywne obliczenia entropii, które zmniejszają oszacowanie entropii w puli dla każdego generowanego bajtu, a /dev/urandomnie dotyczą samej ilości entropii w puli.

Jeśli oszacowanie entropii w puli jest zbyt niskie, /dev/randomblokuje się, aż można akumulować więcej entropii. Może to poważnie osłabić szybkość, z jaką /dev/randommoże wytwarzać produkcję. To właśnie tutaj obserwujesz. Nie ma to nic wspólnego tr; ale stringsodczytuje dane wyjściowe z buforowaniem, więc musi odczytać pełny bufor (kilka KB), /dev/randomaby wygenerować przynajmniej jeden bajt danych wejściowych.

/dev/urandomjest całkowicie akceptowalny do generowania klucza kryptograficznego , ponieważ entropia w rzeczywistości nie zmniejsza się w żaden zauważalny sposób. (Jeśli utrzymujesz swoją maszynę dłużej niż wszechświat istniał, nie możesz zaniedbać tych rozważań, ale poza tym jesteś dobry.) Jest tylko jeden przypadek, w którym /dev/urandomnie jest dobry, czyli na świeżo zainstalowanym systemie, który nie ma nie miał jeszcze czasu na wygenerowanie entropii lub świeżo uruchomionego systemu, który uruchamia się z nośnika tylko do odczytu.

Wyeliminowanie stringsz łańcucha rozruchowego prawdopodobnie przyspieszy proces. Poniżej trfiltrowane są znaki niedrukowalne:

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

Ale można użyć /dev/urandomtutaj , tak długo, jak zadbać, aby nie generować hasła w systemie, który nie miał czasu, aby zgromadzić wystarczającą entropię. Możesz sprawdzić poziom puli entropii Linuksa w /proc/sys/kernel/random/entropy_avail(jeśli użyjesz /dev/random, liczba w tym pliku będzie konserwatywna, być może bardzo).


1

Powinieneś użyć, /dev/urandomaby uzyskać wysokiej jakości (pseudo) liczby losowe i /dev/randomtylko wtedy, gdy absolutnie potrzebujesz liczb losowych, które są naprawdę nieprzewidywalne. Atakujący poniżej zasobów NSA będzie miał bardzo trudny do złamania /dev/urandom(i nie zapomnij o kryptografii węża gumowego ). Jądro wypełnia bufor „naprawdę losowymi” bajtami, co /dev/randomdaje. Niestety tempo, w jakim te są generowane jest niska, więc przeczytaniu wielu zz /dev/random będzie stoisko czeka na przypadkowości.

Możesz rozważyć użycie random.org lub jego generatora haseł lub jednego z wielu, wielu losowych generatorów haseł, które się zmieniają, spójrz np. Na tę stronę, aby uzyskać kilka wskazówek z wiersza poleceń (nie polecam wszystkich z nich , ale powinny dać ci pomysły), lub możesz użyć czegoś takiego mkpasswd(1)(tutaj w części Fedora 19 expect-5.45-8.fc19.x86_64).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.