【问题标题】:Generating random string based on some hex基于一些十六进制生成随机字符串
【发布时间】:2026-01-10 05:00:01
【问题描述】:

我在 python 中有一个 md5 校验和;喜欢s = '14966ba801aed57c2771c7487c7b194a'

我想要的是缩短它并使其成为“a-zA-Z0-9_.-”形式的字符串,而不会丢失我的随机 md5 校验和的熵。

输出必须是可发音的,所以我不能只做binascii.unhexlify(s)。我也不能做base64.encodestring(s) 并剪掉它,因为那样我会失去熵。

关于如何在不将十六进制对 (00->FF) 的疯狂数字 (256) 映射到不同字母的情况下解决此问题的任何想法?

我想要这个的原因是能够通过电话说出整个 md5 校验和,但使用整个字母+数字+一些特殊字符。

【问题讨论】:

  • 可能是hash(s)hex(hash(s))
  • 嗯,十六进制基本上是一种以 16 为基数的编码方式;编码为 base 65 (26+26+10+3) 应该没什么不同(除了没有内置函数可以做到这一点)。
  • 什么用例要求您需要这个?
  • 假设一个随机的s,你想缩短它而不降低熵吗?我希望你意识到这是没有意义的
  • 我希望 md5 校验和更短。一个人应该通过电话说出来,因此最好缩短它并使用整个字母+数字。我也可以使用大写和小写。

标签: python string random passwords md5


【解决方案1】:

我将根据您的要求快速而轻松地进行一些尝试,并尝试一些我认为可能对您有帮助的东西。

阅读您所写的内容,对我来说突出的要求是通过电话阅读消息摘要的一种方式。

为此,您可能需要查看Bubble Babble。 Bubble Babble 旨在将摘要(或其他内容)编码为可发音的字符串:

ASCII 输入编码 -------------------------------------------------- ---------------- `' (空字符串) `xexax' `1234567890' `xesef-disof-gytuf-katof-movif-baxux' `菠萝' `xigak-nyryk-humil-bosek-sonax'

这是一个 Python 实现:http://code.activestate.com/recipes/299133-bubblebabble/

【讨论】:

  • +1,在我看到用例是有人必须通过电话将字符串读给另一个人之后,我打算提出这个建议。
  • 很好的提示,我想我可以使用它。但是,对我来说,最终的解决方案是缩短长度并使用 a-zA-Z0-9..
【解决方案2】:

由于您希望“数字”(是的,md5 哈希只不过是一个 base16 数字,我们当然可以将其转换为 base-something 以缩短字符串)在电话中可以发音,我建议避免混合大写- / 小写。 而当我们只允许 [0-9A-Z] 时,我们可以简单地使用带有 Base36 的内置 int() 进行解码。

见:

>>> def encode(num):
        import string
        ALPHABET = string.digits + string.ascii_uppercase
        tmp = []
        while num:
            num, rem = divmod(num, len(ALPHABET))
            tmp.append(ALPHABET[rem])
        return ''.join(reversed(tmp))

>>> import hashlib
>>> the_hash = hashlib.md5('test').hexdigest()
>>> decimal_representation = int(the_hash, 16)
>>> encoded = encode(decimal_representation)
>>> the_hash
'098f6bcd4621d373cade4e832627b4f6'
>>> decimal_representation
12707736894140473154801792860916528374L
>>> encoded
'KDISMNX5MOYU6Q6PZT8TQDPY'
>>> decimal_representation == int(encoded, 36)
True
>>> hex(int(encoded, 36))
'0x98f6bcd4621d373cade4e832627b4f6L'

您当然可以使用更长的字母来缩短生成的字符串,但是您必须编写自己的 decode() 函数。不过应该不会太难。

【讨论】:

  • 这正是我想要的。我把它改成了 string.ascii_letters + '1234567890' + ',.-_*!|@#$%&=+?'作为字符,它的工作方式与您期望的一样。非常感谢!
【解决方案3】:
  • 简短回答:你不能
  • 更长的答案:
    一个 md5 哈希和包含 128 位信息,因此要存储它,您还需要 128 位。您从中获得的最接近人类可读形式的可能是对它进行base64编码,这将为您留下22个字符(24个带有填充)。这可能很短。*
    无论如何,您的 md5 哈希中的随机性来自哪里? md5 散列不是随机的,因此您可能正在随机散列一些东西(什么?)来获取它们(这样做您不能以任何方式增加熵,只能减少它)。

*您可能会创建自己的方式来使用 unicode 范围内的更大范围的字符对校验和进行编码......但这意味着您必须选择一组合适的字符,任何人都会知道如何发音...... .
☺ ⚓ ⚔ ☂ ☏ 之类的东西看起来很清楚,但 之类的符号没有那么多...

【讨论】:

  • 感谢 cmets。 md5总和是计算出来的,所以它不是“随机”的。 md5 总和也是 32 个字符长,因此将其降低到 22 会好得多。使用扩展的可打印 ascii,我可以将其降低到 17-18 左右(请参阅en.wikipedia.org/wiki/Password_strength#Random_passwords)。
  • 我知道您使用的是十六进制摘要,它已经是一种编码表示。在这种情况下最好使用原始摘要 - 例如:hashlib.new("md5", "test").digest().encode('base64')
最近更新 更多