如何实现 os.urandom 功能 - Python2

How to implement a os.urandom function - Python2

我正在实现一个函数来替换 os.urandom(n)。下面的代码是我目前所拥有的:

def random_entropy(n):
    """
    Returns a random entropy, which is a sequence of numbers between 0, 255

    :n: a integer number
    """
    if n <= 0:
        return ""
    buffer = []
    for i in range(0, n):
        number = random.randint(0, 255)
        buffer.append(hex(number))
    
    return ''.join(buffer)

如果我去终端,我得到以下输出:

>>> import os
>>> os.urandom(10)
'm\xd4\x94\x00x7\xbe\x04\xa2R'
>>> type(os.urandom(10))
<type 'str'>
>>> map(ord, os.urandom(10))
[65, 120, 218, 135, 66, 134, 141, 140, 178, 25]

最后,我希望我的函数 return 与 os.urandom 类似的输出:'m\xd4\x94\x00x7\xbe\x04\xa2R'(我的意思是二进制输出)。我怎样才能做到这一点?我正在为 SGX 的 ecdsa 模块实现这个,所以我不能使用 ossecrets 包。

来自 Python 文档:

Return a string of size random bytes suitable for cryptographic use.

首先,在开始之前,您应该知道 random 在许多应用程序中不足以替代 urandom。阅读问题评论中给出的链接。您在函数名称中滥用了“熵”一词。

通过在每个数字上使用 hex,您可以将其转换为可读的多字符字符串表示形式。你不想要那个,你想要 chr 相反。

这是 Python 2 的代码的快速修复:

def random_entropy(n):
    """
    Returns a random entropy, which is a sequence of numbers between 0, 255

    :n: a integer number
    """
    if n <= 0:
        return ""
    buffer = []
    for i in range(0, n):
        number = random.randint(0, 255)
        buffer.append(chr(number))
    
    return ''.join(buffer)

无需先生成列表,直接在join中循环即可,大大简化了事情:

def random_entropy(n):
    """
    Returns a random entropy, which is a sequence of numbers between 0, 255

    :n: a integer number
    """
    return ''.join(chr(random.randint(0, 255)) for _ in range(n))

Python 3 做事有点不同。这是等效的:

def random_entropy(n):
    """
    Returns a random entropy, which is a sequence of numbers between 0, 255

    :n: a integer number
    """
    return b''.join(random.randint(0, 255).to_bytes(1, 'little') for _ in range(n))

编辑:最后在 Python 3.9 中,random 中有一个函数可以完全满足您的要求:random.randbytes。注意那里给出的警告:

This method should not be used for generating security tokens. Use secrets.token_bytes() instead.

def random_bytes(n):
    """
    Returns a random byte string, which is a sequence of numbers between 0, 255.
    This should not be used in any application requiring cryptographic security.

    :n: a integer number for the number of bytes requested.
    """
    return random.randbytes(n)