python - 无法在 iconomi 的 python 中使用 sha512 签署消息
问题描述
我正在尝试通过iconomi.com上的 API 发送经过身份验证的消息。我习惯于在处理其他交换 API 时对消息进行签名,但无法用这个特定的 API 进行身份验证。
我阅读了官方文档进行身份验证:
您可以通过在 prehash 字符串时间戳 + 方法 + requestPath + 正文(其中 + 表示字符串连接)上使用 base64 解码的密钥创建 sha512 HMAC 来生成 ICN-SIGN 标头,并对输出进行 base64 编码,其中:
时间戳值与 ICN-TIMESTAMP 标头相同。body 是请求正文字符串,如果没有请求正文(通常用于 GET 请求),则省略。方法必须始终为大写
示例:base64_encode(HMAC_SHA512(secret_key, timestamp + upper_case(method) + requestPath + body))
我还在官方 github上找到了一个 java 客户端示例,请参阅下面的 java 签名生成:
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,requests
import hashlib,hmac,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), 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.post(api_url_target,headers=headers_sign,json = json.loads(body), timeout=3, verify=True).content
print (res)
推荐阅读
- vue.js - VueRouter 在导航后保持组件处于活动状态
- android - Flutter,如何在键盘打开时无缝滚动视图
- powerbi - 将单个表从 DirectQuery 更改为 Import
- python - 在 SQL 中将 Python 列表作为输入传递给 Redshift
- python - 使用 Pyinstaller 获取 exe,包括 pygubu
- sql - 在 clickhouse 上类似 ON CONFLICT DO NOTHING
- python-3.x - Jupyter / Tornado “弃用警告:`should_run_async` 将来不会自动调用 `transform_cell`”
- pycharm - JetBrains IDE - 控制台打印消息中本地文件的可点击链接
- ios - 当细分发生变化时,如何在 Eureka 中更新我的列表?
- python - 为什么我的类不继承其基类中定义的方法?