Как правильно подписать запрос GDAX в Clojure

Некоторое время я боролся с подписанием запросов на частные конечные точки GDAX. Все, что я попробовал, приводит к 400 ответам с сообщением "неверная подпись". Я прочитал их документацию по этому вопросу несколько раз, которую можно найти здесь. Мой текущий код ниже. я использую clj-http для подачи запросов. Я использую их /time ответ конечной точки для временной метки, и я использую pandect для генерации HAMAC sha256. Я пытался преобразовать secret-decoded к строке, используя String. прежде чем передать его sha256-hmac, Я также изучил запрос, используя 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")))

1 ответ

Я понял проблему. На случай, если у кого-то возникнет эта специфическая проблема, я выкладываю решение. Моя ошибка заключалась в том, что я использовал sha256-hmac функция из pandect, которая возвращает строку hmac, затем я конвертировал ее в байтовый массив, кодировал в base64 и преобразовывал обратно в строку. Где-то в этих преобразованиях или, возможно, в преобразовании функции pandect, значение изменяется ошибочно.

Что работает с использованием sha256-hmac* функция (обратите внимание на звездочку) из pandect, которая возвращает необработанный байтовый массив 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.))))
Другие вопросы по тегам