无法在 iconomi

问题描述

我正在尝试通过位于 iconomi.com 的 API 发送经过身份验证的消息。 我在处理其他交换API的时候习惯了对消息进行签名,但是无法通过这个特定的API进行身份验证。

我阅读了 official documentation 以进行身份​​验证:

您通过使用以下命令创建 sha512 HMAC 来生成 ICN-SIGN 标头 预哈希字符串时间戳 + 方法 + 上的 base64 解码密钥 requestPath + body(其中 + 表示字符串连接)和 对输出进行 base64 编码,其中:

时间戳值与 ICN-TIMESTAMP 标头相同。身体 是请求正文字符串,如果没有请求正文则省略 (通常用于 GET 请求)。方法必须总是大写

示例:base64_encode(HMAC_SHA512(secret_key,timestamp + upper_case(method) + requestPath + body))

我还在 official github 上找到了一个 java 客户端示例,请参阅 java 中的 bellow 签名生成

private String generateServerDigest(String method,String uri,long timestamp,String body) {
    //return timestamp + request.getmethodValue() + uri + body;
    String checkDigestString = timestamp + method + uri + body;//  "GET+/v1/daa-list+123123123"; //timestamp in epoch milliseconds

    // hash server composited digest with algorithm and apikeys secret
    SecretKeySpec signingKey = new SecretKeySpec(apiSecret.getBytes(),"HmacSHA512");
    Mac mac;
    try {
        mac = Mac.getInstance(signingKey.getAlgorithm());
        mac.init(signingKey);
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        log.warn("Could not ={}",signingKey.getAlgorithm());
        return null;
    }

    return Base64.getEncoder().encodetoString(mac.doFinal(checkDigestString.getBytes()));
}

请注意官方文档中的 checkDigestString 代码 timestamp + method + uri + body 和注释 GET+/v1/daa-list+123123123 已经不同。


这是我的 python 实现尝试:

def sign(timestamp,method,requestPath,body):
    global api_secret
    base64_decoded_secret_key = base64.b64decode(api_secret)
    content_to_hash = (str(timestamp) + method.upper() + requestPath + body).encode('utf-8')
    sign_digest = hmac.new(base64_decoded_secret_key,content_to_hash,hashlib.sha512).digest()    
    return base64.b64encode(sign_digest).decode('utf-8')

当我用 requestPath = "/v1/user/balance"(需要验证)尝试这个签名方法时,它失败了,没有错误......


有没有同时使用java和python的可以帮我把这个签名方法转换成python?

解决方法

此代码适用于 GET:

import time,requests
import hashlib,hmac,base64

api_key = "my api key"
api_secret = "my api secret"

defaut_encoding = "utf8"

uri = "https://api.iconomi.com"
requestPath = "/v1/user/balance"
api_url_target = uri+requestPath # https://api.iconomi.com/v1/user/balance
method="GET"
body=""
icn_timestamp = int(1000.*time.time())

message = (str(icn_timestamp) + method.upper() + requestPath + body).encode(defaut_encoding)
signature_digest = hmac.new(api_secret.encode(defaut_encoding),message,hashlib.sha512).digest() #here digest is byte
b64_signature_digest= base64.b64encode(signature_digest).decode(defaut_encoding)

headers_sign= {
    "ICN-API-KEY":api_key,"ICN-SIGN":b64_signature_digest,"ICN-TIMESTAMP":str(icn_timestamp)
}

s=requests.session()
res = s.get(api_url_target,headers=headers_sign,timeout=3,verify=True).content
print (res)

更新@Karl 评论,此代码适用于 POST:

import time,base64,json

api_key = "my api key"
api_secret = "my api secret"
ticker = "my ticker strategy"


defaut_encoding = "utf8"

uri = "https://api.iconomi.com"
requestPath = "/v1/strategies/"+ticker+"/structure"
api_url_target = uri+requestPath # https://api.iconomi.com/v1/strategies/{my ticker strategy}/structure
method="POST"
body="{'ticker': ticker,'values': [{'rebalancedWeight': 1.,'targetWeight':1.,'assetTicker': 'XMR','assetName': 'Monero','assetCategory': 'Privacy'}]}"
icn_timestamp = int(1000.*time.time())

message = (str(icn_timestamp) + method.upper() + requestPath + body).encode(defaut_encoding)
signature_digest = hmac.new(api_secret.encode(defaut_encoding),"ICN-TIMESTAMP":str(icn_timestamp)
}

s=requests.session()
res = s.post(api_url_target,json = json.loads(body),verify=True).content
print (res)