Подпись запроса

Поддержка
  • Имеется код на питоне.
    Не могу воспроизвести одну его часть в бас
    Сам код, он работает:

    import hmac
    import hashlib
    import base64
    from urllib.parse import urlencode
    API_KEY = 'xxxxxxxx-xxxxxxxxx-xxxxxxxx-xxxxxxxxxx'
    API_SECRET = 'xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxx'
    timestamp = '2021-03-04T12:54:56'
    params_dict = {
        'AccessKeyId': API_KEY,
        'SignatureMethod': 'HmacSHA256',
        'SignatureVersion': '2',
        'Timestamp': timestamp
    }
    params_url_enc = urlencode(
        sorted(params_dict.items(), key=lambda tup: tup[0]))
    pre_signed = 'GET\n'
    pre_signed += 'api.huobi.pro\n'
    pre_signed += '/v1/account/accounts\n'
    pre_signed += params_url_enc
    sig_bin = hmac.new(
        API_SECRET.encode(),
        pre_signed.encode(),
        hashlib.sha256).digest()
    sig_b64_bytes = base64.b64encode(sig_bin)
    sig_b64_str = sig_b64_bytes.decode()
    sig_url = urlencode({'Signature': sig_b64_str})
    url = 'https://api.huobi.pro/v1/account/accounts?'
    url += params_url_enc + '&'
    url += sig_url
    print('API_KEY={}'.format(API_KEY))
    print('API_SECRET={}'.format(API_SECRET))
    print('timestamp={}'.format(timestamp))
    print('params_dict={}'.format(params_dict))
    print('params_url_enc={}'.format(params_url_enc))
    print('pre_signed:\n{}'.format(pre_signed))
    print('sig_bin={}'.format(sig_bin))
    print('sig_b64_bytes={}'.format(sig_b64_bytes))
    print('sig_b64_str={}'.format(sig_b64_str))
    print('sig_url={}'.format(sig_url))
    print('url={}'.format(url))
    

    А проблемы с этой часть:

    sig_bin = hmac.new(
        API_SECRET.encode(),
        pre_signed.encode(),
        hashlib.sha256).digest()
    sig_b64_bytes = base64.b64encode(sig_bin)
    sig_b64_str = sig_b64_bytes.decode()
    sig_url = urlencode({'Signature': sig_b64_str})
    

    Как его воспроизвести в басе?

    П.С,
    вот как написано в документации
    Use the pre-signed text in step 6 and your API Secret Key to generate hash code by HmacSHA256 hash function.
    Encode the hash code with base-64 to generate the signature.

    Я делал так:

    const crypto = require('crypto');
    const query_string = [[PRE_SIGN]]
    const secret = [[SECRET_KEY]]
    [[RESULT]] = hash = crypto.createHmac('sha256', secret)
                       .update(query_string)
                       .digest('hex');
    

    Потом encode через Base64 кодировать/декодировать
    Но то ли лыжи не едут. то ли... В общем получаю не ту сигну.

  • В общем воспользовался ИИ - ChatGPT
    Дал ему код с запросом переделать под JS

    Он мне выдал весь код. Я только готовую переменную с pre_signed подсунул и убрал вывод url, так как почему то дублировались некоторые символы.
    И вот что получилось. сигна совпадает с нужной, запрос срабатывает.

    const crypto = require('crypto');
    const querystring = require('querystring');
    
    const API_KEY = [[API_KEY]];
    const API_SECRET = [[SECRET_KEY]];
    const timestamp = '2021-03-04T12:54:56';
    
    const params_dict = {
        AccessKeyId: API_KEY,
        SignatureMethod: 'HmacSHA256',
        SignatureVersion: '2',
        Timestamp: timestamp
    };
    const params_url_enc = querystring.stringify(
        Object.entries(params_dict).sort()
    );
    
    const pre_signed = [[PRE_SIGN]]
    
    const sig_bin = crypto.createHmac('sha256', API_SECRET)
                          .update(pre_signed)
                          .digest();
    const sig_b64_str = Buffer.from(sig_bin).toString('base64');
    const sig_url = querystring.stringify({ Signature: sig_b64_str });
    const url = `https://api.huobi.pro/v1/account/accounts?${params_url_enc}&${sig_url}`;
    
    console.log(`API_KEY=${API_KEY}`);
    console.log(`API_SECRET=${API_SECRET}`);
    console.log(`timestamp=${timestamp}`);
    console.log(`params_dict=${JSON.stringify(params_dict)}`);
    console.log(`params_url_enc=${params_url_enc}`);
    console.log(`pre_signed:\n${pre_signed}`);
    console.log(`sig_bin=${sig_bin}`);
    console.log(`sig_b64_str=${sig_b64_str}`);
    console.log(`sig_url=${sig_url}`);