【问题标题】:Creating a unique key based on file content in python在python中根据文件内容创建唯一键
【发布时间】:2011-02-15 16:50:59
【问题描述】:

我有很多很多文件要上传到服务器,我只是想要一种避免重复的方法。

因此,从大字符串生成唯一且小的键值似乎是校验和的目的,hashing seemed like the evolution of that

所以我打算使用哈希 md5 来执行此操作。但后来我读到 somewhere 说“MD5 并不意味着是唯一键”,我觉得这真的很奇怪。

正确的做法是什么?

编辑: 顺便说一句,我使用two sources 进行以下操作,这就是我目前正在做的事情,并且使用 Python 2.5 运行良好:

import hashlib

def md5_from_file (fileName, block_size=2**14):
    md5 = hashlib.md5()
    f = open(fileName)
    while True:
        data = f.read(block_size)
        if not data:
            break
        md5.update(data)
    f.close()
    return md5.hexdigest()

【问题讨论】:

  • 使用 "f = open(fileName, 'rb')" 在 Windows 上获得正确的结果

标签: python hash cryptography checksum unique-key


【解决方案1】:

坚持使用 MD5 是个好主意。只是为了确保我将文件长度或块数附加到您的文件哈希表中。

是的,您可能会遇到两个具有相同 MD5 哈希值的文件,但这不太可能(如果您的文件大小合适)。因此,将块的数量添加到您的哈希中可能会帮助您减少这种情况,因为现在您必须找到两个大小相同且 MD5 相同的文件。

# This is the algorithm you described, but also returns the number of chunks.
new_file_hash, nchunks = hash_for_tile(new_file)
store_file(new_file, nchunks, hash)

def store_file(file, nchunks, hash):
  "" Tells you whether there is another file with the same contents already, by 
     making a table lookup ""
  # This can be a DB lookup or some way to obtain your hash map
  big_table = ObtainTable()

  # Two level lookup table might help performance
  # Will vary on the number of entries and nature of big_table
  if nchunks in big_table:
     if hash in big_table[hash]:
       raise DuplicateFileException,\
         'File is dup with %s' big_table[nchunks][lookup_hash]
  else:
    big_table[nchunks] = {}

  big_table[nchunks].update({
    hash: file.filename
  })

  file.save() # or something

为了减少这种可能性,请切换到 SHA1 并使用相同的方法。如果性能不是问题,甚至使用两者(连接)。

当然,请记住,这仅适用于二进制级别的重复文件,而不适用于“相同”但具有不同签名的图像、声音、视频。

【讨论】:

  • 嗯,我的案例实际上是关于大图像和大视频的,性能是一个很大的问题。但是,是的,例如,我不希望它检测到同一场景的两个稍微不同的角度。
  • 这绝对是最好的答案。如果 OP 想要比 SHA1 更好,而不是连接,他应该只使用 SHA2。
  • 在散列中添加更多数据只会改变你的散列函数(例如,这个答案说“在 MD5 返回的内容上附加一些其他值以生成更长的散列”)。有时这是最简单的,但您也可以首先生成更长的散列。唉,散列不能防止冲突。
  • #dash 怎么做才能生成更长的哈希?我在关于 hashlib 的文档上看不到任何指向这一点。
  • 您可以通过将两个(独立)散列函数的结果一个接一个地粘贴来轻松获得更长的散列。例如。如果你取 MD5 返回值,然后将文件长度连接到它上面,那么你有一个更长的哈希值。文件长度不是一个好的散列算法,但它作为一个例子很有用。不过,我对任何公共散列 API 一无所知,所以我不知道你会/可以给它们提供什么,尽管我怀疑 MD5 向后处理数据会产生足够不可重复的结果,即连接正向和反向哈希将是双重强度。
【解决方案2】:

散列的问题在于它从“大”数据集生成“小”标识符。这就像一个有损压缩。虽然您不能保证唯一性,但您可以使用它来大幅限制需要比较的其他项目的数量。

考虑 MD5 产生一个 128 位的值(我认为就是这样,尽管确切的位数无关紧要)。如果您的输入数据集有 129 位并且您实际上全部使用了它们,则每个 MD5 值平均会出现两次。对于更长的数据集(例如,“所有正好有 1024 个可打印字符的文本文件”),一旦你获得足够的输入,你仍然会遇到冲突。与另一个答案所说的相反,在数学上肯定会发生碰撞。

http://en.wikipedia.org/wiki/Birthday_Paradox

诚然,在 2.6*10^18 个条目处,与 128 位哈希发生冲突的几率约为 1%,但最好处理确实发生冲突的情况,而不是希望永远不会发生冲突。

【讨论】:

    【解决方案3】:

    MD5 的问题在于它已损坏。对于最常见的用途,几乎没有问题,人们仍然同时使用 MD5 和 SHA1,但我认为如果你需要一个散列函数,那么你需要一个强大的散列函数。据我所知,仍然没有标准的替代品。有许多算法“被认为”很强大,但我们在 SHA1 和 MD5 方面拥有最多的经验。也就是说,我们(认为)我们知道这两种算法何时崩溃,而我们并不真正知道新算法何时崩溃。

    底线:考虑风险。如果您希望多走一点,那么您可以在发现哈希重复时添加额外的检查,以牺牲性能为代价。

    【讨论】:

    • 在这种情况下,散列函数的强度无关紧要。 MD5 将绝对防止重复到虚拟的数学确定性。
    • “散列函数的强度无关紧要”是什么意思?当前针对 MD5 的攻击可以让您在一秒钟内在单个 CPU 上产生冲突——所以不,MD5 不会防止“重复”
    • 正如其他地方所说,MD5 并没有防止重复/冲突,尽管它确实使它们不太可能发生。此外,MD5 仅在其加密不安全的意义上被“破坏”——如果需要,一个坚定的攻击者可能会造成冲突。但是,就原始问题而言,加密安全不是必需的,因此这不是驳回 MD5 的正当理由。
    • 生成固定长度散列的散列函数固有地容易发生冲突。只是我们不想找到两个散列到相同值的不同文本。我们知道碰撞就在那里,我们只是不想找到它们。更糟糕的是,当给定任意文本时,我们可以生成另一个散列相同的不同文本;或者当给定一个哈希值时,我们可以生成一个哈希到相同哈希值的文本。这对 OP 来说有多严重,只有 OP 知道:我认为这是一个风险评估问题。
    猜你喜欢
    • 2018-09-17
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多