我需要为包含一些文件的文件夹创建哈希。我已经为每个文件完成了这项任务,但我正在寻找为文件夹中的所有文件创建一个散列的方式。任何想法如何做到这一点?为文件夹创建哈希
(当然我可以为每个文件哈希,并将其拼接到一些大的哈希,但它不是一种方法,我喜欢)
在此先感谢。
我需要为包含一些文件的文件夹创建哈希。我已经为每个文件完成了这项任务,但我正在寻找为文件夹中的所有文件创建一个散列的方式。任何想法如何做到这一点?为文件夹创建哈希
(当然我可以为每个文件哈希,并将其拼接到一些大的哈希,但它不是一种方法,我喜欢)
在此先感谢。
将文件名和文件内容连接在一个大字符串中并对其进行散列,或者对块进行散列以获得性能。
当然,你需要考虑几件事情考虑:
如果你已经有了所有文件的散列,只需按字母顺序对散列进行排序,连接它们并再次散列它们以创建一个超级散列。
创建文件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