I am trying to make a signed request to the trading API at bitfloor.com (it's a REST API)
Bitfloor gives me:
1) API Key (i.e. 6bd2b780-00be-11e2-bde3-2837371c3c3a)
2) Secret Key (i.e. oaFz62YpmbWiXwseMUSod53D8pOjdyVcweNYdiab/TSQqxk6IuemDvimNaQoA==)
The following is Bitfloor's exact instructions for making the request:
Requests must be HTTPS POST requests on port 443 (https). Each request must contain the required headers (listed below). The headers identify, verify, and validate your request to prevent tampering. headers
bitfloor-key This is the provided by bitfloor to uniquely identify your account. (i.e. 6bd2b780-00be-11e2-bde3-2837371c3c3a)
bitfloor-sign The sign field is a sha512-hmac of the request body using the secret key which corresponds to your api key.
To sign your request: base64 decode the secret key into the raw bytes (64 bytes). Use those bytes for your sha512-hmac signing of the http request body. Base64 encode the signing result and send in this header field.
bitfloor-passphrase The passphrase you specified when creating this api key. We cannot recover your passphrase if forgotten. You will need to create a new API key.
bitfloor-version The api version of the resource you are interested in. The only valid value currently is 1
After a full eight hours of trial and error and searching the internet repeatedly for any sort of insight or information, the following code is as close as I can come to what I think might be somewhere in the direction of how to construct the request properly, alas, no matter what I attmept I get "Invalid Signature" returned by their API.
Here is what I have so far...
FIRST, I found this function on the web that someone wrote to do the SHA512 signing:
<cffunction name="HMAC_SHA512" returntype="binary" access="public" output="false">
<cfargument name="signKey" type="string" required="true">
<cfargument name="signMessage" type="string" required="true">
<cfset var jMsg = JavaCast("string",arguments.signMessage).getBytes("iso-8859-1")>
<cfset var jKey = JavaCast("string",arguments.signKey).getBytes("iso-8859-1")>
<cfset var key = createObject("java","javax.crypto.spec.SecretKeySpec")>
<cfset var mac = createObject("java","javax.crypto.Mac")>
<cfset key = key.init(jKey,"HmacSHA512")>
<cfset mac = mac.getInstance(key.getAlgorithm())>
<cfset mac.init(key)>
<cfset mac.update(jMsg)>
<cfreturn mac.doFinal()>
</cffunction>
I have no idea what it does, but it seems to work and does so without error.
Here is my implementation of this function and my attempt at making the request: NOTE: The "nonce" value is a required param that must be sent with the request.
<cffunction name="myorders">
<cfset nonce = dateDiff("s",createDateTime(2012,01,01,0,0,0),now())>
<cfset requestbody = "?nonce=#nonce#">
<cfset key = "oaFz62YpmbWiXwseMUSod53D8pOjdyVcweNYdiab/TSQqxk6IuemDvimNaQoA==">
<cfset sign = HMAC_SHA512(key,requestbody)>
<cfset signed = binaryEncode(sign,"Base64")>
<!--- HTTP REQUEST --->
<cfhttp url = "https://api.bitfloor.com/orders#requestbody#"
method = "post"
result = "bitfloor">
<!--- HEADERS --->
<cfhttpparam
type = "body"
value = requestbody>
<cfhttpparam
type = "header"
name = "bitfloor-key"
value = "6bd2b780-00be-11e2-bde3-2837371c3c3a">
<cfhttpparam
type = "header"
name = "bitfloor-sign"
value = signed>
<cfhttpparam
type = "header"
name = "bitfloor-passphrase"
value = "mysecretpassphrase">
<cfhttpparam
type = "header"
name = "bitfloor-version"
value = "1">
</cfhttp>
</cffunction>
I think most of my confusion comes from not knowing exactly what the "request body" is. I feel like I'm not signing the right thing perhaps.
I hope there is a Coldfusion programmer out there who is familiar with signed requests. I'm at my wit's end.
Please help! Namaste