从预填充的随机缓冲区中提取基数为K的随机“位”

时间:2019-03-10 07:08:36

标签: c algorithm performance random cryptography

说我需要在[0,K)范围内的N个密码安全的伪随机整数。实现此目的最明显的方法是对arc4random_uniform(3)进行N次调用,而这正是我正在做的事情。

但是,探查器告诉我,对arc4random_uniform(3)的多次调用占用了整个执行时间的2/3,我确实需要使我的代码更快。这就是为什么我计划预先生成一些随机字节(可能使用arc4random_buf(3)),然后一点一点地从中提取。

对于K = 2,我可以简单地屏蔽掉所需的位,但是当K不是2的幂时,事情就会变得多毛。当然,我可以使用一堆%=/=,但是那样我会产生模偏差。另一个问题是,当N太大时,我将无法再将整个缓冲区解释为整数并对其执行算术运算。

在有意义的情况下,K会小于20,而N可能会非常大,例如数百万。

1 个答案:

答案 0 :(得分:3)

您可以使用模运算符和除法,只需要做一些额外的预处理即可。正常生成值数组。将P设为K的最大乘方,小于或等于2^32(其中^表示幂),并遍历数组以确保所有随机值严格少于P。如果不是,则替换为小于P的新随机数。这样可以消除偏差。

现在要处理大型N,您将需要两个循环。第一个循环遍历数组中的元素,第二个循环从每个元素中提取多个随机数。如果为P = k ^ e,则可以从数组中每个元素的e中提取[0, k)个随机数。每次从元素提取随机数时,请对该元素进行k的底数除法。

当然,这不一定是实际的循环。您可以存储两个变量(数组索引,子元素索引),并在调用函数时从array_index元素中提取。如果为sub_element_index == e,则将其重置为零并增加array_index。从该数组元素中提取一个随机数,然后返回它。