1

I've a C# method which I have to convert to PHP. I tried several things, but I still get different results. Unfortunately I cannot change anything on the C# application. It has to be as it is. Maybe one of you could help?

C#:

static public void Main ()
{
    string StringToSign = "test";
    string Key = "123456";

    //Calculate Signature
    string Signature = CalculateSignature(StringToSign, Key);

    Console.WriteLine ("StringToSign: " + StringToSign);
    Console.WriteLine ("Key: " + Key);
    Console.WriteLine ("Signature Caculated: " + Signature + "\r\n");
}

static private string CalculateSignature(String StringToSign, String Key)
{
    Encoding enc = Encoding.GetEncoding(65001);

    byte[] KeyHex = StringHexValuesToByteArray(Key);
    byte[] StringToSign_byte = enc.GetBytes(StringToSign);

    //Check Signature
    HMACSHA256 hmac = new HMACSHA256(KeyHex);
    byte[] hashValue = hmac.ComputeHash(StringToSign_byte);

    return BitConverter.ToString(hashValue).Replace("-", "");
}

static public byte[] StringHexValuesToByteArray(string str)
{
    if (str.Length % 2 != 0)
        return null;

    string s = string.Empty;
    byte[] ret = new byte[str.Length / 2];

    for (int run = 0; run < str.Length / 2; run++)
    {
        s = str.Substring(run * 2, 2);
        ret[run] = Convert.ToByte(s, 16);
    }
    return ret;
}

PHP:

public function send() {

    $stringToSign = 'test';
    $key = '123456';

    //Calculate Signature
    $signature = $this->calculateSignature($stringToSign, $key);

    print_r("StringToSign: " . $stringToSign . PHP_EOL);
    print_r("Key: " . $key . PHP_EOL);
    print_r("Signature Caculated: " . $signature . PHP_EOL);
}

private function calculateSignature($stringToSign, $key) {

    // check signature
    $hash = strtoupper(hash_hmac('sha256', $stringToSign, $key, false));
    return $hash;
}

For better understanding, here is the output of the code blocks above:

C#

StringToSign: test

Key: 123456

Signature Caculated: DA3617974490FB780F04F06287BF93B0F24A7F15970471146428B943FFDC7850

PHP

StringToSign: test

GroupKey: 123456

Signature Caculated: 9D2BB116E1DF997FFE8A5139FC1D187F976C19579A138414A112BC2E39020EBA

1 Answer 1

1

If you want to modify the PHP to make it equivalent to C#

Change

$hash = strtoupper(hash_hmac('sha256', $stringToSign, $key, false));

to

$hash = strtoupper(hash_hmac('sha256', $stringToSign, hex2bin($key), false));

Be sure to check the code will work for non-ASCII characters like àèéìòù.

ideone here.

If you want to modify the C# code to make it equivalent to PHP

You are complicating everything:

static private string CalculateSignature(String stringToSign, String key)
{
    byte[] key_byte = Encoding.UTF8.GetBytes(key);
    byte[] stringToSign_byte = Encoding.UTF8.GetBytes(stringToSign);

    //Check Signature
    HMACSHA256 hmac = new HMACSHA256(key_byte);
    byte[] hashValue = hmac.ComputeHash(stringToSign_byte);

    return BitConverter.ToString(hashValue).Replace("-", "");
}

There is nothing hex. And instead of using Encoding.GetEncoding(65001) it is normally better to use Encoding.UTF8, because it is clearer for everyone.

Note that there could be problems with the encoding. Try calculating the hmac of something like àèéìòù to see which encoding the PHP is using.

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

2 Comments

Unfortunately I cannot change anything on the C# application. It has to be as it is. Actually the key looks like "8A46AA67F474FB3285D3A55F4798EB24BCFF460AF1529F07AD140DB77F579D3CD1A614C8D80A56952F2CB96ED60F8BDE0BCC398C196507008C404BD2DCDFF9D1". I just changed it for testing purposes.
@ChristianDornbusch Updated the response.

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.