Delphi 10.2 Coinbase Pro API签名

问题描述 投票:1回答:1

我正在尝试使用Delphi 10.2将Coinbase Pro API集成到我的程序中。

Coinbase Pro API需要四个不同的标头,其中之一是已加密的签名。我在形成有效签名时遇到问题。根据Coinbase Pro API文档:

CB-ACCESS-SIGN标头是通过使用prehash字符串时间戳+方法+ requestPath +正文(其中+表示字符串串联)上的base64解码密钥创建sha256 HMAC并生成base64编码输出而生成的。时间戳记值与CB-ACCESS-TIMESTAMP标头相同。主体为请求主体字符串,如果没有请求主体(通常用于GET请求),则省略。方法应为UPPER CASE。

我知道时间戳是正确的,因为我首先要从币库服务器获取时间戳,然后将其传递给签名。因此,我猜测它与base64解码/编码或sha256 hmac有关。

我的签名功能是:

function Signature(RequestPath, TimeStamp, Method : String) : ANSIString;
var
  skeydecode : AnsiString;
  sha256     : AnsiString;
  prehash    : AnsiString;
  Body       : String;

begin
  Body := '';

  prehash    :=  TimeStamp + Method + RequestPath + Body ;

////Option 1 - [Coinbase] Invalid Signature
  skeydecode := TIdDecoderMIME.DecodeString(APISecret);
  sha256     := trim(CalculateHMACSHA256(prehash ,skeydecode));

  result     := Tidencodermime.EncodeString(sha256);

end;

然后我要使用的HMAC函数是:

function CalculateHMACSHA256(const value, salt: String): String;
var
  hmac: TIdHMACSHA256;
  hash: TIdBytes;
begin
  LoadOpenSSLLibrary;
  if not TIdHashSHA256.IsAvailable then
    raise Exception.Create('SHA256 hashing is not available!');
  hmac := TIdHMACSHA256.Create;
  try
    hmac.Key := IndyTextEncoding_UTF8.GetBytes(salt);
    hash := hmac.HashValue(IndyTextEncoding_UTF8.GetBytes(value));
    Result := ToHex(hash);
  finally
    hmac.Free;
  end;
end;

我可以通过REST请求成功连接到Coinbase API,因为我可以连接到时间端点,但这不需要签名标头。

[当尝试将签名标头包含在其他REST请求中时,coinbase api返回无效签名。

delphi encryption delphi-xe2 coinbase-api
1个回答
2
投票

不要将AnsiString用于二进制数据。您的数据正在通过AnsiUnicode转换。

将base64密钥解码为字节,并按原样将其用于hmac密钥,然后base64照原样对所得的字节进行编码,而不是字节的十六进制编码表示形式。

尝试一下:

function CalculateHMACSHA256(const value: String; const salt: TIdBytes): TIdBytes;
var
  hmac: TIdHMACSHA256;
begin
  LoadOpenSSLLibrary;
  if not TIdHashSHA256.IsAvailable then
    raise Exception.Create('SHA256 hashing is not available!');
  hmac := TIdHMACSHA256.Create;
  try
    hmac.Key := salt;
    Result := hmac.HashValue(IndyTextEncoding_UTF8.GetBytes(value));
  finally
    hmac.Free;
  end;
end;

function Signature(const RequestPath, TimeStamp, Method : String) : String;
var
  key : TIdBytes;
  sha256 : TIdBytes;
  prehash : String;
  Body : String;
begin
  Body := '';
  prehash := TimeStamp + UpperCase(Method) + RequestPath + Body;
  key := TIdDecoderMIME.DecodeBytes(APISecret);
  sha256 := CalculateHMACSHA256(prehash, key);
  Result := TIdEncoderMIME.EncodeBytes(sha256);
end;
© www.soinside.com 2019 - 2024. All rights reserved.