
我需要一個腳本來讀取輸入檔併計算每個 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
...
但是1)這不是我需要的佈局,2)我特別需要MD4,3)另一個問題是即使沒有更多數據可供讀取,循環也不會停止,儘管有條件$offset -lt $length
(我一定做錯了) ) 。
我需要的是常規 32 位元組 MD4 字串:
908CB75033311ADCB0FBCD0DCD869050 0
A1211C1B77C0EFFA98DB8F719AB30A93 9728000
D9719A4CB32F2D350CB39A0CB790424B 19456000
...
然後今天我發現這個MD4腳本。我嘗試透過改編上面的腳本來使用它,但是失敗的米斯巴利。另外,如果我在自己的腳本中複製腳本的全部內容(以 開頭),則該函數無法識別,function Get-MD4...
只有透過「點源」(我在花費大約2 小時的時間發現的一個概念)調用腳本時,該函數才有效。可能是由於格式問題嗎? (如果我在 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 版本編寫的,效率非常低。它也無法正確處理 Unicode,因此使用-String
可能會傳回損壞的輸出。無論如何,您可以透過將上面更新的程式碼儲存為 *.ps1 檔案(例如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.2 MB 的小檔案就需要 4 分鐘,這是~29.5 KB/秒! !請放心,當您下載視訊檔案時,您甚至無法足夠快地對其進行哈希處理。您確實應該找到一個這樣的第三方庫/工具,並使用上面的循環向它們提供數據
另請注意,如果您經常使用某個功能,那麼您應該將其添加到設定檔中,如下所示
Add-Content -Path $profile -Value ". .\md4.ps1"
現在您可以刪除. .\md4.ps1
腳本中的 ,因為每次執行 PowerShell 時都會載入該函數