Не удается подписать сообщение с использованием sha512 в python на iconomi

#python #api #authentication #sha512

#python #API #аутентификация #sha512

Вопрос:

Я пытаюсь отправить аутентифицированное сообщение через API по адресу iconomi.com . Я привык подписывать сообщения при работе с другими API exchange, но не могу пройти аутентификацию с помощью этого конкретного API.

Я прочитал официальную документацию для аутентификации:

Вы генерируете заголовок ICN-SIGN, создавая HMAC sha512, используя декодированный base64 секретный ключ в строке предварительной хэш-строки timestamp method requestPath body (где представляет конкатенацию строк) и кодируете вывод base64, где:

значение метки времени совпадает с заголовком ICN-TIMESTAMP . тело является строкой тела запроса или опущено, если нет тела запроса (обычно для запросов GET). метод всегда должен быть в верхнем регистре

Пример: base64_encode(HMAC_SHA512(секретный ключ, временная метка верхний регистр (метод) Путь запроса тело))

Я также нашел пример java-клиента на официальном github, см. Ниже Генерация подписи в 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()));
}
 

Пожалуйста, обратите внимание, что код timestamp method uri body checkDigestString и комментарий 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?

Комментарии:

1. удалось ли вам выполнить POST? GET работает для меня, но POST по какой-то причине возвращает 401 несанкционированный

Ответ №1:

Этот код будет работать для 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)
 

Комментарии:

1. Разве это не должно работать и для сообщений / обновлений? Я пытаюсь обновить свою структуру, но получаю эту ошибку b'{«timestamp»:1617618493409,»path»:»/v1/strategies/PRINCIPLES/structure»,»status»:401,»error»:»Unauthorized»,»message»:»»,»requestId»:»031154a9-10370867″}’

2. Нет, это не должно так работать для запросов POST, пожалуйста, позвольте мне когда-нибудь перепроверить, как с этим справиться! С уважением

3. @ASTEFANI ницца, я искал скрипт Iconomi на python, который действительно работает. Размер страницы по умолчанию равен 25 — я не смог запустить его, чтобы получить все мои исторические действия («/ v1 / user / activity»). У вас есть идея?

4. @schluk5 хорошо, вы можете сделать что-то вроде: s.get(api_url_target,param={«PageNumber»:2}, headers= headers_sign,timeout= 3, verify=True).content, затем увеличивайте номер страницы, пока не получите пустую транзакцию. Список.