问题描述
我正在尝试从使用 cryptographically secure DRBG 而不是 Python 中默认使用的“不安全”梅森扭曲器的总体中生成随机样本。
This library 提供了 DRBG,我重新利用了 Python 源代码中的 random.sample
生成算法作为我的采样算法的基础。
代码有效,但仅适用于远小于总体的样本,而内置的 Mersenne Twister 即使样本和总体大小相等也不会失败。
程序将随机选择数组中的位置,让字符驻留在其中。不允许覆盖,因为在将字符串放入数组后必须从数组中重建字符串(这部分代码未显示,但会进行解释以帮助解释问题)。
代码:
import string
import secrets as secret
import random as rd
import numpy as np
from math import ceil,log
from aes_drbg import AES_DRBG
import timeit
# Initialize the AES DRBG
key = 1
aes_drbg = AES_DRBG(256)
aes_drbg.instantiate(bytes(key))
def random_number(limit):
"""Generate a random number within the limit using the AES DRBG."""
sequence_length = 1
if limit >= 4_294_967_296:
sequence_length = 8
elif limit >= 65_536:
sequence_length = 4
elif limit >= 256:
sequence_length = 2
random_number_bytes = aes_drbg.generate(sequence_length)
random_number = int.from_bytes(random_number_bytes,byteorder="big")
return random_number % limit
def sample(population,k):
"""Generate a random sample of size k from the given population"""
randbelow = random_number
n = len(population)
if not 0 <= k <= n:
raise ValueError("Sample larger than population or is negative")
result = [None] * k
setsize = 21 # size of a small set minus size of an empty list
if k > 5:
setsize += 4 ** ceil(log(k * 3,4)) # table size for big sets
if n <= setsize:
# An n-length list is smaller than a k-length set
pool = list(population)
for i in range(k): # invariant: non-selected at [0,n-i)
j = randbelow(n - i)
result[i] = pool[j]
pool[j] = pool[n - i - 1] # move non-selected item into vacancy
else:
selected = set()
selected_add = selected.add
for i in range(k):
j = randbelow(n)
while j in selected:
j = randbelow(n)
selected_add(j)
result[i] = population[j]
return result
def string_generator(size):
"""Generate a random string of a given size."""
chars = string.ascii_uppercase + string.ascii_lowercase
return ''.join(secret.choice(chars) for _ in range(size))
def main():
test = string_generator(50_000_000) # Generate random string as test data.
array = np.zeros([100_000_000]) # Initialize empty array.
rd.seed(1)
start_time = timeit.default_timer()
rand_sample = sample(range(len(array)),len(test)) # use `sample` for AES DRBG; `rd.sample` for the Mersenne Twister
end_time = timeit.default_timer()
print(rand_sample)
print(f"Execution time: {end_time - start_time}")
if __name__ == "__main__":
main()
随着 len(test)
的值接近 len(array)
的值,DRBG 停止输出并无限期运行。我不确定我哪里出错了,但我无法诊断错误。
MWE 是对我的实际代码的简化,但就我所能收集到的而言,它充分说明了问题。 test
和 array
的数量在生产中要大得多(十亿),所以我愿意接受任何其他更有效的算法或其他加密安全的 DRBG,例如 XCHACHA20 甚至其他具有安全 DRBG 可用的库这样可以完全控制种子,从而可以重复结果。非常感谢任何指导。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)