作为预订过程的一部分,我正在使用以下方法为用户创建随机代码:
User.objects.make_random_password()
当用户出现在会场时,他们将出示密码。
假设两个人最终不会使用相同的代码是否安全?
谢谢
不,假设两个人不能拥有相同的代码是不安全的。随机并不意味着唯一。这可能不太可能而且很少见,具体取决于您指定的长度和您正在处理的用户数量。但是你不能依赖它的独特性。
这取决于您现在拥有的用户数量,以及您选择的密码长度,以及您如何使用User.objects.make_random_password()
默认情况下,机会基本上为零,IMO;
此方法是使用get_random_string()
. 来自 django github 仓库:
def get_random_string(length=12,
allowed_chars='abcdefghijklmnopqrstuvwxyz'
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
"""
Returns a securely generated random string.
The default length of 12 with the a-z, A-Z, 0-9 character set returns
a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
"""
if not using_sysrandom:
# This is ugly, and a hack, but it makes things better than
# the alternative of predictability. This re-seeds the PRNG
# using a value that is hard for an attacker to predict, every
# time a random string is required. This may change the
# properties of the chosen random sequence slightly, but this
# is better than absolute predictability.
random.seed(
hashlib.sha256(
"%s%s%s" % (
random.getstate(),
time.time(),
settings.SECRET_KEY)
).digest())
return ''.join([random.choice(allowed_chars) for i in range(length)])
根据 github,当前代码默认使用 62 个字符(大小写字母和数字)的字符串中的 12 个字符的密码。这使得 62**12 或 3226266762397899821056 (3.22e21) 可能有不同的密码。这比目前的世界人口(大约 7e9)要大得多。
该random.choice()
函数从这个字符列表中挑选字母。random.choice()
现在的问题变成了重复调用两次返回相同序列的可能性有多大?
从 的实现中可以看出get_random_string()
,代码努力避免可预测性。当不使用操作系统的伪随机值生成器(在 Linux 和 *BSD 上从以太网数据包或按键到达的时间收集真正的随机性)时,它会在每次调用时重新播种random
模块的Mersenne Twister可预测 PRNG,并结合当前随机状态、当前时间和(可能是常数)密钥。
因此,要生成两个相同的密码,随机生成器的状态(在 python 中约为 8 kiB)和生成它们的时间(根据 epoch 以秒为单位测量time.time()
)必须相同。如果系统的时间维护得很好,并且您正在运行密码生成程序的一个实例,那么发生这种情况的机会基本上为零。如果您在完全相同的时间使用完全相同的 PRNG 种子启动此密码生成程序的两个或多个实例,并结合它们的输出,人们会期望某些密码会出现不止一次。