如何将MD5哈希值转换为字符串并用作文件名

5

我正在对图像文件进行MD5哈希处理,并且希望使用哈希值作为文件名。

如何将哈希值转换为有效的文件名字符串?

编辑:toString()仅返回"System.Byte[]"


你想要将哈希值转换为十六进制而不是二进制...不过我不熟悉C#,所以不知道怎么做。 - Greg
提醒一下,由于MD5正在逐步淘汰,您可能希望使用SHAx。 - Spencer Ruport
1
停止使用MD5的唯一原因是最近对其进行的密码攻击(与SHA-0/1相同)。如果您不是出于密码学原因而使用它,那么没有必要急于更换。 - Jonathan Rupp
2
对于简单的哈希操作而言,如果不考虑安全性问题,MD5仍然足够使用。 - Joey
7个回答

21

这个怎么样:

string filename = BitConverter.ToString(yourMD5ByteArray);

如果你喜欢没有连字符的更短的文件名,那么你可以直接使用:

string filename =
    BitConverter.ToString(yourMD5ByteArray).Replace("-", string.Empty);

请注意,此处使用十六进制编码。 - meandmycode

11

System.Convert.ToBase64String

正如一位评论者指出的——普通的base64编码可能会包含'/'字符,这显然会对文件名造成问题。但是,还有其他可用的字符,例如下划线-只需用下划线替换所有的'/'即可。

string filename = Convert.ToBase64String(md5HashBytes).Replace("/","_");

我在使用那个时遇到了错误,但如果尝试使用 test.jpg,则可以正常工作? - Malcolm
看起来字符串中有“/”,错误是找不到路径的一部分? - Malcolm
要么删除所有“/”字符,要么使用我在答案中建议的方法。 - sharptooth
你需要将所有的 / 和 + 字符转换为 _ 和 - 字符。 - C. K. Young
“+”字符不被禁止,无需删除。 - sharptooth
如果不是因为使用base64编码时会出现像+ - /这样的奇怪字符,那么转换为base64可能是个好主意。但是这种编码经常会导致文件系统和解析器无法识别。 - Johan Buret

3

试试这个:

string Hash = Convert.ToBase64String(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("sample")));
//input "sample" returns = Xo/5v1W6NQgZnSLphBKb5g==

或者

string Hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("sample")));
//input "sample" returns = 5E-8F-F9-BF-55-BA-35-08-19-9D-22-E9-84-12-9B-E6

请注意,Base64生成区分大小写的名称,因为它使用大写和小写字母。Windows文件系统不区分大小写,所以请小心处理。 - nzeemin

3

这可能是文件名最安全的方式。您总是得到一个十六进制字符串,不需要担心 / 或 + 等字符。

        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(inputString));
        StringBuilder sBuilder = new StringBuilder();
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }
        string hashed = sBuilder.ToString();

3

试试这个:

Guid guid = new Guid(md5HashBytes);
string hashString = guid.ToString("N"); 
// format: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

string hashString = guid.ToString("D"); 
// format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

string hashString = guid.ToString("B"); 
// format: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}

string hashString = guid.ToString("P"); 
// format: (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

Guid.ToString() 方法使用的不是原始字节数组的顺序! - springy76

1

尝试使用MD5的Base32哈希。它会生成文件名安全、不区分大小写的字符串。

    string Base32Hash(string input)
    {
        byte[] buf = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(input));
        return String.Join("", buf.Select(b => "abcdefghijklmonpqrstuvwxyz234567"[b & 0x1F]));
    }

请注意,MD5不符合FIPS标准,在启用FIPS的计算机上会抛出异常。请改用SHA1。 - Yury Chaikou

1

从技术上讲,在Windows中使用Base64是不好的,因为文件名不区分大小写(至少在资源管理器视图中是这样的)。但在Base64中,“a”与“A”是不同的,这意味着可能不太可能,但您最终会得到更高的冲突率。

更好的选择是十六进制,例如使用BitConverter类,或者如果可以的话,请使用base32编码(在从base64和base32中删除填充的情况下,在128位的情况下,将为您提供类似长度的文件名)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接