检查了这两个的cpython源代码。秘密 和 uuid4. 两者似乎都在使用os.urandom。
#uuid.py
def uuid4():
"""Generate a random UUID."""
return UUID(bytes=os.urandom(16), version=4)
#secrets.py
def token_bytes(nbytes=None):
"""Return a random byte string containing *nbytes* bytes.
If *nbytes* is ``None`` or not supplied, a reasonable
default is used.
>>> token_bytes(16) #doctest:+SKIP
b'\\xebr\\x17D*t\\xae\\xd4\\xe3S\\xb6\\xe2\\xebP1\\x8b'
"""
if nbytes is None:
nbytes = DEFAULT_ENTROPY
return _sysrand.randbytes(nbytes)
# This is code for randbytes in SystemRandom in random
def randbytes(self, n):
"""Generate n random bytes."""
# os.urandom(n) fails with ValueError for n < 0
# and returns an empty bytes string for n == 0.
return _urandom(n)
IETF 警告不要使用 uuid 的安全功能。参考第6节 UUID. 它说
安全考虑因素
不要以为UUID是很难猜到的;例如,不应该把UUID作为安全能力(仅仅拥有就可以访问的标识符)。 一个可预测的随机数源会加剧这种情况。
如果secret真的和uuid4一样使用urandom,我们能不能用uuid4代替secret。使用secret token_bytes而不是uuid4本身的目的是什么?按照IETF的标准,api keystokens的secret模块真的不安全吗?
你可能会惊讶地发现,随机UUID并不是完全随机的。准确地说,有6个位设置为特定的值(以 表明 它是一个随机的UID)。) 它们被创建为 独一无二 (具有很高的确定性)。UUID有特定的用途,所以你会发现在它们上面定义了各种各样的方法。
此外,顾名思义,它们不是 意思 秘密。这也可能意味着没有采取适用于秘密的可能保护措施。例如,字符串通常很容易在内存中找到,而UUID通常是以文本表示的方式进行交流。
令牌则不同。它通常是加密和保密的。因此,它有不同的用途。当然,UUID和令牌都可以由随机位和字节组成。然而,这更多的是关于使用正确的工具来完成工作。
如果你要创建一个秘钥而不是令牌或UUID,我更倾向于使用API特定的方法来生成密钥。否则的话,使用以下方法可能是个好主意 SystemRandom
直接,因为密钥既不是UUID,也不是Token。