Крошечный и независимый от платформы генератор случайных чисел для любой FPGA (и даже ASIC).
NeoTRNG призван стать небольшим и независимым от платформы генератором случайных чисел TRUE (TRNG), который можно синтезировать для любой целевой технологии (FPGA и даже ASIC). Он основан на простых автономных кольцевых генераторах, которые усовершенствованы с помощью специальной технологии , позволяющей осуществлять синтез для любой платформы. Фазовый шум , возникающий при дискретизации автономных кольцевых генераторов, используется в качестве физического источника энтропии.
Этот проект является «побочным продуктом» процессора NEORV32 RISC-V, в котором neoTRNG реализован как модуль SoC по умолчанию.
Ключевые особенности
Осторожность
Вполне возможно, что между внутренними/внешними сигналами/событиями и сгенерированными случайными числами может существовать хотя бы некоторая взаимная корреляция. Следовательно, нет никакой гарантии, что neoTRNG предоставит идеальные или даже криптографически безопасные случайные числа! Посмотрите предоставленные результаты оценки или (что еще лучше) протестируйте их самостоятельно. Кроме того, пока не существует механизма обнаружения взлома или онлайн-мониторинга работоспособности, позволяющего проверить целостность/качество сгенерированных случайных данных.
Предупреждение
Постоянное включение neoTRNG приведет к увеличению динамического энергопотребления, а также может вызвать локальный нагрев чипа (при использовании очень больших конфигураций). Кроме того, конструкция может создавать дополнительные электромагнитные помехи (ЭМП).
Весь проект реализован в виде одного файла VHDL rtl/neoTRNG.vhd
, который вообще не имеет зависимостей (например, специальных библиотек, пакетов или подмодулей).
entity neoTRNG is
generic (
NUM_CELLS : natural range 1 to 99 := 3 ; -- number of ring-oscillator cells
NUM_INV_START : natural range 3 to 99 := 5 ; -- number of inverters in first cell, has to be odd
SIM_MODE : boolean := false -- enable simulation mode (no physical random if enabled!)
);
port (
clk_i : in std_ulogic ; -- module clock
rstn_i : in std_ulogic ; -- module reset, low-active, async, optional
enable_i : in std_ulogic ; -- module enable (high-active)
valid_o : out std_ulogic ; -- data_o is valid when set (high for one cycle)
data_o : out std_ulogic_vector ( 7 downto 0 ) -- random data byte output
);
end neoTRNG ;
NeoTRNG использует единый тактовый домен, управляемый сигналом clk_i
. Сигнал сброса модуля rstn_i
является необязательным (привязывается к '1'
если не используется). Случайные данные получаются с использованием простого интерфейса data/valid: всякий раз, когда доступен новый действительный случайный байт, выходной сигнал valid_o
будет высоким ровно в течение одного цикла, поэтому выходной сигнал data_o
может быть выбран пользовательской логикой.
Сигнал enable_i
используется для инициализации и запуска TRNG. Прежде чем можно будет использовать TRNG, этот сигнал должен поддерживаться на низком уровне в течение как минимум нескольких 100 тактов (в зависимости от конфигурации), чтобы гарантировать, что все биты внутренних сдвиговых регистров снова очищены. Когда enable_i
установлен, а valid_o
установлен впервые, TRNG работает. Отключение TRNG также требует, чтобы enable_i
был низким в течение того же количества тактов. Когда enable_i
становится низким, все кольцевые генераторы будут остановлены, что приведет к снижению активности динамического переключения и энергопотребления.
Для настройки neoTRNG предусмотрены три дженерика. NUM_CELLS
определяет общее количество ячеек энтропии. NUM_INV_START
определяет количество инверторов (= длина кольцевого генератора) в самой первой ячейке. Эти два обобщения подробно описаны в разделе «Архитектура» ниже. Последний общий SIM_MODE
может быть установлен, чтобы позволить моделировать TRNG в рамках простой симуляции RTL.
NeoTRNG основан на настраиваемом количестве ( NUM_CELLS
) энтропийных ячеек. Каждая ячейка представляет собой простой кольцевой генератор («RO»), построенный с использованием нечетного числа инверторов. Частота колебаний RO определяется задержкой распространения элементов внутри кольца. Эта частота не является статичной, поскольку она подвержена минимальным колебаниям, вызванным тепловым шумом, электронным дробовым шумом. Состояние последнего инвертора RO записывается в триггер с помощью статических часов ( clk_i
). Поскольку частота RO хаотично меняется со временем, собственный фазовый шум выборочных данных используется в качестве фактического источника энтропии.
Каждая энтропийная ячейка генерирует 1-битный поток случайных данных. Выходные данные всех ячеек смешиваются с использованием широкого вентиля XOR, прежде чем поток будет смещен с помощью простого экстрактора случайных чисел. Несколько несмещенных битов выбираются/десериализуются блоком выборки для получения случайного числа шириной в байт. Блок выборки также применяет простую постобработку для улучшения спектрального распределения случайных чисел.
Каждая энтропийная ячейка состоит из кольцевого генератора, состоящего из нечетного числа инвертирующих защелок . Длина кольца в самой первой энтропийной ячейке определяется обобщенным параметром NUM_INV_START
. Каждая дополнительная энтропийная ячейка добавляет к этой начальной длине цепи еще 2 инвертора. Следовательно, каждая дополнительная энтропийная ячейка колеблется с более низкой частотой, чем предыдущая.
Асинхронные элементы, такие как кольцевые генераторы, сложно реализовать независимо от платформы, поскольку они обычно требуют использования примитивов, атрибутов или настроек синтеза, специфичных для платформы/технологии. Чтобы обеспечить реальную независимую от цели архитектуру, которую можно синтезировать для любой целевой технологии, применяется специальный метод: за каждым инвертором внутри RO следует защелка , обеспечивающая глобальный сброс, а также индивидуальная защелка, разрешающая переключение. защелка в прозрачный режим.
Отдельные разрешения защелки управляются длинным сдвиговым регистром, который имеет отдельный FF для каждой отдельной защелки в цепочке RO. Когда TRNG включен, этот сдвиговый регистр начинает заполняться единицами. Таким образом, защелки активируются индивидуально одна за другой, что делает невозможным для инструмента синтеза обрезку какой-либо логики/элементов из цепочки RO, поскольку начальные состояния каждой защелки могут (теоретически) контролироваться внешней логикой. Разрешающий сдвиговый регистр всех энтропийных ячеек подключается последовательно, чтобы продолжить процедуру запуска по всему энтропийному массиву.
На следующем изображении показана упрощенная схема самой первой энтропийной ячейки, состоящей из 5 элементов инвертора-защелки для кольцевого генератора, 5 триггеров для регистра сдвига включения и еще 2 триггеров для синхронизатора.
Изображение, показывающее результат сопоставления FPGA (сгенерированный Intel Quartus Prime) самой первой энтропийной ячейки, можно увидеть здесь. Это показывает, что все элементы защелки + инвертора цепи кольцевого генератора были успешно сопоставлены с отдельными LUT4.
Как только последний бит регистра сдвига включения энтропийной ячейки установлен, запускается блок устранения смещения. В этом устройстве реализован простой «экстрактор случайности Джона фон Неймана» для устранения смещения полученного потока случайных данных. Экстрактор реализует 2-битный сдвиговый регистр, который производит выборку случайного бита с функцией XOR из массива энтропийных ячеек. В каждом втором цикле экстрактор оценивает два выбранных бита, чтобы проверить непересекающуюся пару бит на наличие границ .
Всякий раз, когда обнаруживается фронт, «действительный» сигнал отправляется на следующий блок выборки. Нарастающий фронт ( 01
) выдает 1
бит данных, а спадающий фронт ( 10
) выдает 0
бит данных. Следовательно, блоку устранения смещения требуется как минимум два тактовых цикла для генерации одного случайного бита. Если фронт не обнаружен ( 00
или 11
), действительный сигнал остается низким, и блок выборки останавливается.
Блок выборки реализует 8-битный сдвиговый регистр для преобразования последовательного несмещенного потока битов в случайные числа шириной в байт. Кроме того, блок выборки обеспечивает простую постобработку для улучшения спектрального распределения полученных случайных выборок.
Чтобы сгенерировать один байт случайных данных, блок выборки сбрасывает свой внутренний сдвиговый регистр на нуль и начинает потреблять 64 бита несмещенного случайного потока. Регистр сдвига реализован как регистр сдвига с линейной обратной связью (LFSR), который выполняет операцию XOR входного потока с последним битом регистра для дальнейшего скремблирования и смешивания случайного потока битов.
NeoTRNG оценивается как часть процессора NEORV32, где neoTRNG доступен в качестве стандартного модуля SoC. Процессор был синтезирован для FPGA Intel Cyclone IV EP4CE22F17C6N
, работающей на частоте 100 МГц. Для оценки использовалась очень маленькая конфигурация по умолчанию : реализованы три энтропийные ячейки, где первая реализует 5 инверторов, вторая реализует 9 инверторов и третья реализует 11 инверторов. Более сложные конфигурации с большим количеством ячеек энтропии могут обеспечить «лучшее» случайное качество.
NUM_CELLS = 3
NUM_INV_START = 5
SIM_MODE = false
Примечание
Для оценок было получено в общей сложности 4 МБ случайных данных. Этот набор данных доступен в виде двоичного файла entropy.bin
в ресурсах выпуска.
Для простого анализа гистограммы из neoTRNG было выбрано 4 МБ случайных байтов. Полученные байты накапливались в соответствии с их появлением и сортировались по контейнерам, где каждый контейнер представляет один определенный шаблон байтов (1 байт = 8 бит = 256 различных шаблонов). Полученный результат затем был проанализирован с точки зрения его статистических свойств:
[NOTE] integer numbers only
Number of samples: 4194304
Arithmetic mean: 127 (optimum would be 127)
Histogram occurrence
Average: 16384 (optimum would be 4194304/256 = 16384)
Min: 16051 = average - 333 (deviation) at bin 183 (optimum deviation would be 0)
Max: 16706 = average + 322 (deviation) at bin 144 (optimum deviation would be 0)
Average dev.: +/- 96 (optimum would be 0)
$ ent entropy.bin
Entropy = 7.994306 bits per byte.
Optimum compression would reduce the size
of this 4194304 byte file by 0 percent.
Chi square distribution for 4194304 samples is 16726.32, and randomly
would exceed this value less than 0.01 percent of the times.
Arithmetic mean value of data bytes is 127.9417 (127.5 = random).
Monte Carlo value for Pi is 3.132416851 (error 0.29 percent).
Serial correlation coefficient is 0.000496 (totally uncorrelated = 0.0).
$ rngtest < entropy.bin
rngtest 5
Copyright (c) 2004 by Henrique de Moraes Holschuh
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
rngtest: starting FIPS tests...
rngtest: entropy source drained
rngtest: bits received from input: 33554432
rngtest: FIPS 140-2 successes: 1676
rngtest: FIPS 140-2 failures: 1
rngtest: FIPS 140-2(2001-10-10) Monobit: 0
rngtest: FIPS 140-2(2001-10-10) Poker: 0
rngtest: FIPS 140-2(2001-10-10) Runs: 1
rngtest: FIPS 140-2(2001-10-10) Long run: 0
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=138.214; avg=1557.190; max=2119.276)Mibits/s
rngtest: FIPS tests speed: (min=32.660; avg=106.337; max=111.541)Mibits/s
rngtest: Program run time: 330110 microseconds
Набор тестов для случайных чисел «Dieharder» (Википедия, домашняя страница) Роберта Г. Брауна — отличный набор инструментов для стресс-тестирования и характеристики генераторов случайных чисел.
Важный
? работа в процессе?
dieharder нужен большой набор случайных выборок (около 4 ГБ). В противном случае случайные данные перематываются, что, очевидно, снижает общую энтропию. Сейчас я использую простое соединение UART для передачи данных с FPGA на ПК. Но даже при более высокой скорости передачи данных для отправки набора данных объемом 4 ГБ потребуется много времени . Пока у меня не будет лучшего канала передачи (или просто не появится много времени), эта оценка находится в стадии разработки .
Результаты сопоставления для neoTRNG, реализованного в процессоре NEORV32 RISC-V с использованием конфигурации по умолчанию. Результаты получены для FPGA Intel Cyclone EP4CE22F17C6N
, работающей на частоте 100 МГц, с использованием Intel Quartus Prime.
Module Hierarchy Logic Cells Logic Registers
------------------------------------------------------------------------------------
neoTRNG:neoTRNG_inst 56 (27) 46 (19)
neoTRNG_cell:entropy_source:0:neoTRNG_cell_inst 8 (8) 7 (7)
neoTRNG_cell:entropy_source:1:neoTRNG_cell_inst 10 (10) 9 (9)
neoTRNG_cell:entropy_source:2:neoTRNG_cell_inst 14 (14) 11 (11)
Примечание
Инструменты синтеза могут выдать предупреждение об обнаружении защелок и комбинаторных циклов. Однако это не недостаток дизайна, поскольку это именно то, что мы хотим.
Максимальная скорость генерации neoTRNG определяется двумя факторами:
Следовательно, neoTRNG требует как минимум A * B = 2 * 64 = 128
тактов для выдачи одного случайного байта. Оценка FPGA показала, что фактическое время выборки составляет около 300 тактов. Таким образом, реализация, работающая на частоте 100 МГц, может генерировать примерно 330 КБ случайных данных в секунду. Более высокая скорость генерации может быть достигнута путем параллельного запуска нескольких экземпляров neoTRNG.
Поскольку асинхронные кольцевые генераторы не могут быть смоделированы в режиме rtl (из-за комбинаторных циклов), neoTRNG предоставляет специальный режим моделирования, который включается общим параметром SIM_MODE
. Если этот параметр включен, к инверторам кольцевого генератора добавляется «задержка распространения», реализованная как простой триггер.
Важный
Режим моделирования предназначен только для моделирования/отладки! Проекты с включенным SIM_MODE
можно синтезировать, но они вообще не дадут никаких истинных/физических случайных чисел!
Папка sim
предоставляет простой тестовый стенд для neoTRNG с использованием конфигурации по умолчанию. Тестовый стенд выведет полученные случайные байты данных в виде десятичных значений на консоль симулятора. Тестовый стенд можно смоделировать с помощью GHDL, используя предоставленный скрипт:
neoTRNG/sim$ sh ghdl.sh
../rtl/neoTRNG.vhd:105:3:@0ms:(assertion note): [neoTRNG] The neoTRNG (v3.2) - A Tiny and Platform-Independent True Random Number Generator, https://github.com/stnolting/neoTRNG
../rtl/neoTRNG.vhd:112:3:@0ms:(assertion warning): [neoTRNG] Simulation-mode enabled (NO TRUE/PHYSICAL RANDOM)!
18
210
147
5
79
94
70
100
185
246
203
220
ghdl:info: simulation stopped by --stop-time @100us
Данные о форме сигнала GHDL сохраняются в файле sim/neoTRNG_tb.ghw
и их можно просмотреть с помощью gtkwave
:
neoTRNG/sim$ gtkwave neoTRNG_tb.ghw
Простой запуск моделирования выполняется с помощью рабочего процесса проекта neoTRNG-sim
GitHub.