我正在使用一个API,它接受最多21个字符的名称来表示一个内部会话,其寿命大约为"两天"。我希望使用某种哈希方式使名称不具备意义?MD5生成40个字符,有其他可用的方法吗?
目前,我使用'user id[:10]' + 创建时间:ddhhmmss + 随机3个字符。
谢谢。
我正在使用一个API,它接受最多21个字符的名称来表示一个内部会话,其寿命大约为"两天"。我希望使用某种哈希方式使名称不具备意义?MD5生成40个字符,有其他可用的方法吗?
目前,我使用'user id[:10]' + 创建时间:ddhhmmss + 随机3个字符。
谢谢。
>>> import uuid
>>> u = uuid.uuid4()
>>> u
UUID('d94303e7-1be4-49ef-92f2-472bc4b4286d')
>>> u.bytes
'\xd9C\x03\xe7\x1b\xe4I\xef\x92\xf2G+\xc4\xb4(m'
>>> len(u.bytes)
16
>>>
16个随机字节非常难以猜测,如果你只想要一个不可预测的不透明标识符,那么没有必要使用API允许的全部21个字节。
如果不能直接使用原始字节,这可能是一个不好的主意,因为它在日志和其他调试消息中更难使用,并且比较起来更困难,那么可以将字节转换为一些更易读的东西,比如使用base-64编码,结果被裁剪为21(或其他)个字节:
>>> u.bytes.encode("base64")
'2UMD5xvkSe+S8kcrxLQobQ==\n'
>>> len(u.bytes.encode("base64"))
25
>>> u.bytes.encode("base64")[:21]
'2UMD5xvkSe+S8kcrxLQob'
>>>
os.urandom(16).encode("base64")[:21]
但如果您不想担心其可用性,那么请使用uuid模块。
base64.urlsafe_b64encode(uuid.uuid4().bytes)[:21]
来生成URL安全的字符串。需要导入import base64
模块。 - andilabsMD5的十六进制表示法随机性非常差:每个字符只有4位熵。
使用随机字符,例如:
import random
import string
"".join([random.choice(string.ascii_letters + string.digits + ".-")
for i in xrange(21)])
u.bytes.encode("base64")
import base64
token = base64.urlsafe_b64encode(u.bytes)
u = uuid.UUID(bytes=base64.urlsafe_b64decode(token))
字符还是字节?如果它接受任意字符串,你可以直接使用字节而不必担心扩展到可读字符(对于这种情况,base64比十六进制更好)。
如果不使用其十六进制扩展,MD5生成16个字符。在相同条件下,SHA1生成20个字符。
>>> import hashlib
>>> len(hashlib.md5('foobar').digest())
16
>>> len(hashlib.sha1('foobar').digest())
20
在此之后需要几个额外的字节。