1

I'm trying to do a GET request to an API with the specified headers and even though all the headers are right and exactly the same as the working python code but I get an error saying on of the header is not correct. This is the working python code:

api_passphrase = "passphrase"
api_secret = "secret"
api_key = "key"

url = 'https://api-futures.kucoin.com/api/v1/position?symbol=XBTUSDM'
now = int(time.time() * 1000)
str_to_sign = str(now) + 'GET' + '/api/v1/position?symbol=XBTUSDM'
signature = base64.b64encode(
    hmac.new(api_secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
passphrase = base64.b64encode(hmac.new(api_secret.encode('utf-8'), api_passphrase.encode('utf-8'), hashlib.sha256).digest())
headers = {
    "KC-API-SIGN": signature,
    "KC-API-TIMESTAMP": str(now),
    "KC-API-KEY": api_key,
    "KC-API-PASSPHRASE": passphrase,
    "KC-API-KEY-VERSION": "2"
}
response = requests.request('get', url, headers=headers)
# print(response.json())
# print(response)
# print(response.request.headers)
# print(response.request.body)
# #
print(passphrase)
 

and this is my Haskell code:

import qualified Config                    as C
import           Control.Lens
import           Control.Monad
import           Control.Monad.Catch
import           Control.Monad.IO.Class
import qualified Crypto.Hash.SHA256        as H
import qualified Data.Aeson                as A
import           Data.Aeson.Lens           as AL
import qualified Data.ByteString           as B
import qualified Data.ByteString.Base64    as U
import qualified Data.ByteString.Char8     as BC
import qualified Data.ByteString.Lazy      as BL
import qualified Data.ByteString.Lazy.UTF8 as BU
import           Data.Monoid
import qualified Data.Text                 as T
import           Data.Text.Encoding        (encodeUtf8)
import qualified Data.Time.Clock.POSIX     as TI
import           GHC.Generics
import           Network.Wreq


apiSign :: BC.ByteString -> BC.ByteString -> BC.ByteString -> TI.POSIXTime -> IO BC.ByteString
apiSign method endpoint body time = do
  timeStamp <- apiTimeStamp' time
  let message = mconcat [timeStamp,method,endpoint,body]
  let hash = H.hmac (BC.pack C.apiSecret) message
  return $ (encodeUtf8 . U.encodeBase64) hash

apiTimeStamp' :: TI.POSIXTime -> IO BC.ByteString
apiTimeStamp' = return . BC.take 13 . BC.pack . show . (* 1000)

apiPassphrase :: BC.ByteString
apiPassphrase = U.encodeBase64' $ H.hmac (BC.pack C.apiSecret) (BC.pack C.apiPassphrase)

apiKeyVersion :: BC.ByteString
apiKeyVersion = BC.pack C.apiVersion

main' :: IO ()
main' = do
  time <- TI.getPOSIXTime
  timeStamp <- apiTimeStamp' time
  apiSignValue <- apiSign "GET" "/api/v1/position?symbol=XBTUSDM" "" time
  let opt = defaults & header "Accept" .~ ["*/*"]
                     & header "KC-API-VERSION" .~ ["2"]
                     & header "KC-API-KEY" .~ [BC.pack C.apiKey]
                     & header "KC-API-TIMESTAMP" .~ [timeStamp]
                     & header "KC-API-PASSPHRASE" .~ [apiPassphrase]
                     & header "KC-API-SIGN" .~ [apiSignValue]
                     & param "symbol" .~ ["XBTUSDM"]

  r <- getWith opt (kucoin ++ "position")
  let response = r ^. responseBody
  print response

The error says that the passphrase is not correct

this is the passphrase generated by python: b'e3GO2zT3kWv1oVrAhAF1TByq0u8ExNMw/76KrsFGnls='

and this is the passphrse genereted by Haskell: e3GO2zT3kWv1oVrAhAF1TByq0u8ExNMw/76KrsFGnls=

and finally, this is the error I get while using the wreq library in Haskell

"{"code":"400004","msg":"Invalid KC-API-PASSPHRASE"}")

everything else beside passphrase is fine.

At some point I thought it's because of lazy evaluation and I tried BangPatterns but the issue didn't resolve.

  • 3
    I don't see the equivalent of your Python code's `headers`. It seems possible the problem lies in another field than `KC-API-PASSPHRASE` and the error is intentionally incorrect in this way for security reasons. – Daniel Wagner Jun 26 '22 at 14:05

0 Answers0