여러 다이제스트를 동시에 계산합니까 (md5, sha256)?


24

디스크 I / O 및 사용 가능한 RAM이 병목 현상 (CPU 시간에 제한이 없음)이라고 가정하면 한 번에 여러 메시지 요약을 계산할 수있는 도구가 있습니까?

특히 대용량 파일 (기가 바이트 단위)의 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

2
@Marco이 접근 방식의 문제점은 한 명령이 다른 명령보다 빠르기 때문에 나중에 동일한 데이터로 디스크 캐시가 비워지고 다시 채워질 수 있다는 것입니다.
Lekensteyn

1
당신이 디스크 캐시에 대해 걱정하는 경우, 당신은 단지 한 번 파일을 읽을 수 있습니다 : for i in file1 file2 …; do tee < "$i" >(sha256sum) | md5sum ; done그것은 표준 입력으로 전송되기 때문에 그런 다음, 파일 이름을 표시하는 코드를 추가해야 md5sum하고 sha256sum.
Marco

답변:


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

1
pee가장 좋은 인터페이스를 가지고 있으며 다른 스레드 와의 시간 비교는 이 게시물 에서 찾을 수 있으며 멀티 스레드 Python 도구를 보여줍니다.
Lekensteyn

불행히도, 데비안 시스템 moreutils과 충돌 GNU parallel합니다… 그러나 그러한 도구가 있다는 것을 아는 것이 좋습니다.
liori

@ Lekensteyn : 패키지 수준에서 충돌이 발생합니다 (즉, aptitude두 패키지를 동시에 가질 수는 없습니다).
liori

@liori 데비안이 그렇게 구현 한 것이 너무 나쁘다. 이것에 버그를 제출하는 것이 좋다. 아치 리눅스에는 moreutils-parallel충돌을 피하기 위한 이름이 있습니다.
Lekensteyn

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

이것은 checksummers가 표준 입력으로 전달되기 때문에 파일 이름을 알지 못하는 단점이 있습니다. 허용되지 않으면 파일 이름을 수동으로 내 보내야합니다. 완전한 예 :

for file in *.mkv; do
  echo "$file"
  tee < "$file" >(sha256sum) >(sha384sum) | md5sum
  echo
done > hashfilelist

1
와 출력이 호환하려면 *sum: 도구의 가족이 나오지 표현 대신에 사용될 수있다 sed "s;-\$;${file//;/\\;};(후행 대체 -파일 이름으로,하지만 파일 이름이 올바르게 이스케이프됩니다 있는지 확인).
Lekensteyn

AFAICS는에서만 작동합니다 zsh. ksh93 및 bash에서 sha256sum의 출력은 md5sum으로갑니다. 당신은 원할 것입니다 : { tee < "$file" >(sha256sum >&3) | md5sum; } 3>&1. 반대 문제는 unix.stackexchange.com/q/153896/22565 를 참조하십시오 .
Stéphane Chazelas

6

openssl 유틸리티가 여러 다이제스트 명령을 허용하지 않는 것이 유감입니다. 여러 파일에서 동일한 명령을 수행하는 것이 더 일반적인 사용 패턴이라고 생각합니다. FWIW, 내 시스템 (Mepis 11)의 openssl 유틸리티 버전에는 다른 sha 변형이 아닌 sha 및 sha1에 대한 명령 만 있습니다. 그러나 md5sum뿐만 아니라 sha256sum이라는 프로그램이 있습니다.

다음은 원하는 것을 수행하는 간단한 Python 프로그램 인 dual_hash.py입니다. 64k의 블록 크기가 내 컴퓨터 (2G RAM을 갖춘 Intel Pentium 4 2.00GHz), YMMV에 최적 인 것으로 보입니다. 작은 파일의 경우 속도는 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결합 속도가 비슷합니다 (이 Python 스크립트의 경우 4.7s + 14.2s vs 18.7s, 캐시 된 파일, 콜드 런의 경우 33.6s). 64KiB 대 1MiB는 상황을 변경하지 않았습니다. 코드가 주석 처리 된 상태에서 5.1은 md5 (n = 3), 14.6은 sha1 (n = 3)에 사용되었습니다. 8GB RAM이있는 i5-460M에서 테스트되었습니다. 더 많은 스레드를 사용하면 더 향상 될 수 있다고 생각합니다.
Lekensteyn

C 또는 C ++는 OpenSSL 모듈에서 많은 양의 런타임이 사용되는 것처럼 중요하지 않을 것입니다 (hashlib에서 사용). 더 많은 스레드가 속도를 향상시킵니다 . 멀티 스레드 Python 스크립트에 대한게시물을 참조하십시오 .
Lekensteyn

