如何实现 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 模块实现这个,所以我不能使用 os
或 secrets
包。
来自 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)
我正在实现一个函数来替换 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 模块实现这个,所以我不能使用 os
或 secrets
包。
来自 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)