Swift:用于 coinspot 的 HMAC SHA-512 API

Swift: HMAC SHA-512 for coinspot API

我正在尝试连接到 coinspot API,它的文档非常劣质。 Link 下面:

https://www.coinspot.com.au/api

它需要一个附加到用户密钥的 HMAC SHA512 散列,然后是 POST 请求参数中的随机数密钥,它是一个时间戳,转换为整数以在每个请求中保持唯一性。 header 需要 API 密钥和签名。

我通过 coinspot 的私有 API URL https://www.coinspot.com.au/api

使用 Alamofire 的 JSON 编码 post 请求

我似乎收到了一条连接成功的消息,但收到了 {status = invalid;} 响应。

我能想到的只有两件事是错误的 POST 请求(似乎不是这样,好像我没有在参数中添加 nonce 键,我得到了正确的响应从服务器请求一个)和 HMAC SHA-512 哈希。我已经从 HMAC SHA512 using CommonCrypto in Swift 3.1

并稍微修改它以仅包含 SHA512 哈希。

代码如下:

extension String{

    var sha512:String{
         return HMAC.hash(inp: self, algo: HMACAlgo.SHA512)
    }
}

public struct HMAC{

    static  func hash(inp: String, algo: HMACAlgo)->String{
        if  let stringData = inp.data(using: String.Encoding.utf8, allowLossyConversion: false){
            return hexStringFromData(input: digest(input: stringData as NSData, algo: algo))
        }
        return ""
    }

    private  static  func digest(input: NSData, algo: HMACAlgo)-> NSData{
        let digestLength = algo.digestLength()
        var hash = [UInt8](repeating: 0, count: digestLength)
        CC_SHA512(input.bytes, UInt32(input.length), &hash)
        return  NSData(bytes: hash, length: digestLength)
    }

    private  static  func hexStringFromData(input: NSData)-> String{
        var bytes = [UInt8](repeating: 0, count: input.length)
        input.getBytes(&bytes, length: input.length)
        var hexString = ""
        for byte in bytes{
            hexString += String(format: "%02x", UInt8(byte))
        }
        return hexString
    }
}

enum HMACAlgo{
    case SHA512

    func digestLength()->Int{
        var result:CInt = 0
        switch self{
        case .SHA512:
            result = CC_SHA512_DIGEST_LENGTH
        }
        return Int(result)
    }
}

CommonCrypto 库已正确添加了 objectiveC 桥接文件,打印结果为我提供了正确的散列签名。

我已经联系了 coinspot,但他们收到了很多请求,而且他们只有一个 cookie 模板响应关于他们 API 的任何技术支持。

这是我放置在函数下的 Alamofire 段,用于向 coinspot 服务器调用任何命令:

    func request(_ command: Router, params: [String: AnyObject]?, completion: @escaping (Result<JSON>)-> Void){
        var parameters = ["nonce": Int(Date().timeIntervalSince1970*1000) as AnyObject]
        if params != nil{
            parameters = parameters + params!
        }
let sign = customerSecret.sha512
        print(sign)
        let headers:HTTPHeaders = ["key": APIKey, "sign": sign]
        do{
            try Alamofire.request( command.asURL(), method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON{(response) in
                guard let json = response.result.value else {
                    completion(.failure(CoinSpotError.networkError(error: response.result.error)))
                    return
                }
                print(response)
            }
        } catch {
            print("error")
        }
    }

我认为以上是正确的。路由器只是一组调用正确的 POST 请求以检索数据的地址。

最后,我将请求更改为 GET,去掉了 header 和参数,我得到了状态 ok 和结果 JSON。我想我只需要在浏览器上尝试一个命令就可以了,

API 确实说每个请求都必须是 post 方法。

Coinspot API 已关闭,没有预计到达时间:Coinbase API down

我会继续收到 {'status': 'invalid'} 我提出的任何请求。

他们的 publicapi 仍在运行,尽管仅适用于 BTC、LTC 和 DOGE。

def get_latest_price():
   r = requests.get("https://www.coinspot.com.au/pubapi/latest").json()
   print(r)