Delphi 10.2 Coinbase Pro API Signature



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

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

CB-ACCESS-SIGN 标头是通过在预哈希字符串时间戳 + 方法 + requestPath + 正文(其中 + 表示字符串连接(上使用 base64 解码的密钥创建 sha256 HMAC 并对输出进行 base64 编码来生成的。时间戳值与 CB-ACCESS-TIMESTAMP 标头相同。正文是请求正文字符串,如果没有请求正文,则省略(通常用于 GET 请求(。该方法应为大写。

我知道时间戳是正确的,因为我首先从 coinbase 服务器获取它,然后将其传递到签名中。所以我猜它与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 返回无效签名。

不要将AnsiString用于二进制数据。您的数据正在经历 Ansi<->Unicode 转换。

将 base64 键解码为字节,并按原样使用 hmac 键,然后按原样对生成的字节进行编码,而不是字节的十六进制编码表示形式。

试试这个:

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;

最新更新