如何生成文件的 MD5 校验和?
有没有简单的方法可以在 Python 中生成(和检查)文件列表的 MD5 校验和? (我正在开发一个小程序,我想确认文件的校验和)。
Is there any simple way of generating (and checking) MD5 checksums of a list of files in Python? (I have a small program I'm working on, and I'd like to confirm the checksums of the files).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
你可以使用 hashlib.md5()
注意,有时你会无法适应内存中的整个文件。在这种情况下,您必须顺序读取 4096 字节的块并将它们提供给
md5
方法:注意:
hash_md5.hexdigest()
将返回摘要的十六进制字符串表示形式,如果您只需要打包字节,请使用return hash_md5.digest()
,这样您就不必转换回来。You can use hashlib.md5()
Note that sometimes you won't be able to fit the whole file in memory. In that case, you'll have to read chunks of 4096 bytes sequentially and feed them to the
md5
method:Note:
hash_md5.hexdigest()
will return the hex string representation for the digest, if you just need the packed bytes usereturn hash_md5.digest()
, so you don't have to convert back.有一种内存效率低下的方法。
单个文件:
文件列表:
不过请记住,MD5 已知已损坏,因此不应被损坏用于任何目的,因为漏洞分析可能非常棘手,并且分析代码将来可能用于解决安全问题的任何可能用途是不可能的。恕我直言,它应该从库中完全删除,这样每个使用它的人都被迫更新。因此,您应该这样做:
如果您只想要 128 位的摘要,您可以执行
.digest()[:16]
。这将为您提供一个元组列表,每个元组包含其文件名及其哈希值。
我再次强烈质疑您对 MD5 的使用。您至少应该使用 SHA1,并且考虑到 最近在 SHA1 中发现的缺陷,可能还不是这样。有些人认为只要您不将 MD5 用于“加密”目的,就可以了。但事情的范围往往会比你最初预期的更广泛,而你的随意漏洞分析可能会被证明是完全有缺陷的。最好一开始就养成使用正确算法的习惯。只需输入一组不同的字母即可。这并不难。
这是一种更复杂的方法,但是内存效率高:
而且,由于 MD5 已损坏并且不应该再使用:
同样,您可以将
[:16]<如果您只需要 128 位的摘要,请在调用
hash_bytestr_iter(...)
之后使用 /code> 。There is a way that's pretty memory inefficient.
single file:
list of files:
Recall though, that MD5 is known broken and should not be used for any purpose since vulnerability analysis can be really tricky, and analyzing any possible future use your code might be put to for security issues is impossible. IMHO, it should be flat out removed from the library so everybody who uses it is forced to update. So, here's what you should do instead:
If you only want 128 bits worth of digest you can do
.digest()[:16]
.This will give you a list of tuples, each tuple containing the name of its file and its hash.
Again I strongly question your use of MD5. You should be at least using SHA1, and given recent flaws discovered in SHA1, probably not even that. Some people think that as long as you're not using MD5 for 'cryptographic' purposes, you're fine. But stuff has a tendency to end up being broader in scope than you initially expect, and your casual vulnerability analysis may prove completely flawed. It's best to just get in the habit of using the right algorithm out of the gate. It's just typing a different bunch of letters is all. It's not that hard.
Here is a way that is more complex, but memory efficient:
And, again, since MD5 is broken and should not really ever be used anymore:
Again, you can put
[:16]
after the call tohash_bytestr_iter(...)
if you only want 128 bits worth of digest.我显然没有添加任何根本性的新内容,但在我达到评论状态之前添加了这个答案,加上代码区域使事情变得更加清晰 - 无论如何,特别是从 Omnifarious 的答案中回答 @Nemo 的问题:
我碰巧在考虑稍微检查一下(特别是来这里寻找有关块大小的建议),并发现这种方法可能比您预期的要快。从对大约文件进行校验和的几种方法中的每一种中获取最快(但非常典型)
timeit.timeit
或/usr/bin/time
结果。 11MB:所以,看起来 Python 和 /usr/bin/md5sum 对于 11MB 文件大约需要 30 毫秒。相关的
md5sum
函数(上面清单中的md5sum_read
)与 Omnifarious 的非常相似:当然,这些来自单次运行(
mmap
是当至少进行几十次运行时,总是会快一点),并且我的通常在缓冲区耗尽后得到一个额外的f.read(blocksize)
,但它是相当可重复的,并且显示命令行上的 md5sum
不一定比 Python 实现更快...编辑:抱歉这么长时间的延迟,有一段时间没有看过这个了,但是为了回答 @EdRandall 的问题,我会写下来Adler32 实现。但是,我还没有为其运行基准测试。它基本上与 CRC32 相同:所有内容都是
zlib.adler32()
调用,而不是 init、update 和digest 调用:请注意,这必须以空字符串开始,因为阿德勒总和从零开始与
""
的总和(即1
)确实不同——CRC 可以从0
开始。需要使用AND
-ing 使其成为 32 位无符号整数,这确保它在各个 Python 版本中返回相同的值。I'm clearly not adding anything fundamentally new, but added this answer before I was up to commenting status, plus the code regions make things more clear -- anyway, specifically to answer @Nemo's question from Omnifarious's answer:
I happened to be thinking about checksums a bit (came here looking for suggestions on block sizes, specifically), and have found that this method may be faster than you'd expect. Taking the fastest (but pretty typical)
timeit.timeit
or/usr/bin/time
result from each of several methods of checksumming a file of approx. 11MB:So, looks like both Python and /usr/bin/md5sum take about 30ms for an 11MB file. The relevant
md5sum
function (md5sum_read
in the above listing) is pretty similar to Omnifarious's:Granted, these are from single runs (the
mmap
ones are always a smidge faster when at least a few dozen runs are made), and mine's usually got an extraf.read(blocksize)
after the buffer is exhausted, but it's reasonably repeatable and shows thatmd5sum
on the command line is not necessarily faster than a Python implementation...EDIT: Sorry for the long delay, haven't looked at this in some time, but to answer @EdRandall's question, I'll write down an Adler32 implementation. However, I haven't run the benchmarks for it. It's basically the same as the CRC32 would have been: instead of the init, update, and digest calls, everything is a
zlib.adler32()
call:Note that this must start off with the empty string, as Adler sums do indeed differ when starting from zero versus their sum for
""
, which is1
-- CRC can start with0
instead. TheAND
-ing is needed to make it a 32-bit unsigned integer, which ensures it returns the same value across Python versions.在 Python 3.8+ 中,您可以使用 赋值运算符
:=
(以及hashlib
) 像这样:考虑使用
hashlib .blake2b
而不是md5
(只需将上面代码片段中的md5
替换为blake2b
)。它具有加密安全性,并且比 MD5 更快。In Python 3.8+, you can can use the assignment operator
:=
(along withhashlib
) like this:Consider using
hashlib.blake2b
instead ofmd5
(just replacemd5
withblake2b
in the above snippet). It's cryptographically secure and faster than MD5.在 Python 3.11+ 中,有一个新的可读和节省内存的方法:
In Python 3.11+, there's a new readable and memory-efficient method:
您可以使用
simple-file-checksum
1,仅使用subprocess
调用openssl
(适用于 macOS/Linux 和CertUtil
(适用于 Windows)并仅提取输出摘要:安装:
用法:
还支持
SHA1
、SHA256
、SHA384
和SHA512
算法。1 披露:我是
simple-file 的作者-校验和
。You could use
simple-file-checksum
1, which just usessubprocess
to callopenssl
for macOS/Linux andCertUtil
for Windows and extracts only the digest from the output:Installation:
Usage:
The
SHA1
,SHA256
,SHA384
, andSHA512
algorithms are also supported.1 Disclosure: I am the author of
simple-file-checksum
.将
file_path
更改为您的文件change the
file_path
to your file你可以在这里使用 shell。
you can make use of the shell here.