5

I am taking the MD5 hash of an image file and I want to use the hash as a filename.

How do I convert the hash to a string that is valid filename?

EDIT: toString() just gives "System.Byte[]"

unwind
  • 391,730
  • 64
  • 469
  • 606
Malcolm
  • 12,524
  • 28
  • 89
  • 125
  • You want to get the hash as hex not binary... I don't do c# though so I don't know how – Greg Apr 17 '09 at 12:11
  • Just as a heads up, you might want to use SHAx since MD5 is being phased out. – Spencer Ruport Apr 17 '09 at 12:32
  • 1
    The only reason to discontinue using MD5 is because of the cryptographic attacks against it recently (same with SHA-0/1). If you're not using it for cryptographic reasons, there's no big hurry to change over. – Jonathan Rupp Apr 17 '09 at 12:45
  • 2
    For simple hashing without security considerations MD5 should still be enough. – Joey Apr 17 '09 at 12:45

7 Answers7

21

How about this:

string filename = BitConverter.ToString(yourMD5ByteArray);

If you prefer a shorter filename without hyphens then you can just use:

string filename =
    BitConverter.ToString(yourMD5ByteArray).Replace("-", string.Empty);
LukeH
  • 263,068
  • 57
  • 365
  • 409
11

System.Convert.ToBase64String

As a commenter pointed out -- normal base 64 encoding can contain a '/' character, which obivously will be a problem with filenames. However, there are other characters that are usable, such as an underscore - just replace all the '/' with an underscore.

string filename = Convert.ToBase64String(md5HashBytes).Replace("/","_");
Jonathan Rupp
  • 15,522
  • 5
  • 45
  • 61
3

Try this:

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

or

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
Alexander
  • 23,432
  • 11
  • 63
  • 73
D.Gjinovci
  • 31
  • 1
  • Note that Base64 produces case-sensitive names because it uses both capital and lower letters. Windows file systems are case-insensitive so be carefull with that. – nzeemin May 13 '15 at 11:02
3

This is probably the safest for file names. You always get a hex string and never worry about / or +, etc.

        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();
Erkan
  • 109
  • 1
  • 2
3

Try this:

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)
jrista
  • 32,447
  • 15
  • 90
  • 130
1

Try Base32 hash of MD5. It gives filename-safe case insensitive strings.

    string Base32Hash(string input)
    {
        byte[] buf = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(input));
        return String.Join("", buf.Select(b => "abcdefghijklmonpqrstuvwxyz234567"[b & 0x1F]));
    }
Yury Chaikou
  • 143
  • 1
  • 5
  • Please note that MD5 is not FIPS-compliant and will throw exception on machines with FIPS-enabled. Use SHA1 instead. – Yury Chaikou Aug 20 '12 at 19:45
1

Technically using Base64 is bad if this is Windows, filenames are case insensitive (at least in explorers view).. but in base64, 'a' is different to 'A', this means that perhaps unlikely but you end up with even higher rate of collision..

A better alternative is hexadecimal like the bitconverter class, or if you can- use base32 encoding (which after removing the padding from both base64 and base32, and in the case of 128bit, will give you similar length filenames).

meandmycode
  • 17,067
  • 9
  • 48
  • 42