Generating HMAC-SHA256 Signature in C# from a Python sample

Question:

I’ve been trying to generate HMAC-SHA256 signature using three parameters; a Unix timestamp in seconds, an API Key and an API Secret, in C#.Net for authentication in a spesific style, but couldn’t manage to reverse-engineer the steps from an example code in Python.

The Python code I’m trying to dechiper the steps from is:

import hmac
import hashlib
import datetime
import json

def create_signature_Py27(key, secret):  # (string key, string secret) 
    timestamp = int(datetime.datetime.now().timestamp())  # UNIX timestamp in seconds
    string = "{}{}".format(timestamp, key)
    return hmac.new(secret, string, hashlib.sha256).hexdigest()

# Python 2.7 - 3.5+ 
# Note: latest versions of hmac lib requires 'secret' and 'string' as byte strings but not unicode
#
def create_signature(key, secret):  # (string key, string secret) 
    timestamp = int(datetime.datetime.now().timestamp())  # UNIX timestamp in seconds
    string = "{}{}".format(timestamp, key)
    return timestamp, hmac.new(secret.encode(), string.encode(), hashlib.sha256).hexdigest()

def auth_request(key, secret):
    timestamp, signature = create_signature(key, secret)
    return json.dumps({'e': 'auth',
        'auth': {'key': key, 'signature': signature, 'timestamp': timestamp,}, 'oid': 'auth', })

auth_request = auth_request('1WZbtMTbMbo2NsW12vOz9IuPM', '1IuUeW4IEWatK87zBTENHj1T17s'):

What I’ve tried so far:

       public static string TEST(string timestamp4, string apikey1, string apisecret1)
       {

     
           HMACSHA256 hmc1 = new HMACSHA256(Encoding.ASCII.GetBytes(apisecret1));
           string mes = timestamp4 + apikey1;
           MessageBox.Show(mes);

           byte[] hmres1 = hmc1.ComputeHash(Encoding.ASCII.GetBytes(mes));
           string hex1 = BitConverter.ToString(hmres1).Replace("-", string.Empty);
           string b641 = Convert.ToBase64String(hmres1).Replace("=", "");
           MessageBox.Show(b641, "b64");
           return b641;                   // THIS TEST SIGNITURE RETURNS SOMETHING LIKE "asdaefcdvcxv/sdfdsfsd/fsd" , WHERE DOES THE "/" COMES FROM?
                                         //TIMESTAMP RETURNS WRONG VALUE WHICH THEN FEED INTO SIGNITURE FUNCTION- GIVING INVALID SIGNITURE( but its unix timestamp in sec's whish is expected)
}

But with this, I cannot re-generate the correct sample signature. The Sample Apikey,Secret,timestamp and their product signature:

  • apiSecret 1IuUeW4IEWatK87zBTENHj1T17s

  • timestamp 1448034533

  • apiKey 1WZbtMTbMbo2NsW12vOz9IuPM

  • signature 7d581adb01ad22f1ed38e1159a7f08ac5d83906ae1a42fe17e7d977786fe9694

Instead, the signature I end up with is:

  • Generated Signature 3EHLmGeh0jK9vRLgh/0j5LgQU6h/nijzj4G9KBBjv10

I have tried to feed the parameters one by one to the encryption function but that didn’t go well.

When I use the real function to generate a signature with the real Api Key and Secret and realtime timestamp, the returned message from the server shows that timestamp is incorrect(but I couldn’t see any problem), and that is also feed into the signature, which could have been solely due to the incorrect timestamp but even with the provided sample ApiKey and Secret, the test function generates entirely different structure.(with "/" in it and shorter)

There is no problem so far with the Json request function, but, just in case, this is what it should look like(the signature given her differs from the above):

{
"e": "auth",
"auth": {
"key": "1WZbtMTbMbo2NsW12vOz9IuPM.",
"signature": "02483c01efc26fac843dd34d0342d269bacf4daa906a32cb71806eb7467dcf58",
"timestamp": 1448034533
}
}

I apologize in advance if I missed any existing topics explaining this problem, and I’d greatly appreciate if someone could shed some light on this issue.

Asked By: bergdi

||

Answers:

Your method returns the base64 representation of the signature.

If you return hex1 instead, you get the expected result in upper case. If you want lower case letters, return hex1.ToLower();

Answered By: mbd
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.