Leon Cullens
Leon Cullens

Reputation: 12476

How to create this hash on Windows Phone 8

I'm working with the Kraken API and to query the private methods I need to send a hash as a parameter. This is what their documentation says:

Public methods can use either GET or POST.

Private methods must use POST and be set up as follows:

HTTP header:

API-Key = API key

API-Sign = Message signature using HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key

POST data:

nonce = always increasing unsigned 64 bit integer

otp = two-factor password (if two-factor enabled, otherwise not required)

Note: There is no way to reset the nonce to a lower value so be sure to use a nonce generation method that won't generate numbers less than the previous nonce. A persistent counter or the current time in hundredths of a second precision or higher is suggested.

They also have a PHP/Node.JS/Python example that creates the API-Sign hash. I am trying to port this code to C# for Windows Phone 8, but I encountered a big problem: the HMACSHA512 class isn't available for Windows Phone. I tried searching for alternatives that can create a HMAC-SHA512 hash, but couldn't find much. HashLib isn't available for Windows Phone. CryptSharp is, but I can't figure out how to add both a message and a password like PHP's hash_hmac() function allows. I also went searching for the algorithm/pseudo code for the HMAC-SHA512 algorithm to implement my own class but strangely enough I couldn't find it (does it have another name?).

Long story short, I need to convert this code in a Windows Phone 8 compatible piece of code that yields the same result:

if(!isset($request['nonce'])) {
    // generate a 64 bit nonce using a timestamp at microsecond resolution
    // string functions are used to avoid problems on 32 bit systems
    $nonce = explode(' ', microtime());
    $request['nonce'] = $nonce[1] . str_pad(substr($nonce[0], 2, 6), 6, '0');
}

// build the POST data string
$postdata = http_build_query($request, '', '&');

// set API key and sign the message
$path = '/' . $this->version . '/private/' . $method;
$sign = hash_hmac('sha512', $path . hash('sha256', $request['nonce'] . $postdata, true), base64_decode($this->secret), true);
$headers = array(
    'API-Key: ' . $this->key,
    'API-Sign: ' . base64_encode($sign)
);

The first part (till $sign = ...) looks pretty straightforward:

long nonce = DateTime.UtcNow.Ticks;

string postData = "nonce=" + nonce;
if (!string.IsNullOrEmpty(otp))
{
    postData += "&otp=" + otp;
}

But when I get to the cryptography part, I get stuck due to the lack of libraries.

Upvotes: 2

Views: 1083

Answers (1)

XeroxDucati
XeroxDucati

Reputation: 5190

This isn't likely to even compile, but it should give you the general idea..

byte[] uriPath = GetBytes(uriPathString);
byte[] nonceAndPostData = GetBytes(nonce + postData);

byte[] keyData = Convert.FromBase64String(apiKey);
string decodedKey = Encoding.UTF8.GetString(keyData);

byte[] result;
SHA512 shaM = new SHA512Managed();
SHA256 shaN = new SHA256Managed();
result = shaN.ComputeHash(nonceAndPostData);
result = shaM.ComputeHash(result + decodedKey);

static byte[] GetBytes(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

Upvotes: -1

Related Questions