2012-10-16 16 views
14

Ich versuche, bei bitfloor.com eine signierte Anforderung an den Handel API zu machen (es ist eine REST API)Coldfusion CFHTTP mit SHA512-hmac unterzeichnet Anfrage REST Körper

Bitfloor gibt mir:

1) API Key (dh 6bd2b780-00be-11E2-bde3-2837371c3c3a)

2) Secret Key (dh oaFz62YpmbWiXwseMUSod53D8pOjdyVcweNYdiab/TSQqxk6IuemDvimNaQoA ==)

Hier finden Sie genaue Anweisungen des Bitfloor die Anforderung für die Herstellung:

Anforderungen müssen HTTPS POST-Anforderungen an Port 443 (https) sein. Jede Anfrage muss die erforderlichen Header enthalten (siehe unten). Die Header identifizieren, verifizieren und validieren Ihre Anfrage, um Manipulationen zu verhindern. Header

bitfloor-key Dies ist die von bitfloor zur eindeutigen Identifizierung Ihres Accounts zur Verfügung gestellt. (D 6bd2b780-00be-11E2-bde3-2837371c3c3a)

bitfloor-sign Das Vorzeichenfeld ist ein sha512-HMAC des Anforderungs Körper, den geheimen Schlüssel verwendet, die auf Ihren api Schlüssel entspricht.

Ihre Anfrage zu unterzeichnen: base64 den geheimen Schlüssel in die rohen Bytes (64 Bytes) zu dekodieren. Verwenden Sie diese Bytes für Ihre sha512-hmac-Signatur des http-Anfragekörpers. Base64 codiert das Signaturergebnis und sendet dieses Header-Feld.

Bitboden-Passphrase Die Passphrase, die Sie beim Erstellen dieses API-Schlüssels angegeben haben. Wir können Ihre Passphrase nicht wiederherstellen, wenn sie vergessen wurde. Sie müssen einen neuen API-Schlüssel erstellen.

bitfloor-Version Die api Version der Ressource, die Sie interessieren. Der einzige derzeit gültige Wert ist 1


nach einer vollen 8 Stunden von Versuch und Irrtum und der Suche im Internet immer wieder für jeden Art von Einsicht oder Informationen, der folgende Code ist so nah wie möglich, um zu kommen, was ich denke, irgendwo in der Richtung sein könnte, wie die Anfrage richtig zu erstellen, ach, egal was ich bezweifle bekomme ich "Ungültige Signatur" von ihren zurückgegeben API.

Hier ist, was ich bisher ...

FIRST, fand ich diese Funktion auf dem Netz, dass jemand die SHA512 Unterzeichnung zu tun hat geschrieben:

<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> 

Ich habe keine Ahnung, was es tut , aber es scheint zu funktionieren und tut es ohne Fehler.

Hier ist meine Implementierung dieser Funktion und mein Versuch, die Anfrage zu machen: HINWEIS: Der "Nonce" -Wert ist ein erforderlicher Parameter, der mit der Anfrage gesendet werden muss.

<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> 

Ich denke, die meisten meiner Verwirrung kommt davon, nicht genau zu wissen, was der "Anfragekörper" ist. Ich habe das Gefühl, ich unterschreibe nicht das Richtige.

Ich hoffe, es gibt einen Coldfusion Programmierer da draußen, der mit unterschriebenen Anfragen vertraut ist. Ich bin mit meinem Latein am Ende.

Bitte helfen!

Namaste

Antwort

2

Ich habe nicht, dass api verwendet, aber ich lief einige Tests und es scheint, mit den folgenden Verbesserungen zu arbeiten:

  • Da der secretKey Wert Base64 codiert ist, muss Ihre Signatur-Funktion binaryDecode verwenden Extrahieren Sie die Bytes. Die Verwendung von String.getBytes(...) erzeugt ein völlig anderes (und falsches) Ergebnis.

  • Der Wert erwartete Anfrage Körper ist nur: nonce=#nonceValue# (ohne die führenden "?")

  • Sie die Content-Type=application/x-www-form-urlencoded Header zu verlangen scheint, sonst scheitert es, den Inhalt und die Antwort zu analysieren: { „Fehler“: "no nonce angegeben"}

-Code

<cfset apiKey = "6bd2b780-00be-11e2-bde3-2837371c3c3a"> 
<cfset secretKey = "oaFz62YpmbWiXwseMUSod53D8pOjdyVcweNYdiab/TSQqxk6IuemDvimNaQoA=="> 
<cfset passphrase = "your secret phrase"> 

<cfset requestBody = "nonce="& now().getTime()> 
<cfset signBytes = HMAC_SHA512(secretKey, requestbody)> 
<cfset signBase64 = binaryEncode(signBytes, "base64")> 

<cfhttp url="https://api.bitfloor.com/orders" method="post" port="443" result="bitfloor"> 
    <cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded"> 
    <cfhttpparam type="header" name="bitfloor-key" value="#apiKey#"> 
    <cfhttpparam type="header" name="bitfloor-sign" value="#signBase64#"> 
    <cfhttpparam type="header" name="bitfloor-passphrase" value="#passphrase#"> 
    <cfhttpparam type="header" name="bitfloor-version" value="1"> 
    <cfhttpparam type="body" value="#requestBody#"> 
</cfhttp> 

<cfdump var="#bitfloor#" label="Response"> 

<cffunction name="HMAC_SHA512" returntype="binary" access="public" output="false"> 
    <cfargument name="base64Key" type="string" required="true"> 
    <cfargument name="signMessage" type="string" required="true"> 
    <cfargument name="encoding" type="string" default="UTF-8"> 

    <cfset var messageBytes = JavaCast("string",arguments.signMessage).getBytes(arguments.encoding)> 
    <cfset var keyBytes = binaryDecode(arguments.base64Key, "base64")> 
    <cfset var key = createObject("java","javax.crypto.spec.SecretKeySpec")> 
    <cfset var mac = createObject("java","javax.crypto.Mac")> 
    <cfset key = key.init(keyBytes,"HmacSHA512")> 
    <cfset mac = mac.getInstance(key.getAlgorithm())> 
    <cfset mac.init(key)> 
    <cfset mac.update(messageBytes)> 

    <cfreturn mac.doFinal()> 
</cffunction> 
+0

Vielen Dank Leigh! Ich wünschte, ich könnte dir die Freude erklären, die ich empfand, als ich sah, dass echte Daten nach hunderten von Fehlversuchen endlich zurückkamen. Es schien, als würde es nie funktionieren. Du bist ein echter Lebensretter! Danke danke danke! Ich bleibe auf dieser Website und versuche mein Bestes, um es zu bezahlen. Namaste mein Freund – Jay

+0

Froh, dass es geholfen hat! (Vergessen Sie nicht, neue API-Schlüssel zu erzeugen :) – Leigh

+0

Ich bin gerade gekommen, um Ihnen Punkte für die Beantwortung einer so schwierigen Frage zu geben. –

Verwandte Themen