4

I have a string that I need to hash in order to access an API. The API-creator has provided a codesnippet in Python, which hashes the code like this:

hashed_string = hashlib.sha1(string_to_hash).hexdigest()

When using this hashed string to access the API, everything is fine. I have tried to get the same hashed string result in C#, but without success. I have tried incredibly many ways but nothing has worked so far. I am aware about the hexdigest part aswell and I have kept that in mind when trying to mimic the behaviour.

Does anyone know how to get the same result in C#?

EDIT: This is one of the many ways I have tried to reproduce the same result in C#:

public string Hash(string input)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
        var sb = new StringBuilder(hash.Length * 2);

        foreach (byte b in hash)
        {
            sb.Append(b.ToString("X2"));
        }

        return sb.ToString().ToLower();
    }
}

This code is taken from: Hashing with SHA1 Algorithm in C#

Another way

public string ToHexString(string myString)
{
    HMACSHA1 hmSha1 = new HMACSHA1();
    Byte[] hashMe = new ASCIIEncoding().GetBytes(myString);
    Byte[] hmBytes = hmSha1.ComputeHash(hashMe);
    StringBuilder hex = new StringBuilder(hmBytes.Length * 2);
    foreach (byte b in hmBytes)
    {
        hex.AppendFormat("{0:x2}", b);
    }
    return hex.ToString();
}

This code is taken from: Python hmac and C# hmac

EDIT 2

Some input/output:

C# (using second method provided in above description)

input: callerId1495610997apiKey3*_&E#N@B1)O)-1Y

output: 1ecded2b66e152f0965adb96727d96b8f5db588a


Python

input: callerId1495610997apiKey3*_&E#N@B1)O)-1Y

output: bf11a12bbac84737a39152048e299fa54710d24e


C# (using first method provided in above description)

input: callerId1495611935​apiKey{[B{+%P)s;WD5&5x

output: 7e81e0d40ff83faf1173394930443654a2b39cb3


Python

input: callerId1495611935​apiKey{[B{+%P)s;WD5&5x

output: 512158bbdbc78b1f25f67e963fefdc8b6cbcd741

16
  • 4
    Please show a minimal reproducible example - my guess is that there's a bug in your C# code, but as we can't see any of your C# code, it's hard to tell. Commented May 24, 2017 at 7:17
  • Done! @JonSkeet Commented May 24, 2017 at 7:24
  • 1
    You didn't bother including the results of your first C# code, which is the same as your python results, just in upper case... Commented May 24, 2017 at 7:44
  • 2
    As noted in comments on Federico's answer, you've got a non-ascii character in the input for the bottom two examples. I suspect that's not meant to be there, is it? Commented May 24, 2017 at 8:23
  • 1
    Please take note that if you'd provided a minimal reproducible example from the start, you may well have found the problem before even hitting "Post". Worth remembering for next time... Commented May 24, 2017 at 9:23

1 Answer 1

7

C#:

public static string Hash(string input)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
        var sb = new StringBuilder(hash.Length * 2);

        foreach (byte b in hash)
        {
            sb.Append(b.ToString("x2")); // x2 is lowercase
        }

        return sb.ToString().ToLower();
    }
}

public static void Main()
{
    var x  ="callerId1495611935​apiKey{[B{+%P)s;WD5&5x";
    Console.WriteLine(Hash(x)); // prints 7e81e0d40ff83faf1173394930443654a2b39cb3
}

Python

import hashlib
s = u'callerId1495611935​apiKey{[B{+%P)s;WD5&5x'
enc = s.encode('utf-8') # encode in utf8
hash = hashlib.sha1(enc)
formatted = h.hexdigest()
print(formatted) # prints 7e81e0d40ff83faf1173394930443654a2b39cb3

Your main problem is that you are using different encodings for the same string in C# and Python. Use UTF8 in both languages and use the same casing. The output is the same.

Note that inside your input string (between callerId1495611935 and apiKey{[B{+%P)s;WD5&5x) there is an hidden \u200b character. That's why encoding your string in UTF-8 gives a different result than encoding it using ASCII. Does that character have to be inside your string?

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

6 Comments

I'm all for being explicit in general, but on my box at least it makes no difference (which is what I'd expect, given that the input is all-ASCII). hashlib.sha1(s).hexdigest() gives the same result.
@JonSkeet If you try to copy and paste OP original input string you'll notice that between callerId1495611935 and apiKey{[B{+%P)s;WD5&5x there is an hidden \u200b character (don't ask me why).
Urgh - well spotted. that would explain things. I suspect that shouldn't be in the input.
@JonSkeet I agree.
Thanks so much for this, very good catch! And thanks JonSkeet for your help aswell, i'll try to fix this. :)
|

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.