同时计算多个摘要(md5,sha256)?


25

在磁盘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()

您可以只在后台启动一个实例,然后两个哈希并行运行:for i in file1 file2 …; do sha256 "$i"& md5sum "$i"; done
Marco Marco

2
@Marco这种方法的问题在于,一个命令可能比另一个命令快,从而导致磁盘缓存被清空并稍后用相同的数据重新填充。
Lekensteyn 2014年

1
如果您担心磁盘高速缓存,则可以只读取一次文件:for i in file1 file2 …; do tee < "$i" >(sha256sum) | md5sum ; done然后,您必须添加其他代码来标记文件名,因为它是作为标准输入发送给md5sumand的sha256sum
Marco Marco

Answers:


28

从中签出pee(“ tee standard input to pipes”)moreutils。这基本上等效于Marco的tee命令,但键入起来稍微简单一些。

$ echo foo | pee md5sum sha256sum
d3b07384d113edec49eaa6238ad5ff00  -
b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c  -
$ pee md5sum sha256sum <foo.iso
f109ffd6612e36e0fc1597eda65e9cf0  -
469a38cb785f8d47a0f85f968feff0be1d6f9398e353496ff7aa9055725bc63e  -

好命令!我已经安装了这个非常有用的软件包,却不知道这个有趣的实用程序。
Lekensteyn 2014年

1
pee有最好的界面,与其他工具时间比较可以发现这个帖子也说明了一个多线程的Python的工具。
Lekensteyn 2014年

不幸的是,在我的Debian系统上moreutils发生了冲突GNU parallel……不过,很高兴知道有这样的工具。
liori 2014年

@Lekensteyn:我在软件包级别上遇到了冲突(即aptitude,不允许我同时拥有两个软件包)。
liori 2014年

@liori太糟糕了,Debian以这种方式实现了它,可能值得为此提交一个错误。在Arch Linux上,有一个moreutils-parallel名称可以避免冲突。
Lekensteyn 2014年

10

您可以使用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

1
为了使输出与*sum工具系列兼容,可以使用以下sed表达式代替:(sed "s;-\$;${file//;/\\;};-文件名替换结尾,但要确保文件名正确转义)。
Lekensteyn 2014年

AFAICS,它仅适用于zsh。在ksh93和bash中,sha256sum的输出进入md5sum。您需要:{ tee < "$file" >(sha256sum >&3) | md5sum; } 3>&1。有关相反的问题,请参见unix.stackexchange.com/q/153896/22565
斯特凡Chazelas

6

遗憾的是,openssl实用程序不接受多个摘要命令。我猜想在多个文件上执行相同的命令是更常见的使用模式。FWIW,我系统上的openssl实用程序版本(Mepis 11)仅具有用于sha和sha1的命令,而没有其他任何sha变体。但是我确实有一个名为sha256sum和md5sum的程序。

这是一个简单的Python程序dual_hash.py,它可以满足您的需求。对于我的机器(Intel Pentium 4 2.00GHz和2G RAM),YMMV似乎是64k的最佳块大小。对于小文件,其速度与连续运行md5sum和sha256sum大致相同。但是对于较大的文件,速度明显更快。例如,在1967063040字节文件(装有mp3文件的SD卡的磁盘映像)上,md5sum + sha256sum大约需要1m44.9s,dual_hash.py大约需要1m0.312s。

dual_hash.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速度。


对于2.3G的文件,这个版本是有一个相当的速度相比,md5sumsha256sum结合(4.7s + 14.2s VS 18.7s这个Python脚本,文件缓存;对于冷运行33.6s)。64KiB与1MiB并没有改变这种情况。注释了代码,md5(n = 3)花费了5.1s,sha1(n = 3)花费了14.6s。在具有8GB RAM的i5-460M上进行了测试。我猜可以通过使用更多线程来进一步改善。
Lekensteyn 2014年

无论如何,C或C ++无关紧要,因为无论如何,运行时间都花费在OpenSSL模块中(由hashlib使用)。更多线程确实可以提高速度,请参阅有关多线程Python脚本的这篇文章
Lekensteyn

@PM 2Ring-请注意。在digests()函数中的print语句之后,您至少需要清除sha。我不能说您是否应该清除md5。我只用“ del sha”。如果不这样做,则第一个文件之后的每个文件都将具有错误的哈希值。为了证明这一点,请制作一个tmp目录并将文件复制到其中。现在制作该文件的2个副本,然后运行脚本。您会得到3种不同的哈希值,这不是您想要的。编辑:我认为该功能正在读取一组文件,而不仅仅是一次读取单个文件...无需为此使用。;)
Terry Wendt

