HMAC Calculation

I’m working on getting PayEezy working and running into probably what’s a stupid programmer trick on my part.

Using the values given at to generate an HMAC hash. They generate some test values on their website and the point is that whatever I generate should match theirs. Otherwise, a transaction fails.

[code]//These values are constant
dim apiKey as string = “y6pWAJNyJyjGv66IsVuWnklkKUPFbb0a”
dim token as string = “fdoa-a480ce8951daa73262734cf102641994c1e55e7cdf4c02b6”

//This value changes every 5 minutes
dim APISecret as string = “86fbae7030253af3cd15faef2a1f4b67353e41fb6799f576b5093ae52901e6f7”

//These values change constantly but they list them for testing purposes.
dim nonce as string = “9816090227570385000”
dim timestamp as string = “1446828246216”

dim message as string = apiKey +nonce + timestamp + token + kTestpayload

Dim result As String = Crypto.HMAC(APISecret, message, Crypto.Algorithm.SHA256)
dim sHexResult as string = EncodeHex(result.trim)
dim sReturn as string = EncodeBase64(sHexResult.trim)

//From their test website
dim sReturnAuthorization as string = “Y2YwMDMzNWYyZjZkNThmZmM5NDU3ZTkyMDVhYjFiZDZjZmFjODE2MDJmZWE4OTI3MTgyZGJhYzYxMWEwZjM2Yg==”

if sReturn <> sReturnAuthorization then

MUEwRjM2Qg==” Yes, there’s a line break in there.

Their example php code is:

$apiKey = “”;
$apiSecret = “”;
$nonce = “”;
$timestamp = “”;
$token = “”;
$payload = “<For POST - Request body / For GET - empty string>”;
$data = $apiKey . $nonce . $timestamp . $token . $payload;
$hashAlgorithm = “sha256”;

       <!-- Make sure the HMAC hash is in hex --> 
       $hmac = hash_hmac ( $hashAlgorithm , $data , $apiSecret, false );

       <!-- Authorization : base64 of hmac hash -->
       $authorization = base64_encode($hmac); 
       ehco $authorization;

As far as I can see I have the equivalent code. Any ideas on where I might be going wrong?

Could it be encodings? Have you tried Xojo.Crypto.HMAC instead?

I don’t get the same results, which concerns me, but it’s still not the result they get.

[code] dim apiKey as Text = “y6pWAJNyJyjGv66IsVuWnklkKUPFbb0a”
dim token as Text = “fdoa-a480ce8951daa73262734cf102641994c1e55e7cdf4c02b6”

dim APISecret as Text = “86fbae7030253af3cd15faef2a1f4b67353e41fb6799f576b5093ae52901e6f7”

dim nonce as Text = “9816090227570385000”
dim timestamp as Text = “1446828246216”

dim message as text = apiKey +nonce + timestamp + token + kTestpayload

dim mbData as xojo.Core.MemoryBlock = Xojo.Core.TextEncoding.UTF8.ConvertTextToData(message)
dim mbKey as xojo.Core.MemoryBlock = Xojo.Core.TextEncoding.UTF8.ConvertTextToData(APISecret)
dim mbHash as xojo.Core.MemoryBlock = Xojo.Crypto.HMAC(mbKey, mbData, Xojo.Crypto.HashAlgorithms.SHA256)

dim sReturn as text = Xojo.Core.TextEncoding.UTF16.ConvertDataToText(mbHash) //Must be UTF16 to not cause exception

dim sHexResult as string = EncodeHex(sReturn)

dim sReturn as string = EncodeBase64(sHexResult)[/code]

For what it’s worth, I tried the HMAC routines from Einhugur and MBS and got the exact same string back that I generated from the Global Xojo Crypto function. I will continue to look at encodings.

The results are identical. However, before base64 encoding, yours is in all caps and there’s isn’t.

DecodeBase64(YOURBASE64RESULT) = "CF00335F2F6D58FFC9457E9205AB1BD6CFAC81602FEA8927182DBAC611A0F36B"

DecodeBase64(THEIRBASE64RESULT) = "cf00335f2f6d58ffc9457e9205ab1bd6cfac81602fea8927182dbac611a0f36b"

Indeed, good catch Andrew. I will do more testing this afternoon to see if lowercase is indeed the solution.

Another thing that caught me off guard that I didn’t catch until this morning was that EncodeBase64 has a default line length of 76. I had to go in and set it to zero. Here is the final algorithm that works for PayEezy:

[code]Shared Function GenerateHmac(apiKey as string, apiSecret as string, token as string, nonce as string, currentTimestamp as string, payload as String) As string
dim message as string = apiKey + nonce + currentTimestamp + token + payload

//Xojo Global
Dim result As String = Crypto.HMAC(APISecret, message, Crypto.Algorithm.SHA256)
dim sHexResult as string = EncodeHex(result.trim).Lowercase //Important. Put it in lowercase!!!

dim sReturn as string = EncodeBase64(sHexResult, 0) //Adding zero put its all on one line.

return sReturn
End Function[/code]