我需要爲包含一些文件的文件夾創建哈希。我已經爲每個文件完成了這項任務,但我正在尋找爲文件夾中的所有文件創建一個散列的方式。任何想法如何做到這一點?爲文件夾創建哈希
(當然我可以爲每個文件哈希,並將其拼接到一些大的哈希,但它不是一種方法,我喜歡)
在此先感謝。
我需要爲包含一些文件的文件夾創建哈希。我已經爲每個文件完成了這項任務,但我正在尋找爲文件夾中的所有文件創建一個散列的方式。任何想法如何做到這一點?爲文件夾創建哈希
(當然我可以爲每個文件哈希,並將其拼接到一些大的哈希,但它不是一種方法,我喜歡)
在此先感謝。
將文件名和文件內容連接在一個大字符串中並對其進行散列,或者對塊進行散列以獲得性能。
當然,你需要考慮幾件事情考慮:
如果你已經有了所有文件的散列,只需按字母順序對散列進行排序,連接它們並再次散列它們以創建一個超級散列。
創建文件tarball,散列tarball。
> tar cf hashes *.abc
> md5sum hashes
或散列單個文件和管道輸出到哈希命令。
> md5sum *.abc | md5sum
編輯:這兩種方法上面沒有文件進行排序,以便可以返回不同的哈希每次調用,這取決於外殼是如何擴展星號。
這散列所有文件(相對)路徑和內容,並正確處理文件排序。
它很快 - 就像一個4MB目錄30毫秒。
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Linq;
...
public static string CreateMd5ForFolder(string path)
{
// assuming you want to include nested folders
var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
.OrderBy(p => p).ToList();
MD5 md5 = MD5.Create();
for(int i = 0; i < files.Count; i++)
{
string file = files[i];
// hash path
string relativePath = file.Substring(path.Length + 1);
byte[] pathBytes = Encoding.UTF8.GetBytes(relativePath.ToLower());
md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
// hash contents
byte[] contentBytes = File.ReadAllBytes(file);
if (i == files.Count - 1)
md5.TransformFinalBlock(contentBytes, 0, contentBytes.Length);
else
md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0);
}
return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower();
}
非常好的確 – 2013-05-17 15:13:46
如果您使用本地安全策略將其部署到服務器並執行FIPS合規,請注意FIPS合規性 – SkeetJon 2015-06-08 12:21:52
@SkeetJon對於任何加密算法,該技術都是相同的,因此您可以用SHA代替FIPS機器。 – 2015-12-30 23:25:24
Dunc的答案效果很好;但是,它不處理空目錄。下面的代碼爲空目錄返回MD5'd41d8cd98f00b204e9800998ecf8427e'(0長度字符流的MD5)。
public static string CreateDirectoryMd5(string srcPath)
{
var filePaths = Directory.GetFiles(srcPath, "*", SearchOption.AllDirectories).OrderBy(p => p).ToArray();
using (var md5 = MD5.Create())
{
foreach (var filePath in filePaths)
{
// hash path
byte[] pathBytes = Encoding.UTF8.GetBytes(filePath);
md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
// hash contents
byte[] contentBytes = File.ReadAllBytes(filePath);
md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0);
}
//Handles empty filePaths case
md5.TransformFinalBlock(new byte[0], 0, 0);
return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower();
}
}
如果您使用此版本,則需要將'filePath'截斷爲相對路徑以創建'pathBytes'。 – 2017-12-28 14:29:28
感謝您的回覆。字符串可能非常大,所以我需要將它分成大塊,只是想如何正確地做到這一點。 – 2010-09-02 09:51:41
我記得C#hashers有一個函數來爲它們提供塊,最後你可以要求獲得最終的哈希,不知道這些函數/類是什麼。有了它們,您可以按照自己喜歡的方式在內存中對輸入進行排序,然後循環文件並將塊加載到幾百KB中,並將其送入散列器,這樣您不需要太多內存,但仍然需要一些時間進行散列,這是你無法擺脫的。 – aularon 2010-09-02 10:11:50