1
@TerryWendt你让我担心了一秒钟。:)是的,digests每次调用仅处理一个文件。因此,即使您确实在循环中调用它,它也会在每次调用时创建新的md5&sha上下文。FWIW,您可能会喜欢我的可恢复SHA-256哈希
PM 2Ring '18

5

您总是可以使用类似GNU parallel的东西:

echo "/path/to/file" | parallel 'md5sum {} & sha256sum {}'

或者,只需在后台运行两者之一:

md5sum /path/to/file & sha256sum /path/to/file

或者,将输出保存到其他文件,并在后台运行多个作业:

for file in *; do
    md5sum "$file" > "$file".md5 &
    sha256sum "$file" > "$file".sha &
done

这将启动md5sumsha256sum您拥有文件一样多的实例,它们都将并行运行,并将其输出保存到相应的文件名。但是请小心,如果您有许多文件,这可能会很沉重。


1
请参阅对Marco的评论,我担心的是,尽管该命令将是并行的,但对于相同的数据,慢速磁盘将被访问两次。
Lekensteyn 2014年

但是,磁盘缓存的存在是否会使您的后顾之忧变得不必要?
2013年

2
@Twinkles在上面引用Lekensteyn的话,“这种方法的问题在于,一个命令可能比另一个命令更快,从而导致磁盘缓存被清空并稍后用相同的数据重新填充。”
Matt Nordhoff 2014年

2
@MattNordhoff智能I / O调度程序还应该注意并进行优化。可能会想到:“ I / O调度程序考虑这种情况有多难?” 但是,在足够多的不同情况下,应该考虑I / O调度程序,这突然成为一个难题。因此,我同意不应以缓存来解决此问题。
kasperd 2014年

1
假设IO的速度明显慢于所涉及的任何工具,则由于IO,这两个工具的速度应减慢到相同的速度。因此,如果一个工具设法获得比另一工具更多的数据块,则另一个工具将使用磁盘缓存中的数据快速赶上计算速度。从理论上讲,我很想看到一些实验结果证明了这一点……
liori 2014年

3

出于对多线程Python脚本是否会减少运行时间的好奇,我创建了digest.py一个使用的脚本threading.Threadthreading.Queuehashlib计算多个文件的哈希值。

实际上,多线程Python实现比pee与coreutils结合使用要快一些。另一方面,Java是……嗯。结果可在以下提交消息中找到

为了进行比较,对于2.3 GiB的文件(对于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  -

我本来建议比较pee "openssl sha256" "openssl md5" < file,但说实话,我只是尝试了一下,它没有击败digest.py。不过,它缩小了差距。
Matt Nordhoff 2014年

1

Jacksum是一个免费且不受平台限制的实用程序,用于计算和验证校验和,CRC和哈希(消息摘要)以及文件的时间戳。(摘自jacksum手册页

它支持大文件,它可以处理最大8艾字节(= 8,000,000,000千兆字节)的文件大小,也分别假设您的操作系统和文件系统也支持大文件。 (摘自http://www.jonelo.de/java/jacksum/

用法示例:

jacksum -a md5+sha256 -F "#ALGONAME{i} (#FILENAME) = #CHECKSUM{i}" jacksum-testfile

样本输出:

md5 (jacksum-testfile) = d41d8cd98f00b204e9800998ecf8427e
sha256 (jacksum-testfile) = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

在ubuntu上,运行命令apt-get install jacksum来获取它。

或者,可以在以下位置获取源代码


尽管这确实输出了正确的校验和,但是此Java程序的计算速度是coreutils的两倍。请参阅此提交消息
Lekensteyn 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.