7

I have the following function in C#, a hashing function which I need converted into PHP. I've tried a few things in PHP but I don't get the same results (I'm not at all good with .NET)

private static string GetSignature(string args, string privatekey)
{
    var encoding = new System.Text.ASCIIEncoding();
    byte[] key = encoding.GetBytes(privatekey);
    var myhmacsha256 = new HMACSHA256(key);
    byte[] hashValue = myhmacsha256.ComputeHash(encoding.GetBytes(args));
    string hmac64 = Convert.ToBase64String(hashValue);
    myhmacsha256.Clear();
    return hmac64;
} 

One (wrong) attempt in PHP is this:

function encode($data,$key)
{
    return base64_encode( hash_hmac('sha256', $data, $key ) );
}

The ANSWER

A slight variation of what was suggested below by DampeS8N worked for me.

function encode($data,$key)
{
    iconv_set_encoding("input_encoding", "ASCII");
    iconv_set_encoding("internal_encoding", "ASCII");
    iconv_set_encoding("output_encoding", "ASCII");

    return base64_encode( hash_hmac('sha256', $data, $key, true ) );
}

Please also not the fourth parameter of hash_hmac - now set to true for raw output as binary data

1
  • You should accept DampeS8Ns answer if he pointed you in the right direction. Commented Jan 10, 2012 at 13:58

1 Answer 1

6

I suspect the very first line of your .net code is the culprit. PHP has no encoding for the string itself and so when it comes time to hash it either is hashing the internal PHP string format's bytes (unlikely, can someone else confirm?) or more than likely is converting to something else first. In this case probably unicode which is decidedly not the same bytes that the string would be in ASCII as .net is requesting.

My advice would be to ensure that PHP is also using ASCII, with iconv, to allow interoperability.

function encode($data,$key)
{
    return base64_encode( hash_hmac('sha256', iconv( iconv_get_encoding( "internal_encoding"), "ASCII", $data ), iconv( iconv_get_encoding( "internal_encoding"), "ASCII", $key ) ) );
}

I can't be sure that the above code will output the desired hashes, however, as I don't have .net handy to test the initial code. But this might point you in the right direction.

If this doesn't work, the value inside iconv_get_encoding( might be the culprit, try "output_encoding" or "input_encoding" as well. It is also possible that you'll need to set these same values to ASCII with iconv_set_encoding(.

Good Luck!


Update! This is what ultimately worked:

function encode($data,$key)
{
    iconv_set_encoding("input_encoding", "ASCII");
    iconv_set_encoding("internal_encoding", "ASCII");
    iconv_set_encoding("output_encoding", "ASCII");

    return base64_encode( hash_hmac('sha256', $data, $key, true ) );
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for this. It totally makes sense although doesnt seem to work. I have the same problem that I have no .net environment to test with. I also think I still need this encoding.GetBytes(privatekey);
That should just be getting the raw bytes of the ASCII for the key. Because of the dynamic typing in PHP it might be really hard to get at that and control it. I'm sure it is some combination of setting the right things with iconv_set_encoding( to ensure that hash_hmac( isn't undoing all the hard work you've done with iconv( itself.
Sorry, didnt realise that was what I was supposed to do !

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.