【问题标题】:Hashing (hiding) strings in Python在 Python 中散列(隐藏)字符串
【发布时间】:2013-11-04 00:21:49
【问题描述】:

我需要的是散列一个字符串。它不一定是安全的,因为它只是文本文件中的一个隐藏短语(它只是不必被人眼识别)。

它不应该只是一个随机字符串,因为当用户键入字符串时,我想对其进行散列并将其与已经散列的字符串(来自文本文件)进行比较。

什么是最好的?可以用内置类来完成吗?

【问题讨论】:

  • 您的真正问题是什么?散列算法有很多种,bset 方法取决于你将如何使用散列字符串。

标签: python string encryption hash


【解决方案1】:

首先,让我说你不能保证唯一的结果。如果您想要宇宙中所有字符串的唯一结果,最好存储字符串本身(或压缩版本)。

稍后会详细介绍。让我们先获取一些哈希值。

hashlib 方式

您可以通过几个步骤使用任何主要的加密散列来散列字符串:

>>> import hashlib
>>> sha = hashlib.sha1("I am a cat")
>>> sha.hexdigest()
'576f38148ae68c924070538b45a8ef0f73ed8710'

就内置而言,您可以在 SHA1、SHA224、SHA256、SHA384、SHA512 和 MD5 之间进行选择。

这些哈希算法有什么区别?

哈希函数通过获取可变长度的数据并将其转换为固定长度的数据来工作。

对于每个内置于hashlib 的 SHA 算法,固定长度是名称中指定的位数(sha1 除外,它是 160 位)。如果您想更好地确定两个字符串不会最终出现在同一个存储桶中(相同的哈希值),请选择具有更大摘要(固定长度)的哈希。

按排序顺序,这些是您必须使用的摘要大小:

Algorithm  Digest Size (in bits)
md5        128
sha1       160
sha224     224
sha256     256
sha384     384
sha512     512

摘要越大,发生冲突的可能性就越小,前提是您的哈希函数物有所值。

等等,hash() 呢?

内置的hash() 函数返回整数,这也可以很容易地用于您概述的目的。不过也有问题。

>>> hash('moo')
6387157653034356308
  1. 如果你的程序要在不同的系统上运行,你不能确定hash 会返回同样的东西。事实上,我正在使用 64 位 Python 的 64 位机器上运行。这些值将与 32 位 Python 大不相同。

  2. 对于 Python 3.3+,正如@gnibbler 指出的那样,hash() 在运行之间是随机的。它适用于单次运行,但几乎肯定不会跨程序运行(从您提到的文本文件中提取)。

为什么hash() 会这样构建?好吧,内置哈希是出于一个特定的原因。哈希表/字典/在内存中查找表。不是用于加密,而是用于在运行时进行廉价查找。

不要使用hash(),使用hashlib

【讨论】:

  • hash() 在 Python3.3 以来的运行之间是随机的,即。您只能依靠它在一次程序运行中返回相同的值
  • 太棒了。感谢@gnibbler,我不知道它在运行之间不稳定。
【解决方案2】:

您可以简单地使用 base64 模块来实现您的目标:

>>> import base64
>>> a = 'helloworld'
>>> encoded_str = base64.encodestring(a)
>>> encoded_str
'aGVsbG93b3JsZA=='
>>> base64.decodestring(encoded_str)
'helloworld'
>>>

当然你也可以使用 hashlib 模块,它更安全,因为散列后的字符串不能(或非常非常难)被解码,但是对于你的问题 base64 就足够了——“它并不需要安全”

【讨论】:

  • 默认情况下base64 是否附带 Python2.3(是的,我知道它很奇怪)?
  • 是的!在 Python 2.3 中运行上述代码就可以了Learn More From Here
【解决方案3】:

请注意,Python 的字符串哈希不是“定义的”——它可以而且确实会因版本和实现而异。因此存储 Python 字符串哈希会产生困难。 CPython 的字符串哈希也没有试图变得“晦涩”。

一个标准的方法是使用散列函数为这种事情设计。像这样:

>>> import hashlib
>>> encoded = hashlib.sha1("abcdef") # "abcdef" is the password
>>> encoded.hexdigest()
'1f8ac10f23c5b5bc1167bda84b833e5c057a77d2'

那一长串十六进制数字就是“哈希”。 SHA-1 是一个“强”的散列函数。如果你找到两个哈希值相同的字符串,你就会出名;-) 给定相同的输入,它将在所有平台上的所有 Python 版本和实现中返回相同的“hexdigest”。

【讨论】:

  • 特别是因为 Python3.3 hash(somestring) 在运行之间是不同的
【解决方案4】:

只需使用hash()内置函数即可,例如:

s = 'a string'
hash(s)
=> -8411828025894108412

【讨论】:

  • 这会为每个字符串生成唯一的数字吗?可以解码(只是好奇)?
  • @Lucas,固定大小的哈希函数不可能为所有可能的字符串返回不同的值。例如,如果一个哈希函数返回 2 位,则它只有 4 个可能的值。
  • @Lucas 不,哈希不能被“解码”。如果两个对象相等,则它们的哈希值相等;但是,许多对象可以(在字符串的情况下)解析为相同的哈希值。
  • 这是个坏主意。在其他答案上查看我的 cmets
  • Python 2 中字符串的哈希冲突示例描述于:stackoverflow.com/q/37127946/1959808
猜你喜欢
  • 1970-01-01
  • 2016-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 2011-09-30
  • 2020-03-17
  • 2022-01-25
相关资源
最近更新 更多