加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 如何计算我需要多少哈希才能找到碰撞?

发布时间:2020-12-20 13:38:10 所属栏目:Python 来源:网络整理
导读:我正在开发一个程序,使用十六进制字符将图像URL散列为10个字符的字符串,例如64fd54ad29. 它是用Python编写的,哈希的计算如下: def hash_short(self,url): return hashlib.sha1(url).hexdigest()[:10] 我担心与这么短的哈希冲突.我预计在大约一百万次哈希之
我正在开发一个程序,使用十六进制字符将图像URL散列为10个字符的字符串,例如64fd54ad29.

它是用Python编写的,哈希的计算如下:

def hash_short(self,url):
     return hashlib.sha1(url).hexdigest()[:10]

我担心与这么短的哈希冲突.我预计在大约一百万次哈希之后会发生碰撞,但是当我遇到蛮力时我需要一千万次哈希.

计算

十六进制数字有16个可能的值,或2 ^ 4.有十个字符,我有2 ^ 40种可能性,或40位熵.

为了得到1的概率,我们需要查看2 ^ 40 1个URL(通过鸽子原理),但我们会更快地发现碰撞.

n位散列的生日攻击(即暴力)将在2 ^(n / 2)次尝试后发现冲突.因此,我们会看到大约2 ^ 20个URL后的冲突,即1,048,576.

蛮力

我写了一个简单的Python脚本,迭代了很长的URL列表,并将每个哈希值与我之前看到的哈希值进行了比较.我花了10,800,000个网址才找到我的第一次碰撞:“http://c69025.r25.cf3.rackcdn.com/_image1/_Model/34897.jpg”和“http://media.editd.com/assets/matrix/ full / 72f9a997b67c65c66f4adc769ee0a127d1db25eb.jpg“都哈希到”ba2be44bd1“.

import hashlib
import json

def calculate_short_hash(url):
    return hashlib.sha1(url).hexdigest()[:10]


def url_from_json(json_string):
    return json.loads(json_string)['image_url']

if __name__ == '__main__':
    short_hashes = set()

    for i,line in enumerate(open('urls.all')):
        short_hash = calculate_short_hash(url_from_json(line))

        if short_hash in short_hashes:
            print "Already seen: %s" % short_hash
            break
        else:
            short_hashes.add(short_hash)

        if i % 100000 == 0:
            print "Processed %d lines" % (i,)

摘要

要么我的数学不正确,要么我非常不走运.这是什么?我多么不走运?

解决方法

我认为您的碰撞检测代码是错误的:

import hashlib
import random
import string

def hash_short(url):
     return hashlib.sha1(url).hexdigest()[:10]

hashes = dict()
while True:
    if len(hashes) % 10000 == 0:
        print len(hashes)
    newurl = ''.join(random.choice(string.lowercase) for _ in xrange(30))
    newhash = hash_short(newurl)
    if newhash in hashes and newurl != hashes[newhash]:
        print 'found a collision!'
        print newhash
        print newurl
        print hashes[newhash]
        print len(hashes)
        break
    hashes[newhash] = newurl

输出(运行一次):

...
770000
780000
found a collision!
216be03ec7
txnbkwrfkpkmiexloxrifdsnjumkex
xlnmlhobtsswjvmqnjupaybkspptpo
780758

显然我的所谓的url不是,但是这应该与一个好的哈希函数没有区别(并且SHA1有利于此目的).如果你发现一个数据集在SHA1的前5个字节上确实具有异常低的冲突率,那么做得好!用最后5个字节再试一次:-)

你有点不走运?当你有1000万个哈希时,你的2 ** 40空间已经满了大约100k的一个部分.所以没有碰撞的概率大致是(手指在空中),(99999.0 / 100000)** 1000万,即3.7e-44.因此,如果我的数学是正确的[编辑:它不是,请参阅评论]你是天文数字,被定罪 – 超出合理怀疑不幸.

作为偶然发生碰撞概率的保守上限,在已经有100万个哈希值发挥作用后,你做了900万次试验.没有碰撞的概率严格小于(999999.0 / 1000000)** 9000000,仅为0.0001.你可以通过进一步分割它来产生更小的界限:你进行了100万次试验,占用了900万个哈希值.或者你可以准确地计算概率(CodesInChaos做了:1e-20)

所以,贝叶斯统计数据就是这样,我估计你的代码中的错误概率高于所有这些数字,甚至是真正大的保守界限:-)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读