3

I have the following function that hashes a string:

public static uint hashString(string myString)
{
     uint hash = 0;

     foreach (char c in myString)
     {
         hash *= 0x1F;
         hash += c;
     }

     return hash;
}

So if I want to hash hello it will produce 99162322.

Is it possible to write a reverse function that takes in a number and spits out the string (given that the string result is unknown)?

2
  • 3
    No. hash != encryption - it is more like a checksum Commented Mar 24, 2020 at 9:14
  • 1
    The most you can do with a hash is to get some input that when hashed will produce the same hash as what you originally had. There is no guarantee that you will get back the original string. Depending on the complexity of the hash algorithm the job of obtaining input that produces a given hash may or may not be difficult or a long-running process. Commented Mar 24, 2020 at 9:57

2 Answers 2

3

Since you don't use cryptographic hash, your implementation is easy to reverse (i.e. return some string which has the given hash value)

Code:

public static uint hashString(string myString) {
  //DONE: validate public methods' parameters
  if (null == myString)
    return 0;

  uint hash = 0;

  //DONE: hash function must never throw exceptions
  unchecked {
    foreach (char c in myString) {
      hash *= 0x1F;
      hash += c;
    }
  }

  return hash;
}

private static string HashReverse(uint value) {
  StringBuilder sb = new StringBuilder();

  for (; value > 0; value /= 31) 
    sb.Append((char)(value % 31));

  return string.Concat(sb.ToString().Reverse());
}

Demo: (given a hash we produce a string and compute hash from it to check)

uint[] tests = new uint[] {
  99162322,
  123,
  456
};

// Since the string can contain control characters, let's provide its Dump
string Dump(string value) => string.Join(" ", value.Select(c =>((int) c).ToString("x4")));

string report = string.Join(Environment.NewLine, tests
  .Select(test => new { 
    test,
    reversed = HashReverse(test)
  })
  .Select(item => $"{item.test,9} :: {Dump(item.reversed),-30} :: {hashString(item.reversed),9}"));

Console.WriteLine(report);

Outcome:

 99162322 :: 0003 000e 000b 0012 0012 0012  ::  99162322
      123 :: 0003 001e                      ::       123
      456 :: 000e 0016                      ::       456

Please, note, that many a string produce the same hash value (say, "hello" and mine "\u0003\u000e\u000b\u0012\u0012\u0012")

Sign up to request clarification or add additional context in comments.

Comments

2

No.

One of the fundamental points of hashing is that it's irreversible.

There are many string that will produce the has 99162322, so while it might be possible to find all of them (given a maximum string length), but there would be no way to determine which one was 'correct'.

3 Comments

I'm sorry, but since hashString is not a cryptohash it's easy to reverse
Only if there's a limit on the string length.
It depends on your definition of "reverse". OP wants the original string, getting a string is feasible, getting the original one is not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.