@PM 2Ring-참고 사항입니다. digests () 함수의 print 문 다음에 최소한 sha를 지워야합니다. md5를 지워야하는지 여부를 말할 수 없습니다. 난 그냥 "델 샤"를 사용합니다. 그렇지 않으면 첫 번째 파일 이후의 모든 파일에 잘못된 해시가 있습니다. 그것을 증명하기 위해, tmp 디렉토리를 만들고 파일을 복사하십시오. 이제 해당 파일의 사본을 2 개 만들고 스크립트를 실행하십시오. 3 가지 해시를 얻을 수 있습니다. 원하는 것이 아닙니다. 편집 : 함수가 한 번에 하나의 파일을 읽는 것이 아니라 파일 세트를 읽는다고 생각했습니다 ...이 사용을 무시하십시오. ;)
Terry Wendt

1
@TerryWendt 당신은 잠시 동안 거기에 걱정했다. :) 예, digests각 호출에서 단일 파일 만 처리합니다. 따라서 루프에서 호출하더라도 각 호출마다 새로운 md5 및 sha 컨텍스트가 작성됩니다. FWIW, 재개 가능한 SHA-256 해시를 즐길 수 있습니다 .
PM 2Ring

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

즉 많은으로 시작됩니다 md5sum그리고 sha256sum당신이 파일을 가지고있는 경우 그들은 모두 해당 파일 이름에 자신의 출력을 저장 병렬로 실행됩니다. 그러나 파일이 많은 경우주의해야합니다.


1
Marco에 대한 의견을 참조하십시오. 제 명령은 병렬이지만 동일한 데이터에 대해 느린 디스크에 두 번 액세스됩니다.
Lekensteyn

그러나 디스크 캐시가 있으면 걱정할 필요가 없습니까?
Twinkles

2
@Twinkles 위의 Lekensteyn을 인용하자면, "이 접근 방식의 문제점은 하나의 명령이 다른 명령보다 빠르기 때문에 나중에 동일한 데이터로 디스크 캐시가 비워지고 다시 채워지는 것입니다."
Matt Nordhoff

2
@MattNordhoff 또 다른 지능형 I / O 스케줄러가 주목하고 최적화해야합니다. "I / O 스케줄러가이 시나리오를 고려하기가 얼마나 어려울 수 있습니까?" 그러나 충분히 다른 시나리오에서는 I / O 스케줄러가 고려해야하므로 갑자기 어려운 문제가됩니다. 따라서 캐싱이 문제를 처리한다고 가정해서는 안됩니다.
kasperd

1
IO가 관련 도구보다 훨씬 느리다고 가정하면 IO로 인해 두 도구 모두 동일한 속도로 느려 져야합니다. 따라서 한 도구가 다른 도구보다 더 적은 수의 데이터 블록을 가져 오면 다른 도구는 디스크 캐시의 데이터를 사용하여 계산을 빠르게 따라 잡을 수 있습니다. 그것은 이론입니다, 나는 그것을 증명하는 몇 가지 실험 결과를보고 싶습니다 ...
liori

3

다중 스레드 파이썬 스크립트가 실행 시간을 줄일 수 있는지 호기심 중,이 만들어 digest.py사용하는 스크립트 threading.Thread, threading.Queue그리고 hashlib여러 파일의 해시를 계산합니다.

멀티 스레드 파이썬 구현은 실제로 peecoreutils를 사용 하는 것보다 약간 빠릅니다 . 반면에 Java는 meh입니다. 이 커밋 메시지 에서 결과를 사용할 수 있습니다 .

비교를 위해 2.3GiB 파일의 경우 ( n = 10의 경우 최소 / 평균 / 최대 / sd 초) :

  • 오줌 sha256sum md5sum <파일 : 16.5 / 16.9 /17.4/.305
  • python3 digest.py -sha256 -md5 <파일 : 13.7 / 15.0 /18.7/1.77
  • python2 digest.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. 그러나 차이를 좁혔습니다.
Matt Nordhoff

1

Jacksum은 파일의 타임 스탬프뿐만 아니라 체크섬, CRC 및 해시 (메시지 요약)를 계산하고 확인하기위한 무료 플랫폼 독립적 유틸리티입니다. ( 잭섬 매뉴얼 페이지 에서 발췌 )

그것은 큰 파일 인식이며, 최대 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

우분투에서 명령 apt-get install jacksum을 실행 하여 가져옵니다.

또는 소스 코드는


이것이 올바른 체크섬을 출력하지만이 Java 프로그램은 coreutils보다 두 배 느리게 계산합니다. 이 커밋 메시지를 참조하십시오 .
Lekensteyn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.