使用Python创建盐值

37

我该如何在Python中创建一个由16个随机字符组成的、基于62进制的盐?我需要它来实现某个协议,但不确定从哪里开始。谢谢。

8个回答

35
>>> import random
>>> ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
>>> chars=[]
>>> for i in range(16):
    chars.append(random.choice(ALPHABET))

>>> "".join(chars)
'wE9mg9pu2KSmp5lh'

这应该可以正常工作。


21
好的回答,但是最后的四行可以更加习惯性地使用只有''.join(random.choice(ALPHABET) for i in range(16)) - Scott Griffiths
1
@ScottGriffiths 我不会说这更符合惯用语,因为它只有一行... 不过这是一个很好的一行,太棒了 :) - Mikle
1
''.join(chr(random.randint(32,126)) for i in range(16)) 这个怎么样? - d33tah
还可以考虑使用以下代码创建包含字母和数字的字母表:string.ascii_letters + string.digits - Sam Bull
4
请参阅 secrets.choice(在3.6+中可用)以获得一个加密安全的版本,可以替换示例中的 random.choice。 - Sam Bull
显示剩余2条评论

35

你不应该使用UUID,它们是唯一的,而不是随机的:使用CreateUUID()函数作为盐是一个好主意吗?

你的盐应该使用密码学安全的随机数,在Python 2.4+中,os.urandom是这些随机数的源(如果你有一个好的时间来源)。

# for some given b62encode function

salt = b62encode(os.urandom(16))

你也可以使用bcrypt或其他知名且由比我更专业的人员审核过的加密/哈希库来生成器。

import bcrypt
salt = bcrypt.gensalt()
# will be 29 chars you can then encode it however you want.

1
它给了我一个错误:ImportError: 找不到名为bcrypt的模块 - dorado
3
使用“pip install bcrypt”命令可以解决该错误,并表明您的计算机中未安装bcrypt包。 - Transformer
你的 base_64 示例不起作用。哈希可能包含 [./a-zA-Z0-9],而你的还会包含 +=\n - cdauth
@cdauth 鉴于我一开始误读了问题(要求使用62进制),我已经更新了内容以反映这一点。我假设存在一个编码函数 - 在SO上很容易找到其中之一。 - yarbelk

24

secrets实现老问题的新解决方案。

import secrets

random_string = secrets.token_hex(8)
将产生一个具有密码学强度的16个字符的随机字符串。与标准伪随机数生成器相比,使用此方法更加安全。引用自secrets 页面: “secrets”模块用于生成适用于管理密码、帐户认证、安全令牌和相关机密数据的密码学强度的随机数。特别地,在随机模块中,默认的伪随机数生成器是为建模和模拟而设计的,不适用于安全或密码学,应优先使用“secrets”。

11

现在在crypt模块中有一个官方的mksalt方法。它不会给你一个简单的16个字符长的字符串,而是在前面添加了$digit$,这对于大多数哈希函数来说是必需的。如果您要哈希密码,这可能更安全。

import crypt
crypt.mksalt(crypt.METHOD_SHA512)

生成如下输出:

$6$wpg9lx1sVFNFSCrP

2
不支持 Python 2.7。 - Luke Exton
更新一个旧答案,现在crypt模块已经自Python 3.11版本起被弃用,并将在3.13版本中移除(请参见PEP594)。 - lorenzli

0
import random
import string

def get_salt(size=16, chars=None):
    if not chars:
        chars = ''.join(
            [string.ascii_uppercase, 
             string.ascii_lowercase, 
             string.digits]
        )
    return ''.join(random.choice(chars) for x in range(size))

你对“盐应该是唯一的,而不是随机的”这个加盐原则有什么想法? - T.Woody
根据我所知,盐和秘密并不相同。 - kta

0

in base64:

import random, base64, struct
rand_float = random.SystemRandom().random()
salt = base64.b64encode((struct.pack('!d', rand_float)))

这将是12个字符


0

虽然这个链接可能回答了问题,但最好在这里包含答案的关键部分,并提供链接作为参考。仅有链接的答案如果链接页面发生变化,就可能失效。- 来自审核 - Chenmunka

-2

我有点喜欢:

import md5, uuid
m = md5.md5()
m.update(uuid.uuid4())
print m.digest()[:16]

那将会非常、非常随机。


1
你是不是想说 m.update(str(uuid.uuid4()))?还有 m.hexdigest()[:16]?但这样还不是 base62,对吧? - Utku Zihnioglu
抱歉,你对代码是正确的。我想,由于我的解决方案使用了 base62 字符集的子集,所以它可能适用于原帖作者。 - A. Jesse Jiryu Davis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接