Kraken API - ColdFusion

185 views Asked by At

Trying to tackle the Kraken API. Using ColdFusion 2016. I have a few tries in here, but can't seem to quite get it. So testing message, message2, message3 attempts.

https://docs.kraken.com/rest/#section/Authentication/Headers-and-Signature

HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key

EXPECTED RESULT:

4/dpxb3iT4tp/ZCVEwSnEsLxx0bqyhLpdfOpc6fn7OR8+UClSV5n9E6aSS8MPtnRfp32bAb0nmbRn6H8ndwLUQ==

<cfset _key = "APIKEY">
<cfset _s = "kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F">
<cfset nonce = "1616492376594">
<cfset payload = "nonce=1616492376594&ordertype=limit&pair=XBTUSD&price=37500&type=buy&volume=1.25">
<cfset URIPath = "/0/private/AddOrder">

<cfscript>

    apiKey = "#_key#";
    apiSecret = "#_s#";
    theKeyBytes = charsetDecode(#_s#, "UTF-8");
    _Secret64 = toBase64(#_s#);

    // get_kraken_signature(urlpath, data, secret):

    h = '#uripath#' & #payload#;
    _hash = hmac(h, theKeyBytes, "HMACSHA256");


    //HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key

    //SHA256(nonce + POST data))
    _256 = hmac(payload, "HMACSHA256");
    _sign = hmac(payload, theKeyBytes, "HMACSHA256");

    // HMAC-SHA512 of (URI path + SHA256(nonce + POST data))
    message = '#uripath#' & #_256#;
    message2 = '#uripath#' & #_256# & #_Secret64#;
    message3 = '#uripath#' & #_sign# & #_Secret64#;

    _512 = hmac(#message#, "HMACSHA512");
    _512_2 = hmac(#message2#, "HMACSHA512");
    _512_3 = hmac(#message3#, "HMACSHA512");

    _512_H = hmac(#_hash#, "HMACSHA512");
    S_H = hmac(#_512_h#, #_s#, "HmacSHA512");
    H64 = toBase64(binaryDecode(#s_h#, "hex"));


    // base64 decoded secret API key
    _64 = toBase64(#_512#);

    S_Hex = hmac(#_512#, #_s#, "HmacSHA512");
    Hex64 = toBase64(binaryDecode(#s_hex#, "hex"));

    S_Hex2 = hmac(#_512_2#, #_s#, "HmacSHA512");
    Hex642 = toBase64(binaryDecode(#s_hex2#, "hex"));

    S_Hex3 = hmac(#_512_3#, #_s#, "HmacSHA512");
    Hex643 = toBase64(binaryDecode(#s_hex3#, "hex"));

</cfscript>

EXPECTED RESULT:

4/dpxb3iT4tp/ZCVEwSnEsLxx0bqyhLpdfOpc6fn7OR8+UClSV5n9E6aSS8MPtnRfp32bAb0nmbRn6H8ndwLUQ==

Hex64 Gets: w1PXl7IDLs1Pri1Vf++UcLFWIFedkxgpceFVkVFbxt7wvjj/Q0wtwwLSMJxV7bMOdFi+BEN3lHuX+CWRx2SxAQ==

Hex642 Gets: Zxd+96KuI3wSQJ/b0l79djB1M7FMsczoWOfs9Ha5YWIC6sc6uryEGn4MgkcHnF/ndsxDQ2y/jSHl0RxTIuc7PA==

Hex643 Gets: 5KCKhgRGexBPF7SgnSB5G0m3bu+2ecf4fAOndDG0pvYLh0PeWC1nWodi5szigcGU4TyLLb80jPNAR7OmK0t0Sw==

2

There are 2 answers

0
AndreasRu On BEST ANSWER

Taking this question as an exercise, I've managed to translate the python function from KrakenAPI docs to CFML script. That function should help you and others with a practical solution. Also publishing it here for my own documentation:

<cfscript>

    public string function getKrakenSignature( urlpath, postdata, nonce, secretAsBase64) localmode=true {

        // assign arguments to local variables
        urlpath= arguments.urlpath;
        nonce= arguments.nonce;
        postdata = arguments.postdata;
        secretAsBase64= arguments.secretAsBase64;

        // convert urlpath to a binary Hex representation 
        urlpathBinary= toBinary( toBase64( urlpath ));
        urlpathBinaryAsHex= BinaryEncode( urlpathBinary, "HEX");


        // convert secret to binary
        secretBinary= ToBinary(  arguments.secretAsBase64 );

        // concatenate nonce and postdata
        noncePostdata = nonce & postdata; 

        //get binary digest as Hex representation
        noncePostdataDigestBinaryAsHex= hash( noncePostdata, "SHA-256" );


        // concatenate urlPath binary (hex) and oncePostdataDigest binary (hex) 
        messageBinaryAsHex= urlpathBinaryAsHex & noncePostdataDigestBinaryAsHex;

        // convert message hex representation to binary
        messageBinary= BinaryDecode( messageBinaryAsHex, "HEX");

        // sign the message with hmac function
        messageHmacDigestBinaryAsHex = hmac( messageBinary, secretBinary, "HMACSHA512");
        messageHmacDigestBinary=BinaryDecode( messageHmacDigestBinaryAsHex, "HEX");

        return binaryEncode( messageHmacDigestBinary, "base64" );

    }

encodedPayLoad="nonce=1616492376594&ordertype=limit&pair=XBTUSD&price=37500&type=buy&volume=1.25";
nonce="1616492376594";
api_sec = "kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F1huXg==";
urlpath="/0/private/AddOrder";
signature = getKrakenSignature( urlpath, encodedPayLoad, nonce, api_sec);
writeoutput( signature );

</cfscript>

Find a gist here at tryCf.com

0
Merle_the_Pearl On

Yes answer above works. Arrrgh - I had the wrong Secret Key - Cut Paste issue. I only figured it out when reversing the secretkey - that script below as well

kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F

vs

kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F1huXg==

Credit AndreasRu above for that answer and method.

I am posting another method below. I have used this one for most of the Crypto API's.

HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key

    <cfset _key = "APIKEY">
    <cfset _s = "kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F1huXg==">
    <cfset nonce = "1616492376594">
    <cfset payload = "nonce=1616492376594&ordertype=limit&pair=XBTUSD&price=37500&type=buy&volume=1.25">
    <cfset URIPath = "/0/private/AddOrder">

    <cfscript>

    // URIPATH to a binary Hex
    BURL64 = toBinary(toBase64(#URIPath#));
    URLHEX = BinaryEncode(BURL64,"HEX");

    // Secret to binary
    SB = ToBinary(#_s#);

    // SHA256(nonce + POST data)
    SHA256_Post = '#nonce#' & #payload#;
    SHA_256 = hash(#SHA256_Post#, "SHA-256", "UTF-8");

    // BUILD SHA-512
    URI256POST = '#urlhex#' & #SHA_256#;

    // convert SHA512 buid to message hex
    MESSAGEHEX = BinaryDecode(URI256POST,"HEX");

    // messageHex to HMAC SHA-512
    M512 = hmac(#MESSAGEHEX#, #SB#, "HMACSHA512");
    M512HEX = BinaryDecode(M512,"HEX");

    // Final Signature
    SignFinal = toBase64(M512HEX);

    </cfscript>

    <cfoutput>

    EXPECTED RESULT:
    4/dpxb3iT4tp/ZCVEwSnEsLxx0bqyhLpdfOpc6fn7OR8+UClSV5n9E6aSS8MPtnRfp32bAb0nmbRn6H8ndwLUQ==

    #signfinal#

    </cfoutput>  

Figuring out secret code below. Not needed for Kraken API-Sign

    <cfscript>

    hexEncoded = binaryEncode(secretBinary, "hex");
    base64Encoded = binaryEncode(secretBinary, "base64");
    writeDump
      ([
        secretBinary,
        hexEncoded,
        base64Encoded,
        binaryDecode(hexEncoded, "hex"),
        binaryDecode(base64Encoded, "base64")
      ]);

    </cfscript>