14

bitfloor.comのトレーディングAPI(REST API)に署名されたリクエストを送信しようとしています

Bitfloorは私に:

1)APIキー(つまり、6bd2b780-00be-11e2-bde3-2837371c3c3a)

2)秘密鍵(すなわち、oaFz62YpmbWiXwseMUSod53D8pOjdyVcweNYdiab / TSQqxk6IuemDvimNaQoA ==)

以下は、リクエストを行うためのBitfloorの正確な手順です。

リクエストは、ポート443(https)でのHTTPSPOSTリクエストである必要があります。各リクエストには、必要なヘッダー(以下にリスト)が含まれている必要があります。ヘッダーは、改ざんを防ぐためにリクエストを識別、検証、および検証します。ヘッダー

bitfloor-keyこれは、アカウントを一意に識別するためにbitfloorによって提供されます。(つまり、6bd2b780-00be-11e2-bde3-2837371c3c3a)

bitfloor-sign記号フィールドは、APIキーに対応する秘密キーを使用するリクエスト本文のsha512-hmacです。

リクエストに署名するには: base64で秘密鍵をrawバイト(64バイト)にデコードします。これらのバイトを、httpリクエスト本文のsha512-hmac署名に使用します。Base64は署名結果をエンコードし、このヘッダーフィールドで送信します。

bitfloor-passphraseこのAPIキーを作成するときに指定したパスフレーズ。忘れてしまった場合、パスフレーズを取り戻すことはできません。新しいAPIキーを作成する必要があります。

bitfloor-version関心のあるリソースのAPIバージョン。現在有効な値は1のみです。


8時間の試行錯誤を繰り返し、インターネットであらゆる種類の洞察や情報を繰り返し検索した後、次のコードは、リクエストを適切に作成する方法のどこかにあると思うものにできるだけ近づきました。残念ながら、私が何をしようとも、APIから「無効な署名」が返されます。

これが私がこれまでに持っているものです...

最初に、誰かがSHA512署名を行うために書いたこの関数をWeb上で見つけました。

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

私はそれが何をするのか分かりませんが、それはうまくいくようで、エラーなしでそうします。

この関数の実装とリクエストの試行は次のとおりです。注:「nonce」値は、リクエストとともに送信する必要のある必須パラメーターです。

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

私の混乱のほとんどは、「リクエストボディ」が何であるかを正確に知らないことから来ていると思います。おそらく正しいものに署名していないような気がします。

署名されたリクエストに精通しているColdfusionプログラマーがいることを願っています。私は私の機知に富んでいます。

助けてください!ナマステ

4

1 に答える 1

2

私はそのAPIを使用していませんが、いくつかのテストを実行したところ、次の調整で動作するようです:

  • 値は base64 でエンコードされているためsecretKey、署名関数を使用binaryDecodeしてバイトを適切に抽出する必要があります。を使用String.getBytes(...)すると、まったく異なる (そして間違った) 結果が生成されます。

  • 予想されるリクエスト本文の値は次のとおりです: nonce=#nonceValue#(先頭の なし"?")

  • ヘッダーが必要なようですContent-Type=application/x-www-form-urlencoded。それ以外の場合、コンテンツの解析に失敗し、応答は次のとおりです: {"error":"no nonce specified"}

コード

 <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>
于 2012-10-17T00:30:52.707 に答える