Deribit FIX API 登录

Deribit FIX API Logon

以下代码似乎无法使用 FIX API 登录。通过相同的用户名和访问密钥从交换中获取“无效凭据”似乎可以通过 websockets 使用 REST API。 随机数的定义似乎有问题。在这里,我正在尝试一个基本示例来尝试登录。

        string user = settings->get().getString("Username");
        message.setField(Username(user));
        string pass = settings->get().getString("Password");
        milliseconds ms = duration_cast< milliseconds >(
                system_clock::now().time_since_epoch()
        );
        long long millis = ms.count();
        string nonce = "abcdefghijkabcdefghijkabcdefghijkabcdefghijk";
        nonce = base64_encode(nonce);
        string raw = to_string(millis) + "." + nonce;

        message.setField(RawData(raw));
        string password = base64_encode(sha256(raw+pass));

        message.setField(Password(password));

用于base64和sha256编码的函数有:

string base64_encode(const std::string &in) {

    std::string out;

    int val = 0, valb = -6;
    for (unsigned char c : in) {
        val = (val << 8) + c;
        valb += 8;
        while (valb >= 0) {
            out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val>>valb)&0x3F]);
            valb -= 6;
        }
    }
    if (valb>-6) out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val<<8)>>(valb+8))&0x3F]);
    while (out.size()%4) out.push_back('=');
    return out;
}

string sha256(const string str)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str.c_str(), str.size());
    SHA256_Final(hash, &sha256);
    stringstream ss;
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        ss << hex << setw(2) << setfill('0') << (int)hash[i];
    }
    return ss.str();
}

我正在关注 Deribit https://docs.deribit.com/?shell#logon-aquickfix 的文档作为修复引擎。

代码遵循文档中提到的描述。

我能够解决这个问题,我正在提供它的解决方案,以便其他人也能受益。

base64编码使用的方法:

static const std::string base64_chars =
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             "abcdefghijklmnopqrstuvwxyz"
             "0123456789+/";

std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
  std::string ret;
  int i = 0;
  int j = 0;
  unsigned char char_array_3[3];
  unsigned char char_array_4[4];

  while (in_len--) {
    char_array_3[i++] = *(bytes_to_encode++);
    if (i == 3) {
      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
      char_array_4[3] = char_array_3[2] & 0x3f;

      for(i = 0; (i <4) ; i++)
        ret += base64_chars[char_array_4[i]];
      i = 0;
    }
  }

  if (i)
  {
    for(j = i; j < 3; j++)
      char_array_3[j] = '[=10=]';

    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
    char_array_4[3] = char_array_3[2] & 0x3f;

    for (j = 0; (j < i + 1); j++)
      ret += base64_chars[char_array_4[j]];

    while((i++ < 3))
      ret += '=';

  }

  return ret;

} 

以及我如何计算其他字段:

        string user = settings->get().getString("Username");

        milliseconds ms = duration_cast< milliseconds >(system_clock::now().time_since_epoch());
        string timestamp_in_ms = std::to_string(ms.count());
        unsigned char nonce [32] = {};
        RAND_bytes(nonce, sizeof(nonce));
        string nonce64 = base64_encode(nonce, sizeof(nonce));
        string secret = settings->get().getString("Password");
        string raw_data = timestamp_in_ms + "." + nonce64;
        string base_signature_string = raw_data + secret;
        
        unsigned char hash[SHA256_DIGEST_LENGTH];
        SHA256_CTX sha256;
        SHA256_Init(&sha256);
        SHA256_Update(&sha256, base_signature_string.c_str(), base_signature_string.size());
        SHA256_Final(hash, &sha256);

        static string password_sha_base64 = base64_encode(hash, sizeof(hash));

PS: RAND_bytes 和 SHA 函数是 openssl 中的预定义函数。