在Python中散列文件

时间:2014-02-27 02:50:28

标签: python hash md5 sha1 hashlib

我想让python读取到EOF,这样我就可以得到一个合适的哈希值,无论是sha1还是md5。请帮忙。以下是我到目前为止的情况:

import hashlib

inputFile = raw_input("Enter the name of the file:")
openedFile = open(inputFile)
readFile = openedFile.read()

md5Hash = hashlib.md5(readFile)
md5Hashed = md5Hash.hexdigest()

sha1Hash = hashlib.sha1(readFile)
sha1Hashed = sha1Hash.hexdigest()

print "File Name: %s" % inputFile
print "MD5: %r" % md5Hashed
print "SHA1: %r" % sha1Hashed

7 个答案:

答案 0 :(得分:93)

TL; DR使用缓冲区不使用大量内存。

我相信,当我们考虑使用非常大的文件的内存含义时,我们会遇到问题的关键。我们不希望这个坏男孩为2千兆字节的文件翻译2个ram,所以,正如pasztorpisti指出的那样,我们必须处理那些大块的文件!

import sys
import hashlib

# BUF_SIZE is totally arbitrary, change for your app!
BUF_SIZE = 65536  # lets read stuff in 64kb chunks!

md5 = hashlib.md5()
sha1 = hashlib.sha1()

with open(sys.argv[1], 'rb') as f:
    while True:
        data = f.read(BUF_SIZE)
        if not data:
            break
        md5.update(data)
        sha1.update(data)

print("MD5: {0}".format(md5.hexdigest()))
print("SHA1: {0}".format(sha1.hexdigest()))

我们所做的是,当我们使用hashlib的方便花花公子update method时,我们正在以64kb块更新这个坏孩子的哈希值。通过这种方式,我们使用的内存比2gb一样少,可以同时散列这个人!

你可以用以下方法测试:

$ mkfile 2g bigfile
$ python hashes.py bigfile
MD5: a981130cf2b7e09f4686dc273cf7187e
SHA1: 91d50642dd930e9542c39d36f0516d45f4e1af0d
$ md5 bigfile
MD5 (bigfile) = a981130cf2b7e09f4686dc273cf7187e
$ shasum bigfile
91d50642dd930e9542c39d36f0516d45f4e1af0d  bigfile

希望有所帮助!

所有这些都在右侧的链接问题中列出:Get MD5 hash of big files in Python


附录!

一般来说,编写python时,有助于养成遵循pep-8的习惯。例如,在python中,变量通常是下划线而不是camelCased。但这只是风格,除了那些必须阅读不良风格的人之外,没有人真正关心那些事情......这可能是你从现在开始阅读这段代码。

答案 1 :(得分:32)

为了正确有效地计算文件的哈希值(在Python 3中):

  • 以二进制模式打开文件(即将'b'添加到文件模式)以避免字符编码和行结束转换问题。
  • 不要将完整的文件读入内存,因为这会浪费内存。相反,逐块顺序读取它并更新每个块的哈希值。
  • 消除双缓冲,即不使用缓冲IO,因为我们已经使用了最佳块大小。
  • 使用readinto()来避免缓冲搅动。

示例:

import hashlib

def sha256sum(filename):
    h  = hashlib.sha256()
    b  = bytearray(128*1024)
    mv = memoryview(b)
    with open(filename, 'rb', buffering=0) as f:
        for n in iter(lambda : f.readinto(mv), 0):
            h.update(mv[:n])
    return h.hexdigest()

答案 2 :(得分:6)

以二进制模式打开文件,默认模式open()'r',“打开以便以文本模式阅读”。在文本模式下,对数据执行换行转换,这也可能导致特定于平台的错误,但是由于文本模式可能发生的问题是'\ r \ n'序列被替换为'\ n'序列你会得到你的手。并非所有文件都包含'\ r \ n'序列,特别是在二进制文件的情况下,因此错误不会一直存在,并且很难捕获它。

openedFile = open(inputFile, 'rb')

这里还有一个小问题,你在一个大块中读取文件,通过在较小的几千字节块中读取它,你可以散列非常大的文件,即使它们不适合你的可用内存。

答案 3 :(得分:5)

这是Python 3,POSIX解决方案(不是Windows!),它使用mmap将对象映射到内存中。

import hashlib
import mmap

def sha256sum(filename):
    h  = hashlib.sha256()
    with open(filename, 'rb') as f:
        with mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) as mm:
            h.update(mm)
    return h.hexdigest()

答案 4 :(得分:2)

我编写了一个能够使用不同算法散列大文件的模块。

pip3 install py_essentials

使用这样的模块:

from py_essentials import hashing as hs
hash = hs.fileChecksum("path/to/the/file.txt", "sha256")

答案 5 :(得分:2)

import hashlib
user = input("Enter ")
h = hashlib.md5(user.encode())
h2 = h.hexdigest()
with open("encrypted.txt","w") as e:
    print(h2,file=e)


with open("encrypted.txt","r") as e:
    p = e.readline().strip()
    print(p)

答案 6 :(得分:0)

我会简单地建议:

def get_digest(file_path):
    h = hashlib.sha256()

    with open(file_path, 'rb') as file:
        while True:
            # Reading is buffered, so we can read smaller chunks.
            chunk = file.read(h.block_size)
            if not chunk:
                break
            h.update(chunk)

    return h.hexdigest()

这里所有其他答案似乎太复杂了。 Python在读取时已经在缓冲(以理想的方式,或者如果您有更多有关基础存储的信息,则可以配置该缓冲),因此最好分块读取散列函数找到的理想值,这样可以使其更快或更省时计算哈希函数。因此,您可以使用Python缓冲并控制应该控制的内容,而不是禁用缓冲并尝试自己模拟它,即数据消费者可以找到理想的哈希块大小。