如何从 /dev/urandom 获取随机种子?

How to get a random seed from /dev/urandom?

提问人:betacrash 提问时间:7/11/2023 最后编辑:betacrash 更新时间:7/11/2023 访问量:181

问:

在 python 3.11 和 ubuntu 22.04 中,我试图获取一个随机种子(而不是来自种子系统的随机数)。我有一个系统正在运行一个循环的进程。在循环的不同点,我将所有 python 和系统 RNG 设置设置为特定的种子以提高可重复性。在某个特定点上,我需要一个随机种子,与用于系统的特定种子分开。

我需要的随机种子是一个上限为 (2^32 -1) 的整数。是的,有一个函数,但它从种子系统返回一个值。

我在 USB 端口中有一个硬件 RNG,可以与 rng5-tools 包一起使用,但我无法直接访问它。我假设它用于填充熵池,并且 os.urandom() 从该池中提取位。

我尝试使用 os.urandom() 生成一个整数,然后取该整数的最后一个字符。10 个字符(0 到 9)的分布是均匀的。我已经运行了 10^3 到 10^7 的样本来验证这一点。

我这样做了 10 次,每次将单个字符添加到字符串中,然后将字符串转换为整数。每次我向字符串添加整数时,我都会用零填充它并测试它是否< 4294967296 (2^32 -1)。如果失败,则丢弃该角色,并获取并测试一个新角色,直到它通过测试。如果成功,我会将其保留在字符串中,并对新字符重复该过程,直到总共获得十个字符。然后,我将字符串转换为整数。

但是,生成的整数的分布是偏态的,如图所示。谁能解释一下为什么?代码为:

def gen_seed(digits = 10): 

  ssc = ""
  for i in range(digits):
    found_digit = False
    while found_digit == False:
    
      rand=f"{int.from_bytes(os.urandom(1), sys.byteorder)}"
      digit = f"{rand[-1]}"

      ssc_test = int(f"{ssc}{digit}".ljust(10,"0"))

      if ssc_test < 4294967296:
        found_digit = True
        ssc = f"{ssc}{digit}"
  ss = int(ssc)
  return(ss)

Resulting ten-digit integer frequency

python-3.x linux 随机 种子

评论

2赞 Scott Hunter 7/11/2023
一种常见的方法是获取当前时间的低阶部分。
0赞 Codist 7/11/2023
@ScottHunter 连续两次调用 time.time() 可能会返回相同的值
0赞 Sam Mason 7/11/2023
这种偏见是因为你保留了“找到的数字”,而不是每次都从头开始。在第一轮中选择A的概率是1/4,但应该是其中的三分之一。因此,直方图跳过41e9 / (2**32 % 1e9)
0赞 betacrash 7/12/2023
嗨,山姆,在第一轮选 4 实际上是 1/5 的机会 (0 - 4)。我不明白为什么第一个字符上有 10 个不同数字的统一分布,其中一半被丢弃,应该倾向于特定的数字 4?
0赞 Scott Hunter 7/12/2023
@DarkKnight:这与单变化最快的部分有什么关系?

答:

3赞 Barmar 7/11/2023 #1

从中获取所需的字节数,然后将其转换为整数。os.urandom()

def gen_seed(num_bytes = 4):
    b = os.urandom(num_bytes)
    return int.from_bytes(b)

评论

0赞 betacrash 7/12/2023
嗨,Barmar,这似乎在 2^32 -1 范围内产生了一个统一的差异。我想知道你或任何人是否可以告诉我有关os.urandom(bytes)的信息。它是否在不替换的情况下从熵池中提取 8 x 字节数的位数?还是只使用池中 8 x 字节熵位的一小部分?
1赞 Barmar 7/12/2023
文档对此进行了解释。它基本上可以执行系统调用或执行的任何操作。getrandom()/dev/urandom
0赞 Sam Mason 7/12/2023
@betacrash提到 Linux,它可能值得一读:zx2c4.com/projects/linux-rng-5.17-5.18 它描述了代码的最新重构,并包括一些历史和动机
0赞 betacrash 7/12/2023
@Barmar:你回答了如何获得统一号码。我们可以用这个来结束这个问题。但这引出了另一个问题,我将为此发表另一篇文章。
0赞 betacrash 7/12/2023
@Sam:谢谢你的参考。这增加了我将在另一篇文章中提出的下一个问题。