假设磁盘 I/O 和可用 RAM 是瓶颈(而 CPU 时间不是限制),是否存在可以同时计算多个消息摘要的工具?
我对计算大文件(大小以 GB 为单位)的 MD-5 和 SHA-256 摘要特别感兴趣,最好是并行计算。我已经尝试过openssl dgst -sha256 -md5
,但它只使用一种算法计算哈希值。
预期行为的伪代码:
for each block:
for each algorithm:
hash_state[algorithm].update(block)
for each algorithm:
print algorithm, hash_state[algorithm].final_hash()
答案1
查看pee
(" tee standard input to pipes
") 来自moreutils
。这基本上相当于 Marco 的tee
命令,但输入起来更简单一些。
$ echo foo | pee md5sum sha256sum
d3b07384d113edec49eaa6238ad5ff00 -
b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c -
$ pee md5sum sha256sum <foo.iso
f109ffd6612e36e0fc1597eda65e9cf0 -
469a38cb785f8d47a0f85f968feff0be1d6f9398e353496ff7aa9055725bc63e -
答案2
您可以使用for
循环来循环各个文件,然后tee
与进程替换(适用于 Bash 和 Zsh 等)结合使用以通过管道传输到不同的校验和。
例子:
for file in *.mkv; do
tee < "$file" >(sha256sum) | md5sum
done
您还可以使用两个以上的校验和:
for file in *.mkv; do
tee < "$file" >(sha256sum) >(sha384sum) | md5sum
done
这样做的缺点是校验和不知道文件名,因为它是作为标准输入传递的。如果这是不可接受的,您必须手动发出文件名。完整示例:
for file in *.mkv; do
echo "$file"
tee < "$file" >(sha256sum) >(sha384sum) | md5sum
echo
done > hashfilelist
答案3
遗憾的是 openssl 实用程序不接受多个摘要命令;我想对多个文件执行相同的命令是更常见的使用模式。 FWIW,我的系统(Mepis 11)上的 openssl 实用程序版本只有 sha 和 sha1 命令,没有任何其他 sha 变体的命令。但我确实有一个名为 sha256sum 的程序,以及 md5sum。
这是一个简单的 Python 程序,dual_hash.py,它可以完成您想要的操作。 64k 的块大小似乎最适合我的机器(Intel Pentium 4 2.00GHz,2G RAM),YMMV。对于小文件,其速度与连续运行md5sum和sha256sum大致相同。但对于较大的文件,速度要快得多。例如,在一个 1967063040 字节的文件(充满 mp3 文件的 SD 卡的磁盘映像)上,md5sum + sha256sum 大约需要 1m44.9s,dual_hash.py 需要 1m0.312s。
双哈希.py
#! /usr/bin/env python
''' Calculate MD5 and SHA-256 digests of a file simultaneously
Written by PM 2Ring 2014.10.23
'''
import sys
import hashlib
def digests(fname, blocksize):
md5 = hashlib.md5()
sha = hashlib.sha256()
with open(fname, 'rb') as f:
while True:
block = f.read(blocksize)
if not block:
break
md5.update(block)
sha.update(block)
print("md5: %s" % md5.hexdigest())
print("sha256: %s" % sha.hexdigest())
def main(*argv):
blocksize = 1<<16 # 64kB
if len(argv) < 2:
print("No filename given!\n")
print("Calculate md5 and sha-256 message digests of a file.")
print("Usage:\npython %s filename [blocksize]\n" % sys.argv[0])
print("Default blocksize=%d" % blocksize)
return 1
fname = argv[1]
if len(argv) > 2:
blocksize = int(sys.argv[2])
print("Calculating MD5 and SHA-256 digests of %r using a blocksize of %d" % (fname, blocksize))
digests(fname, blocksize)
if __name__ == '__main__':
sys.exit(main(*sys.argv))
我想这个程序的 C/C++ 版本会快一点,但不会快很多,因为大部分工作是由 hashlib 模块完成的,它是用 C(或 C++)编写。正如您上面提到的,大文件的瓶颈是 IO 速度。
答案4
出于好奇多线程Python脚本是否会减少运行时间,我创建了这个digest.py
使用threading.Thread
,threading.Queue
和hashlib
来计算多个文件的哈希值的脚本。
多线程 Python 实现确实比使用pee
coreutils 稍微快一些。另一方面,Java 是......嗯。结果可在此提交消息:
为了进行比较,对于 2.3 GiB 的文件(最小/平均/max/sd 秒(n=10):
- 小便 sha256sum md5sum < 文件:16.5/16.9/17.4/.305
- python3摘要.py-sha256-md5<文件:13.7/15.0/18.7/1.77
- python2摘要.py-sha256-md5<文件:13.7/15.9/18.7/1.64
- jacksum -a sha256+md5 -F '#CHECKSUM{i} #FILENAME': 32.7/37.1/50/6.91
哈希输出与 coreutils 生成的输出兼容。由于长度取决于哈希算法,因此该工具不会打印它。用法(为了比较,pee
也添加了):
$ ./digest.py -sha256 -md5 digest.py
c217e5aa3c3f9cfaca0d40b1060f6233297a3a0d2728dd19f1de3b28454975f2 digest.py
b575edf6387888a68c93bf89291f611c digest.py
$ ./digest.py -sha256 -md5 <digest.py
c217e5aa3c3f9cfaca0d40b1060f6233297a3a0d2728dd19f1de3b28454975f2 -
b575edf6387888a68c93bf89291f611c -
$ pee sha256sum md5sum <digest.py
c217e5aa3c3f9cfaca0d40b1060f6233297a3a0d2728dd19f1de3b28454975f2 -
b575edf6387888a68c93bf89291f611c -