Sandeep Thomas
Sandeep Thomas

Reputation: 4759

Hash a small integer value to a big 16 digit unique number

I've a situation to create a 16 digit number from another integer. It should be like a credit card number. So what is our scenario is if that users ID is 1 or 2, that should be hashed to a 16 digit string (Numeric). So that 16 digit should be unique for 1 I tried to .NET builtin functions like generate hash etc.

That doesn't helped me for a perfect solution

Upvotes: 2

Views: 1198

Answers (2)

Hans Kesting
Hans Kesting

Reputation: 39329

Maybe you could use this:

string SixteenDigitHash(int value)
{
   var rnd = new Random(value);
   StringBuilder sb = new StringBuilder(16);
   sb.Append(rnd.Next(1,10)); // first digit 1..9
   for (int i=1; i<16; i++)
   {
     sb.Append(rnd.Next(0,10)); // other digits 0..9
   }

   return sb.ToString();
}

It uses Random to generate (pseudo) random numbers, but uses the value-to-hash as seed so it always generates the same sequence for a given value and different sequences for different values.

One problem: the sequence is not guaranteed to be the same for different versions of the framework. Maybe you should use your own implementation of that Random class so that you know that the sequence is stable.

Upvotes: 1

tinstaafl
tinstaafl

Reputation: 6948

Not sure how many users you expect, but this code produces 16 digit integers and using the numbers from 1 to 100 there were no repeats:

Imports System.Security.Cryptography

    Dim sha As New SHA1CryptoServiceProvider()
    Dim IntList As New List(Of ULong)
    For I = 1 To 100000
        'Need a byte array for the ComputeHash method
        Dim data() As Byte = BitConverter.GetBytes(I)
        If BitConverter.IsLittleEndian Then Array.Reverse(data)
        'Store the 160 bit hash in a byte array
        Dim result As Byte() = sha.ComputeHash(data)
        'Bitconverter's result can be too long, so by taking the first 16 digits _
         of the results that are too long, and padding the rest to the right with _
        0's we end up with unique 16 digit integers
        Dim HashInt As ULong = ULong.Parse(BitConverter.ToUInt64(result, 0).ToString.PadRight(16, "0"c).Substring(0, 16))
        'Using a list to hold the hash's is just to confirm that each one is unique. _
        for the your purposes I would suggest a dictionary(of integer, ulong)
        If Not IntList.Contains(HashInt) Then
            IntList.Add(HashInt)
        End If
    Next

UPDATE: modified the code to show that it will produce 100000 unique hash's. IntList.Count = 100000.

For results that end up being less than 16 digits, I padded the end with 0's. This is just convenient. By putting the BitConverter.ToUInt64 result into a string you can insert the 0's anywhere you like.

Upvotes: 1

Related Questions