
입력 파일을 읽고 파일 끝까지 각 9728000바이트 청크에 대해 MD4 체크섬을 계산하는 스크립트가 필요합니다. 이전에는 먼저 모든 9728000바이트 청크를 개별 파일로 추출한 다음 다음이라는 명령줄 도구를 사용하여 각각에 대한 MD4 체크섬을 계산하여 이 작업을 수행했습니다.fsum, 그러나 이는 특히 대용량 파일의 경우 편리하지 않습니다.
내가 수집한 정보에 따르면 PowerShell은 기본적으로 MD5 체크섬을 계산할 수 있지만 MD4는 계산할 수 없습니다.
얻은 코드를 적용하여 다음 스크립트로 테스트를 수행했습니다.거기, 나는 아직도 완전히 이해하지 못합니다.
$input = Read-Host "File name"
$file = Get-Item -LiteralPath $input
$offset = 0
$length = $file.length
$name = $file.name
$hasher = [System.Security.Cryptography.HashAlgorithm]::Create('MD5')
for ($offset -lt $length) {
$buffer = [Byte[]]::new(9728000)
$stream = [System.IO.FileStream]::new($file.FullName, 'Open', 'Read')
$stream.Position = $offset
$readSize = $stream.Read($buffer, 0, 9728000)
$md5 = $hasher.ComputeHash($buffer, 0, $readSize)
$stream.Dispose()
echo "$md5 $offset" >> "$name MD5.txt"
$offset = $offset + 9728000
}
결과는 다음과 같습니다.
78 224 90 67 158 49 86 127 118 179 251 89 133 103 144 25 0
190 40 170 149 51 93 153 191 212 194 162 165 38 124 57 96 9728000
160 20 197 150 189 246 209 156 212 84 154 21 200 7 148 228 19456000
...
$offset -lt $length
하지만 1) 이것은 나에게 필요한 레이아웃이 아닙니다. 2) 특히 MD4가 필요합니다. 3) 또 다른 문제는 조건 에도 불구하고 더 이상 읽을 데이터가 없어도 루프가 중지되지 않는다는 것입니다. ).
내가 필요한 것은 일반 32바이트 MD4 문자열입니다.
908CB75033311ADCB0FBCD0DCD869050 0
A1211C1B77C0EFFA98DB8F719AB30A93 9728000
D9719A4CB32F2D350CB39A0CB790424B 19456000
...
그러다 오늘 발견한이 MD4 스크립트. 위의 스크립트를 응용해서 사용하려고 했으나,비참하게 실패했다. 그리고 스크립트의 전체 내용( 으로 시작 function Get-MD4...
)을 내 스크립트에 복사하면 기능이 인식되지 않고, "dot-sourcing"(2시간 정도 투자하면서 발견한 개념)을 통해 스크립트를 호출해야만 작동합니다. 다른 방법으로는 거의 도움이 되지 않은 PowerShell에서 400페이지가 넘는 PDF 책을 선별하는 데 몇 시간이 걸렸습니다. 포맷 문제 때문일 수 있습니까? (Notepad2에서 md4.ps1 스크립트를 열면 줄 끝이 "LF"라고 표시되는 반면 내 스크립트에는 "CR+LF" 줄 끝이 있습니다. 이것이 주요 문제는 아니지만 정말 짜증납니다. 오늘 오후에 무슨 일이 있었는지 알고 싶습니다.)
그만큼읽어보기 파일해당 스크립트에는 다음이 포함됩니다.
This is a MD4 algorithm function wrote in powershell. PS> Get-MD4 -String 'abc' -UpperCase A448017AAF21D8525FC10AE87AA6729D PS> $b = @('abc'.ToCharArray() | %{[int]$_}) PS> Get-MD4 -bArray $b a448017aaf21d8525fc10ae87aa6729d
나는 로 시작하는 줄을 이해하지 못하며 $b =
PDF 책이나 웹 검색에서 관련 내용을 어떻게 찾을 수 있는지 전혀 모릅니다. 그래서 다시 한 번 헤매게 됩니다.
Get-MD4
한 번에 하나의 크기로 정의된 청크씩 파일을 읽고, 이를 함수에 대한 입력으로 공급한 다음, 파일이 끝날 때까지 $offset 값을 증가시키는 등 의 가장 효율적인 방법은 무엇입니까 ? -String
또는 을 사용해야 합니까 -bArray
?
중요한 경우 목표는 eDonkey 네트워크에서 공유되지만 ED2K 체크섬이 일치하지 않는 파일을 확인하는 것입니다. 예를 들어, 4GB MKV 파일이 있는데 eMule로 검색하면 크기는 똑같지만 ED2K 체크섬이 다른 MKV 파일을 찾았습니다. 그래서 어떤 특정 부분이 다른지 알고 싶습니다(ED2K 체크섬은 MD4 체크섬입니다). 메타데이터 파일에서 찾을 수 있는 각 9728000바이트 청크에 대한 MD4 문자열 목록) 그런 다음 해당 파일의 손상된 버전이 내가 가지고 있는 버전인지 현재 공유된 버전인지 확인하기 위해 해당 부분을 구체적으로 다운로드할 수 있습니다. . 그것이 분명하기를 바랍니다. 그렇지 않으면 신경 쓰지 말고 "부분 MD4 체크섬 계산"이라는 주제에 집중하겠습니다.
답변1
위의 코드는 루프 반복마다 새로운 대용량 버퍼와 새 스트림이 생성되기 때문에 매우 비효율적입니다. 그만큼개울이미 오프셋과 모든 것을 처리하므로 루프 본문은 실제로 매우 간단합니다.
Param (
[parameter(Mandatory)][string]$InputFile,
[int]$ChunkSize = 9728000
)
. .\md4.ps1
# Or copy the md4.ps1 content here, or add to the $PROFILE
class Md4Info {
[string]$Checksum
[int]$Offset
}
$stream = [IO.FileStream]::new($InputFile, [IO.FileMode]::Open, [IO.FileAccess]::Read)
$buffer = [Byte[]]::new($ChunkSize)
while (($readSize = $stream.Read($buffer, 0, $ChunkSize)) -gt 0) {
[Md4Info]@{
Checksum = Get-MD4 -bArray $buffer[0..$readSize]
Offset = $stream.Position
}
}
$stream.Dispose()
이는 귀하의 코드에 비해 크게 개선되었지만 분명히 그렇지 않습니다.가장 효율적인 방법왜냐하면md4.ps1위의 스크립트는 매우 오래된 PowerShell 버전용으로 작성되었으며 매우 비효율적입니다. 또한 유니코드를 잘못 처리하므로 사용하면 -String
손상된 출력이 반환될 수 있습니다. 어쨌든 위의 업데이트된 코드를 Get-ChunkMd4.ps1
. 샘플 출력:
PS D:\test> .\Get-ChunkMd4.ps1 D:\test\file.txt
Checksum Offset
-------- ------
11cf3ecf1a3a9d1b270c9e313901441d 0
PS D:\test> .\Get-ChunkMd4.ps1 D:\test\file.mp4 -ChunkSize 1MB
Checksum Offset
-------- ------
8932ec620ef5df53f519e6271931bc0d 0
92a8f97be075655bfd1e8670368ff2a3 1048576
c6ec8e0d67b42cc3a9a1bc9d5c9fa8f0 2097152
1339bac99b94397b5848d1d86b0cc49e 3145728
fd643f329daeb73e07e24194fd1b0a31 4194304
즉, 당신은 결코 가질 수 없습니다최대하드웨어 가속 및/또는 SIMD를 사용하여 매우 효율적인 병렬 코드를 작성하고 네이티브 코드로 컴파일하지 않는 한 효율적인 방법입니다. 기본 MD4 라이브러리는 위의 스크립트보다 수천 배 또는 수백만 배 빠르게 실행될 수 있습니다. 실제로 AVX-512를 사용하는 좋은 해싱 라이브러리는3~30GB/초이상이지만 md4.ps1
너무 나빠서 내 컴퓨터(Ryzen 5 4600H)에서 작은 8.2MB 파일을 해시하는 데 4분이 필요합니다.~29.5KB/s!!!비디오 파일을 다운로드할 때 비디오 파일을 빠르게 해시할 수도 없다는 점을 명심하세요. 실제로 그러한 타사 라이브러리/도구 중 하나를 찾아서 위 의 루프를 사용하여 데이터를 제공해야 합니다.
또한 함수를 많이 사용하는 경우 다음과 같이 프로필에 추가해야 합니다.
Add-Content -Path $profile -Value ". .\md4.ps1"
. .\md4.ps1
이제 PowerShell이 실행될 때마다 함수가 로드되므로 스크립트에서 제거하면 됩니다.