Почему запись в / dev / random не делает параллельное чтение из / dev / random быстрее?


22

Обычно чтение из /dev/randomдает 100-500 байтов и блоков, ожидая сбора энтропии.

Почему запись информации /dev/randomдругими процессами не ускоряет чтение? Разве это не должно обеспечить необходимую энтропию?

Это может быть полезно для разблокировки gpgили аналогичного программного обеспечения без перезапуска и повторного ввода всего, для генерации не сверхсекретных секретных ключей и т. Д.



1
Как перейти gpg --gen-keyот /dev/randomк /dev/urandomбез перезагрузки?
Ви.

IIRC gpgимеет /dev/randomжестко закодированы. Вы можете изменить конфигурацию udev, чтобы сделать /dev/randomто же устройство /dev/urandom, что и другие возможности.
Жиль "ТАК - перестань быть злым"

@ Жиль, он все еще требует перезапуска gpg --gen-key, поэтому повторно вводит данные, которые он запрашивает в интерактивном режиме (или использует более умные методы, такие как указание большего количества параметров командной строки). Также время ЦП, генерирующее простое число, может быть потеряно (gpg может работать минуту, печатать некоторые +es и затем запрашивать дополнительные случайные данные). И это дает ощущение «давайте вернемся и пойдем другим путем» вместо «давайте возьмем молоток и заставим его двигаться вперед» ...
Vi.

Ответы:


19

Вы можете писать, /dev/randomпотому что это часть способа предоставления дополнительных случайных байтов /dev/random, но этого недостаточно, вы также должны уведомить систему о наличии дополнительной энтропии посредством ioctl()вызова.

Мне нужна была та же функциональность для тестирования моей программы установки смарт-карт , так как я не хотел ждать, пока моя мышь / клавиатура сгенерирует достаточно для нескольких вызовов, gpgкоторые были сделаны для каждого запуска теста. Что я сделал, так это запустил программу Python, которая следует параллельно с моими тестами. Конечно, его вообще не следует использовать для gpgгенерации реального ключа, так как случайная строка вовсе не случайна (сгенерированная системой случайная информация все равно будет чередоваться). Если у вас есть внешний источник, для которого нужно установить строку random, то вы должны иметь высокую энтропию. Вы можете проверить энтропию с:

cat /proc/sys/kernel/random/entropy_avail

Программа:

#!/usr/bin/env python
# For testing purposes only 
# DO NOT USE THIS, THIS DOES NOT PROVIDE ENTROPY TO /dev/random, JUST BYTES

import fcntl
import time
import struct

RNDADDENTROPY=0x40085203

while True:
    random = "3420348024823049823-984230942049832423l4j2l42j"
    t = struct.pack("ii32s", 8, 32, random)
    with open("/dev/random", mode='wb') as fp:
        # as fp has a method fileno(), you can pass it to ioctl
        res = fcntl.ioctl(fp, RNDADDENTROPY, t)
    time.sleep(0.001)

(Не забудьте убить программу после того, как вы закончите.)


1
Гораздо проще было бы использовать решение rngd. Он доступен как пакет в большинстве (всех?) Дистрибутивов.
Патрик

4
random = "3420348024823049823-984230942049832423l4j2l42j"см. xkcd.com/221
user253751

@Patrick Я попробовал по крайней мере 3 потенциальных решения для добавления случайности, IIRC rngd был одним из них. Но они не будут работать "из коробки" (это может быть установка Ubuntu 12.04 в то время), и для меня это решение с 10 строками кода было проще.
Anthon

@Anthon: как sidenote, я не выгляжу xs4all.nl, так как mitnik использовал его для хранения некоторых вещей, десятилетия назад ... :)
woliveirajr

@woliveirajr, мой аккаунт от hacktic.nl был перенесен туда где-то в 1992 году, я был там некоторое время, хотя я уже 20 лет не живу в Нидерландах.
Anthon

14

Как правило, он разработан разработчиками ядра и задокументирован в man 4 random:

Writing to /dev/random or /dev/urandom will update the entropy pool
with the data written, but this will not result in a higher entropy
count.  This means that it will impact the contents read from both
files, but it will not make reads from /dev/random faster.

1

Энтони уже объяснил, что запись в /dev/randomне увеличивает счет энтропии, и показал, как RNDADDENTROPY ioctl (см. Random (4) ) можно использовать для подсчета энтропии. Это, очевидно, не совсем безопасно, поэтому здесь есть альтернатива, когда доступен аппаратный генератор случайных чисел.

Следующие реализации берут 512 байтов (4096 битов) случайности /dev/hwrngи направляют ее в пул энтропии (зачисление 4 битов энтропии на байт, это произвольный выбор от меня). После этого он вызовет системный вызов select (2) для блокировки при заполнении пула энтропии (задокументировано на странице random (4) ).

Версия Python:

import fcntl, select, struct
with open('/dev/hwrng', 'rb') as hw, open('/dev/random') as rnd:
    while True:
        d = hw.read(512)
        fcntl.ioctl(rnd, 0x40085203, struct.pack('ii', 4 * len(d), len(d)) + d)
        select.select([], [rnd], [])

Поскольку в Arch Linux iso не был установлен Python, здесь также есть версия Perl:

open my $hw, "</dev/hwrng" and open my $rnd, "</dev/random" or die;
for (;;) {
    my $l = read $hw, my $d, 512;
    ioctl $rnd, 0x40085203, pack("ii", 4 * $l, $l) . $d or die;
    vec(my $w, fileno $rnd, 1) = 1;
    select undef, $w, undef, undef
}

Это, вероятно, то, что делает программа rngd (часть rng-tools ) (не проверено), за исключением того, что она использует инструменты (Python или Perl), которые уже общедоступны.


Если у вас нет аппаратного генератора случайных чисел, вы можете использовать /dev/urandomвместо него, /dev/hwrngесли вы абсолютно не заботитесь о небезопасных случайных значениях .
Лекенштейн

Хм, я обнаружил, что устройства hwrng автоматически генерируют энтропию, когда это необходимо, никаких дополнительных rngd или сценариев не требуется. Однако при getrandom()использовании hwrng в ядрах старше 4.8-rc1 возникает ошибка, приводящая к блокированию. Чтобы обойти это read()дважды /dev/random, смотрите github.com/Lekensteyn/archdir/commit/…
Lekensteyn
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.