如何在 Clojure 中正确签署 GDAX 请求
How to correctly sign GDAX request in Clojure
一段时间以来,我一直在为私有 GDAX 端点的签名请求而苦苦挣扎。我尝试过的所有操作都会导致 400 响应,并显示消息 "invalid signature." 我已多次阅读他们关于此事的文档,可以在 here. My current code is below. I'm using clj-http
for making requests. I'm using their /time
endpoint response for the timestamp, and I'm using pandect 中找到有关 sha256 HMAC 生成的文档。在将 secret-decoded
传递给 sha256-hmac
之前,我尝试使用 String.
将其转换为字符串。我还使用 clj-http
的调试标志检查了请求。在我看来,我完全按照他们的指示行事,但一定是出了什么问题。在发布到这里之前,我已经做了很多在线搜索。任何帮助将不胜感激。
(defn get-time
[]
(-> (str (:api-base-url config) "/time")
(http/get {:as :json})
:body))
(defn- create-signature
([timestamp method path]
(create-signature timestamp method path ""))
([timestamp method path body]
(let [secret-decoded (b64/decode (.getBytes (:api-secret config)))
prehash-string (str timestamp (clojure.string/upper-case method) path body)
hmac (sha256-hmac prehash-string secret-decoded)]
(-> hmac
.getBytes
b64/encode
String.))))
(defn- send-signed-request
[method path & [opts]]
(let [url (str (:api-base-url config) path)
timestamp (long (:epoch (get-time)))
signature (create-signature timestamp method path (:body opts))]
(http/request
(merge {:method method
:url url
:as :json
:headers {"CB-ACCESS-KEY" (:api-key config)
"CB-ACCESS-SIGN" signature
"CB-ACCESS-TIMESTAMP" timestamp
"CB-ACCESS-PASSPHRASE" (:api-passphrase config)
"Content-Type" "application/json"}
:debug true}
opts))))
(defn get-accounts []
(send-signed-request "GET" "/accounts"))
(send-signed-request "GET" "/accounts")))
我已经弄清楚这个问题了。以防万一有人碰巧遇到这个非常具体的问题,我发布了解决方案。我的错误是我使用了 pandect 的 sha256-hmac
函数,其中 returns 是一个字符串 hmac,然后我将其转换为字节数组,对其进行 base64 编码,然后将其转换回字符串。在这些转换的某处,或者可能在 pandect 函数的转换中,值以错误的方式更改。
有效的是使用 pandect 的 sha256-hmac*
函数(注意星号),它 returns 一个原始字节数组 hmac,然后直接对结果进行 base64 编码,并将其转换为字符串。下面是更正后的有效代码片段,我可以用它向私有 GDAX 端点发出请求。
(defn create-signature
([timestamp method path]
(create-signature timestamp method path ""))
([timestamp method path body]
(let [secret-decoded (b64/decode (.getBytes (:api-secret config)))
prehash-string (str timestamp (clojure.string/upper-case method) path body)
hmac (sha256-hmac* prehash-string secret-decoded)]
(-> hmac
b64/encode
String.))))
一段时间以来,我一直在为私有 GDAX 端点的签名请求而苦苦挣扎。我尝试过的所有操作都会导致 400 响应,并显示消息 "invalid signature." 我已多次阅读他们关于此事的文档,可以在 here. My current code is below. I'm using clj-http
for making requests. I'm using their /time
endpoint response for the timestamp, and I'm using pandect 中找到有关 sha256 HMAC 生成的文档。在将 secret-decoded
传递给 sha256-hmac
之前,我尝试使用 String.
将其转换为字符串。我还使用 clj-http
的调试标志检查了请求。在我看来,我完全按照他们的指示行事,但一定是出了什么问题。在发布到这里之前,我已经做了很多在线搜索。任何帮助将不胜感激。
(defn get-time
[]
(-> (str (:api-base-url config) "/time")
(http/get {:as :json})
:body))
(defn- create-signature
([timestamp method path]
(create-signature timestamp method path ""))
([timestamp method path body]
(let [secret-decoded (b64/decode (.getBytes (:api-secret config)))
prehash-string (str timestamp (clojure.string/upper-case method) path body)
hmac (sha256-hmac prehash-string secret-decoded)]
(-> hmac
.getBytes
b64/encode
String.))))
(defn- send-signed-request
[method path & [opts]]
(let [url (str (:api-base-url config) path)
timestamp (long (:epoch (get-time)))
signature (create-signature timestamp method path (:body opts))]
(http/request
(merge {:method method
:url url
:as :json
:headers {"CB-ACCESS-KEY" (:api-key config)
"CB-ACCESS-SIGN" signature
"CB-ACCESS-TIMESTAMP" timestamp
"CB-ACCESS-PASSPHRASE" (:api-passphrase config)
"Content-Type" "application/json"}
:debug true}
opts))))
(defn get-accounts []
(send-signed-request "GET" "/accounts"))
(send-signed-request "GET" "/accounts")))
我已经弄清楚这个问题了。以防万一有人碰巧遇到这个非常具体的问题,我发布了解决方案。我的错误是我使用了 pandect 的 sha256-hmac
函数,其中 returns 是一个字符串 hmac,然后我将其转换为字节数组,对其进行 base64 编码,然后将其转换回字符串。在这些转换的某处,或者可能在 pandect 函数的转换中,值以错误的方式更改。
有效的是使用 pandect 的 sha256-hmac*
函数(注意星号),它 returns 一个原始字节数组 hmac,然后直接对结果进行 base64 编码,并将其转换为字符串。下面是更正后的有效代码片段,我可以用它向私有 GDAX 端点发出请求。
(defn create-signature
([timestamp method path]
(create-signature timestamp method path ""))
([timestamp method path body]
(let [secret-decoded (b64/decode (.getBytes (:api-secret config)))
prehash-string (str timestamp (clojure.string/upper-case method) path body)
hmac (sha256-hmac* prehash-string secret-decoded)]
(-> hmac
b64/encode
String.))))