随机数发生器(True Random Number Generator,TRNG)是一种用于生成随机数的设备,其输出的随机数是基于物理随机现象或过程产生的,这些现象或过程具有固有的随机性
正如我们在[沿着低成本MCU路漫步]中所谈到的,我们开始尝试用相当低成本的应广(Padauk0 – PFS154制造随机数生成器。
我们如何创造“真正的”随机性?
在我们深入研究实现之前,我们可以更多地研究如何实现真正的随机性。
如前所述,我们希望:
通过串行通信链路吐出真随机数的设备
我们如何实现这一目标是最棘手的部分。正如我们在[随机性:它是什么?我们为什么需要它?我们如何创建它?],伪随机性很容易创建,但真正的随机性需要更多。这里的关键是从物理事物中获取熵。
有几种方法(和地点)可以获取此熵。
也许最常用的是制造一个从硬件中获取噪声的系统,例如齐纳二极管击穿、ADC、人体键盘时序、鼠标移动、空气湍流等。
但是我们希望在尽可能少(希望没有)外部要求的情况下做到这一点,而PFS154没有ADC模块,因此不可能从ADC或通过ADC实现随机性。
有几个人已经实现了随机数生成器,它使用2个以不同速度运行的系统时钟,当其中最慢的时钟滴答作响时,数据从连接到另一个时钟的计数器中取出。
通过这样做,我们可以捕获时钟噪声和抖动(可能接近100%随机)。
PFS154有两个时钟系统,我们认为它们彼此完全独立。即IHRC和ILRC,其中IHRC是“快速的”,通常运行在16 MHz,而“慢速”/ ILRC运行在~54 kHz。
我们可以将两个不同的时钟通过管道传输到单独的计时器中,并在每次触发“慢速中断”时从快速计数器中取出一些位。
实施和一些数据
T16中断只发生在~1.6 Hz,以使两个时钟有时间表现不同(IHRC 8位计数器为每个T16中断封装约39,000次)。
但这意味着我们每5秒只能获得一个完整字节的数据!导致一个不那么快的数字生成器…
首先,我们尝试在每次中断时取出2位,从而得到惊人的1.25 bps,但结果数据显然不是随机的(参见下面的“第1轮”结果)。因此,我们通过每次中断仅从计数器获取1位数据来降低速度(来自此的数据称为“第2轮”)。
这个系统在这两轮中产生的所有数据都可以在这里和这里下载。
if ( INTRQ & INTRQ_T16 )
{
if ( random_number_index == 0 )
{
random_number = 0;
}
// take out one bit each time
random_number |= ( ( (TM3CT & 0b00000010) >> 1) << random_number_index );
if ( random_number_index >= 7 )
{
random_number_index = 0;
new_number = 1;
}
else
{
random_number_index++;
}
// mark T16 interrupt request processed
INTRQ &= ~INTRQ_T16;
}
_number_index == 0 )
{
random_number = 0;
}
// take out one bit each time
random_number |= ( ( (TM3CT & 0b00000010) >> 1) << random_number_index );
if ( random_number_index >= 7 )
{
random_number_index = 0;
new_number = 1;
}
else
{
random_number_index++;
}
// mark T16 interrupt request processed
INTRQ &= ~INTRQ_T16;
}
为了方便使用,easypdk被修改为将传入的数据转储到二进制文件:
// Changes added to easypdkprog.c line 714+:
FILE *fptr;
if ( dbgd>0 && !first_byte )
{
dbgmsg[dbgd]=0;
printf("%s", dbgmsg);
fptr = fopen("serialdump.bin","ab");
fwrite(&dbgmsg[0], 1, 1, fptr);
fclose(fptr);
}
if ( first_byte )
{
first_byte = false;
}
是随机的吗?不。
如果我们从两轮的分布开始看
你很快就会发现这不是均匀分布的。如果我们观察这个分布的发展,我们也会发现它缺少几层“随机性”:
所以只要快速看一下这些数字我们就知道这不是随机的。
是的,数据集相当小(第2轮只包含9 189 912位),但我们仍然可以看到这不是“正确”的方式���
为了好玩,我们在《dieharder》中对这个数据集进行了几次统计测试。结果并不令人惊讶:
$ dieharder -g 201 -f serialdump_round2.bin -a
#=============================================================================#
# dieharder version 3.31.1 Copyright 2003 Robert G. Brown #
#=============================================================================#
rng_name | filename |rands/second|
file_input_raw| serialdump_round2.bin| 4.98e+06 |
#=============================================================================#
test_name |ntup| tsamples |psamples| p-value |Assessment
#=============================================================================#
# The file file_input_raw was rewound 48 times
diehard_birthdays| 0| 100| 100|0.00000000| FAILED
# The file file_input_raw was rewound 396 times
diehard_operm5| 0| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 842 times
diehard_rank_32x32| 0| 40000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 1051 times
diehard_rank_6x8| 0| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 1142 times
diehard_bitstream| 0| 2097152| 100|0.00000000| FAILED
# The file file_input_raw was rewound 1872 times
diehard_opso| 0| 2097152| 100|0.00000000| FAILED
# The file file_input_raw was rewound 2359 times
diehard_oqso| 0| 2097152| 100|0.00000000| FAILED
# The file file_input_raw was rewound 2587 times
diehard_dna| 0| 2097152| 100|0.00000000| FAILED
# The file file_input_raw was rewound 2609 times
diehard_count_1s_str| 0| 256000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 3055 times
diehard_count_1s_byt| 0| 256000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 3063 times
diehard_parking_lot| 0| 12000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 3069 times
diehard_2dsphere| 2| 8000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 3073 times
diehard_3dsphere| 3| 4000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 4199 times
diehard_squeeze| 0| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 4199 times
diehard_sums| 0| 100| 100|0.00000000| FAILED
# The file file_input_raw was rewound 4234 times
diehard_runs| 0| 100000| 100|0.83092807| PASSED
diehard_runs| 0| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 4712 times
diehard_craps| 0| 200000| 100|0.00000000| FAILED
diehard_craps| 0| 200000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 11677 times
marsaglia_tsang_gcd| 0| 10000000| 100|0.00000000| FAILED
marsaglia_tsang_gcd| 0| 10000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 11711 times
sts_monobit| 1| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 11746 times
sts_runs| 2| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 11781 times
sts_serial| 1| 100000| 100|0.00000000| FAILED
sts_serial| 2| 100000| 100|0.00000000| FAILED
sts_serial| 3| 100000| 100|0.00000000| FAILED
sts_serial| 3| 100000| 100|0.00000000| FAILED
sts_serial| 4| 100000| 100|0.00000000| FAILED
sts_serial| 4| 100000| 100|0.00000000| FAILED
sts_serial| 5| 100000| 100|0.00000000| FAILED
sts_serial| 5| 100000| 100|0.00000000| FAILED
sts_serial| 6| 100000| 100|0.00000000| FAILED
sts_serial| 6| 100000| 100|0.00000000| FAILED
sts_serial| 7| 100000| 100|0.00000000| FAILED
sts_serial| 7| 100000| 100|0.00000000| FAILED
sts_serial| 8| 100000| 100|0.00000000| FAILED
sts_serial| 8| 100000| 100|0.00000000| FAILED
sts_serial| 9| 100000| 100|0.00000000| FAILED
sts_serial| 9| 100000| 100|0.00000000| FAILED
sts_serial| 10| 100000| 100|0.00000000| FAILED
sts_serial| 10| 100000| 100|0.00000000| FAILED
sts_serial| 11| 100000| 100|0.00000000| FAILED
sts_serial| 11| 100000| 100|0.00000000| FAILED
sts_serial| 12| 100000| 100|0.00000000| FAILED
sts_serial| 12| 100000| 100|0.00000000| FAILED
sts_serial| 13| 100000| 100|0.00000000| FAILED
sts_serial| 13| 100000| 100|0.00000000| FAILED
sts_serial| 14| 100000| 100|0.00000000| FAILED
sts_serial| 14| 100000| 100|0.00000000| FAILED
sts_serial| 15| 100000| 100|0.00000000| FAILED
sts_serial| 15| 100000| 100|0.00000000| FAILED
sts_serial| 16| 100000| 100|0.00000000| FAILED
sts_serial| 16| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 11851 times
rgb_bitdist| 1| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 11990 times
rgb_bitdist| 2| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 12199 times
rgb_bitdist| 3| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 12478 times
rgb_bitdist| 4| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 12826 times
rgb_bitdist| 5| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 13244 times
rgb_bitdist| 6| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 13731 times
rgb_bitdist| 7| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 14288 times
rgb_bitdist| 8| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 14915 times
rgb_bitdist| 9| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 15611 times
rgb_bitdist| 10| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 16377 times
rgb_bitdist| 11| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 17213 times
rgb_bitdist| 12| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 17283 times
rgb_minimum_distance| 2| 10000| 1000|0.00000000| FAILED
# The file file_input_raw was rewound 17387 times
rgb_minimum_distance| 3| 10000| 1000|0.00000000| FAILED
# The file file_input_raw was rewound 17527 times
rgb_minimum_distance| 4| 10000| 1000|0.00000000| FAILED
# The file file_input_raw was rewound 17701 times
rgb_minimum_distance| 5| 10000| 1000|0.00000000| FAILED
# The file file_input_raw was rewound 17770 times
rgb_permutations| 2| 100000| 100|0.00008615| WEAK
# The file file_input_raw was rewound 17875 times
rgb_permutations| 3| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 18014 times
rgb_permutations| 4| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 18188 times
rgb_permutations| 5| 100000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 18536 times
rgb_lagged_sum| 0| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 19233 times
rgb_lagged_sum| 1| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 20277 times
rgb_lagged_sum| 2| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 21670 times
rgb_lagged_sum| 3| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 23411 times
rgb_lagged_sum| 4| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 25501 times
rgb_lagged_sum| 5| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 27938 times
rgb_lagged_sum| 6| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 30724 times
rgb_lagged_sum| 7| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 33858 times
rgb_lagged_sum| 8| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 37340 times
rgb_lagged_sum| 9| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 41170 times
rgb_lagged_sum| 10| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 45348 times
rgb_lagged_sum| 11| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 49875 times
rgb_lagged_sum| 12| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 54750 times
rgb_lagged_sum| 13| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 59973 times
rgb_lagged_sum| 14| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 65545 times
rgb_lagged_sum| 15| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 71464 times
rgb_lagged_sum| 16| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 77732 times
rgb_lagged_sum| 17| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 84348 times
rgb_lagged_sum| 18| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 91312 times
rgb_lagged_sum| 19| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 98624 times
rgb_lagged_sum| 20| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 106285 times
rgb_lagged_sum| 21| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 114294 times
rgb_lagged_sum| 22| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 122651 times
rgb_lagged_sum| 23| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 131356 times
rgb_lagged_sum| 24| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 140409 times
rgb_lagged_sum| 25| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 149811 times
rgb_lagged_sum| 26| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 159561 times
rgb_lagged_sum| 27| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 169659 times
rgb_lagged_sum| 28| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 180105 times
rgb_lagged_sum| 29| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 190900 times
rgb_lagged_sum| 30| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 202042 times
rgb_lagged_sum| 31| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 213533 times
rgb_lagged_sum| 32| 1000000| 100|0.00000000| FAILED
# The file file_input_raw was rewound 213568 times
rgb_kstest_test| 0| 10000| 1000|0.00000000| FAILED
# The file file_input_raw was rewound 214103 times
dab_bytedistrib| 0| 51200000| 1|0.00000000| FAILED
# The file file_input_raw was rewound 214148 times
dab_dct| 256| 50000| 1|0.00000000| FAILED
Preparing to run test 207. ntuple = 0
# The file file_input_raw was rewound 214541 times
dab_filltree| 32| 15000000| 1|0.00000000| FAILED
dab_filltree| 32| 15000000| 1|0.00000000| FAILED
Preparing to run test 208. ntuple = 0
# The file file_input_raw was rewound 214626 times
由于必须重绕输入数据文件的次数,diehard -test可能会报告几个假阴性结果。因此,如果您实际要使用统计测试电池,如硬测试,则需要许多GB的原始数据(与这里的~1 MB相比!)
为什么这不是随机的?
我们可以清楚地看到,这个数据不是“随机的”。
但两个独立的硬件时钟应该包含足够的随机性和抖动,我们可以提取!
也许他们不像我们想象的那么独立?
因为当我们校准其中一个时钟时,另一个时钟开始表现不同,这意味着某种相互作用发生了。也许Padauk偶尔会用IHRC校准ILRC ?
这不是一件坏事,但请注意,数据表中没有记录这种行为,因此很难在PFS154上以这种方式制作TRNG。