我正在使用一個名稱爲21個字符的api來表示一個內部會話,該會話的生命週期爲「兩天」。我希望這個名字不要使用某種形式的意義? MD5生成40個字符,有什麼我可以使用? Python和21個字符的隨機密鑰最大
現在我用'userid [:10]'+創建時間:ddhhmmss +隨機3個字符。
感謝,
我正在使用一個名稱爲21個字符的api來表示一個內部會話,該會話的生命週期爲「兩天」。我希望這個名字不要使用某種形式的意義? MD5生成40個字符,有什麼我可以使用? Python和21個字符的隨機密鑰最大
現在我用'userid [:10]'+創建時間:ddhhmmss +隨機3個字符。
感謝,
如果我正確地閱讀你的問題,你想要生成一些任意的標識符令牌,它必須是最多21個字符。它是否需要高度抵抗猜測?你給出的例子不是「crytographically強」,因爲它可以通過搜索少於整個可能的密鑰空間的1/2來猜測。
您不會說這些字符是否可以是全部256個ASCII字符,或者是否需要限制爲可打印的ASCII(33-127,含)或更小的範圍。
有一個爲 UUID s(通用唯一標識符)設計的Python模塊。您可能需要uuid4,它會生成一個隨機的UUID,並使用操作系統支持(如果可用)(在Linux,Mac,FreeBSD和其他可能的系統上)。
>>> 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個隨機字節是非常難以猜測的,而且也沒有必要使用完整的21個字節的API允許,如果你想要的是有一個難以猜測的不透明標識符。
如果你不能使用這樣的原始字節,這可能是一個壞主意,因爲它很難在日誌和其他調試消息中使用,並且難以用眼比較,然後將字節轉換爲更易讀的字符,如使用鹼-64編碼,其結果砍倒至21(或任何)字節:
>>> u.bytes.encode("base64")
'2UMD5xvkSe+S8kcrxLQobQ==\n'
>>> len(u.bytes.encode("base64"))
25
>>> u.bytes.encode("base64")[:21]
'2UMD5xvkSe+S8kcrxLQob'
>>>
這給你長度21的極高質量的隨機串。
您可能不喜歡可能位於base-64字符串中的「+」或「/」,因爲沒有正確的轉義可能會干擾URL。既然你已經想過使用「隨機3個字符」,我不認爲這是你的擔心。如果是的話,你可以用別的東西替換這些字符(' - '和'。'可能有效),或者如果存在的話將其刪除。如其他人指出的,你可以使用.encode(「十六進制」)並得到十六進制等效值,但這只是4位的隨機性/字符*最多21個字符給你84位的隨機性,而不是兩倍。每一個位都會使您的密鑰空間翻倍,使理論搜索空間變得更小,更小。減小2E24倍。
即使使用十六進制編碼,您的密鑰空間仍然是2E24的大小,所以我認爲這更受理論上的關注。我不會擔心人們對你的系統進行暴力攻擊。
編輯 :如果有
P.S:該uuid.uuid4功能使用libuuid。從當前時間和本地以太網MAC地址中獲取它的來自os.urandom的熵(如果可用)。如果libuuid不可用,那麼uuid.uuid4函數直接從os.urandom獲取字節(如果可用),否則使用隨機模塊。隨機模塊使用基於os.urandom的默認種子(如果可用),否則使用基於當前時間的值。探測發生在每個函數調用中,所以如果你沒有os.urandom,那麼開銷會比你想象的要大一些。
回家的消息?如果你知道你有os.urandom那麼你可以做
os.urandom(16).encode("base64")[:21]
,但如果你不想擔心其可用性,然後使用UUID模塊。
爲什麼不採取第21個字符的MD5或SHA1哈希?
真的應該是相當隨機的 – coulix 2009-03-07 10:43:31
類似hashlib.md5(str(random.random()))。hexdigest()[:21] – 2009-03-07 11:56:42
random.random()默認從os.urandom獲取它的種子,否則從了time.time。假設操作系統支持os.urandom,不妨操作os.urandom(11).encode(「hex」)[:21]。 – 2009-03-07 14:59:39
MD5的十六進制表示具有非常差的隨機性:每個字符只能得到4位熵。
使用隨機字符,是這樣的:
import random
import string
"".join([random.choice(string.ascii_letters + string.digits + ".-")
for i in xrange(21)])
在選擇把所有的可接受的字符。
雖然使用真正的哈希函數(如SHA1)也會爲您帶來不錯的結果 如果使用正確 ,增加的複雜性和CPU消耗似乎不符合您的需求。你只需要一個隨機字符串。
字符或字節?如果它使用任意字符串,則可以使用字節,而不用擔心擴展爲可讀的字符(無論如何base64會比hex更好)。
如果您不使用它的十六進制擴展,則MD5會生成16個字符。 SHA1在相同條件下生成20個。
>>> import hashlib
>>> len(hashlib.md5('foobar').digest())
16
>>> len(hashlib.sha1('foobar').digest())
20
之後需要幾個額外的字節。
base64模塊可以進行URL安全編碼。因此,如果需要的話,而不是
u.bytes.encode("base64")
你可以做
import base64
token = base64.urlsafe_b64encode(u.bytes)
和方便,轉換回
u = uuid.UUID(bytes=base64.urlsafe_b64decode(token))
你必須思考SHA1。 MD5是32位十六進制數字。 – kmkaplan 2009-03-07 11:28:31