0

What would be a simple way of computing an (insecure) hash string from a string seed, with the end result having a specific length and fairly low probability of collision?

For example in C#:

string seed = "PK_DELETE_THIS_TABLE";  
Console.WriteLine("Seed: {0}", seed);  
string hashedData = SimpleHash(seed, 30/2);  
Console.WriteLine("Hash: {0}", hashedData); 

Result:

Seed: PK_DELETE_THIS_TABLE
Hash: CC598675A3072C8B1768DED09BAAA5
aleksander_si
  • 1,021
  • 10
  • 28
  • 1
    Is there a particular reason you want to roll your own hashing algorithm? – mjwills Jul 29 '20 at 08:59
  • 1
    rule #1 about correctly doing your own implementations of hashing, encryption, datetime-handling (and maybe some more): `DON'T` - unless you are a total expert. use the tools that **already numerously exist** – Franz Gleichmann Jul 29 '20 at 09:31
  • The only reason is that I need a hash string of a specific length. Security is not that important and collision concerns are quite low for my use case; I need to convert a name to hash string of 30 characters. – aleksander_si Sep 14 '20 at 19:59

1 Answers1

2

We can compute an insecure hash with fairly low probability of collision with the following algorithm:

public string SimpleHash(string seed, int halfHashLength)  
{  
    if(seed == null) throw new ArgumentNullException(nameof(seed));
    if(halfHashLength <= 0) throw new ArgumentException("Value should be larger than 0.", nameof(halfHashLength));
    
    // Use different random algo for more deterministic hash:
    // https://stackoverflow.com/questions/17094189/crossplatform-random-number-generator
    Random rnd = new Random(seed.GetHashCode());
    byte[] tmp = new byte[halfHashLength];
    rnd.NextBytes(tmp);
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < tmp.Length; i++)
    {
        sb.Append(tmp[i].ToString("X2"));
    }
    return sb.ToString();
}

Note that the the above computed hash may not be portable across runtimes and possibly not even between runtime restarts (.NET Core will return a different seed.GetHashCode() each time the runtime is restarted). Use a more deterministic hashing algorithm if this is a problem.

aleksander_si
  • 1,021
  • 10
  • 28
  • 4
    Note `GetHashCode` is not part of the Specs and is dependent on its implementation with no guarantee they will be the same on other platforms and implementations ect ect ect , if that doesn't bother you (which it likely wont), then this is actually a pretty good answer – TheGeneral Jul 29 '20 at 08:58
  • 1
    Note that the byte array conversion could be simplified to `BitConverter.ToString(tmp).Replace("-","")` – Ackdari Jul 29 '20 at 09:10
  • @TheGeneral Updated the answer to account for your comment. – aleksander_si Jul 29 '20 at 11:09