【问题标题】:What hash algorithm does Python's dictionary mapping use?Python 的字典映射使用什么哈希算法?
【发布时间】:2012-02-18 08:27:47
【问题描述】:

我正在做一个命令行解析器,想知道 python dict 使用什么样的哈希算法?

按照我的设置方式,我有一个模式匹配算法,它将标记化的输入序列与字典键匹配。有些键相对较长(长度为 5 或 6 个 6-7 个字符串的元组)。我想知道是否存在长字典键显着降低键检索效率的点。

【问题讨论】:

  • 看看this question。它有一个指向 this page 的链接,它描述了 python 如何散列一些不同的类型,它可能对你有帮助。
  • 许多现代散列代码已针对 PEP 456 进行了修改,此处记录:python.org/dev/peps/pep-0456。答案是:根据编译参数和字符串大小,可以使用多个哈希函数。

标签: python hashmap


【解决方案1】:

它使用的哈希取决于用作键的对象——每个类都可以定义自己的 __hash__() 方法,它为特定实例返回的值就是用于字典的值。

Python 本身为 str 和 tuple 类型提供了哈希实现。快速浏览一下源代码应该会发现它们的确切算法。

元组的哈希值基于其内容的哈希值。算法本质上是这样的(稍微简化了):

def hash(tuple):
    mult = 1000003
    x = 0x345678
    for index, item in enumerate(tuple):
        x = ((x ^ hash(item)) * mult) & (1<<32)
        mult += (82520 + (len(tuple)-index)*2)
    return x + 97531

对于字符串,解释器还遍历每个字符,将它们与这个(再次稍微简化的)算法相结合:

def hash(string):
    x = string[0] << 7
    for chr in string[1:]:
        x = ((1000003 * x) ^ chr) & (1<<32)
    return x

要担心的更大问题是避免哈希冲突。当字典试图找到存储新对象的位置时,冲突的哈希键将导致线性搜索(这现在被认为是一个安全问题,并且在即将推出的 python 版本中行为可能会发生变化)

【讨论】:

  • 哦,好的。出于某种原因,我假设 python 只是对所有数据类型使用了通用的字节码哈希算法。就碰撞哈希键而言,我认为这不会成为问题,因为我将拥有的键数量(相对)很少——可能有数千个。请原谅我的无知,但是冲突的哈希和线性搜索如何成为安全问题?
  • @Joel Cornett:这是一个安全问题,因为哈希表使用桶来存储密钥,具有相同哈希码的密钥将被哈希到同一个桶中,迫使哈希表进行线性搜索每次它搜索一个密钥时,如果密钥的数量很大,这可能会非常低效(甚至可能导致拒绝服务)。如果程序遇到具有不同键且散列到相同散列码的散列表,则可能导致拒绝服务攻击。
  • 如果攻击者可以控制字典中使用的键,那么他们可能能够插入成百上千的冲突键,从而使插入操作非常缓慢。在某些情况下,这可能会导致机器无响应或数据库无法使用——Dos 攻击
  • 是否有发起此类攻击的记录案例?对于除了最简单的系统之外的所有系统似乎都非常困难,如果没有白盒知识则更难。
  • 我听说的第一个攻击场景是针对 Web 服务的——如果 POST 变量最终出现在一个以它们的名字为关键字的字典中,那么攻击者就可以完全控制这些键,并且可以减慢速度任意一个服务器,有足够的变量。不过,我不知道野外是否有这样的攻击。
猜你喜欢
  • 1970-01-01
  • 2011-01-25
  • 2020-04-15
  • 2010-09-13
  • 2014-08-09
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多