Reputation: 12476
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
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