Delphi HMAC SHA512对Bittrex Exchange的签名调用

Delphi HMAC SHA512对Bittrex Exchange的签名调用,delphi,indy,hmac,sha512,Delphi,Indy,Hmac,Sha512,我已经为此工作了一段时间,但我无法从服务器获得成功的响应。 有关这方面的所有文档可在 签名位的主要关键点可以在标题身份验证 我一直在使用的哈希文件可以在SourceForge上找到。它位于底部,名为4.00.15 我使用这个文件的原因很简单,它似乎是唯一给我正确答案的文件。或者我应该说,它给了我正确的答案,与它给我的结果相比 我曾尝试使用Indy组件生成正确的哈希值,但它似乎从未与网站上的值匹配。也许我没有正确地使用它,或者使用了正确的库或者其他东西,但是我将添加我创建的示例。 (在我写这篇文

我已经为此工作了一段时间,但我无法从服务器获得成功的响应。 有关这方面的所有文档可在

签名位的主要关键点可以在标题身份验证
我一直在使用的哈希文件可以在SourceForge上找到。它位于底部,名为4.00.15

我使用这个文件的原因很简单,它似乎是唯一给我正确答案的文件。或者我应该说,它给了我正确的答案,与它给我的结果相比

我曾尝试使用Indy组件生成正确的哈希值,但它似乎从未与网站上的值匹配。也许我没有正确地使用它,或者使用了正确的库或者其他东西,但是我将添加我创建的示例。 (在我写这篇文章的时候,我刚刚再次测试过,看起来我得到了正确的答案,想想看,也许我使用的是一个更好的OpenSSL库。无论如何,我也会把我的INDY示例放在下面)。


在使用这个版本进行散列之前,我只得到了 “{”success:“false”,message:“APISIGN\u NOT\u PROVIDED”,“result:null}” 当我计算出自定义HTTP头时,我终于继续前进了,现在得到了 “{”success:false,“message”:“无效的_签名”,“result:null}” 它可能是一个简单的无效的临时状态,还是一个太旧的状态? 是否一切正常,或者我缺少INDY组件的一些基本组件设置?


我有一个类似的问题,我最终解决了。我使用了我通过谷歌搜索找到的hmac.pas单元,但不得不对其进行修改,使其与10.1西雅图(特别是IDBytes有点不同)

重要提示:我还必须修改hmac.pas单元,以从函数的HexStr变体前面删除“0x”

另外:我做了所有输入分析

我的测试函数如下

function TBTXClient.Get(sCommand, sAddParams: string): string;
var
  sURL: string;
  nonce: string;
  res: string;
  sec2: string;
  sha: TIDHashSha256;
  hmac: TIdHMAC;
  hash: string;
  ms: TMemoryStream;
begin
  nonce := inttostr(getticker);
  sURL := 'https://bittrex.com/api/v1.1/'+sCommand+'?apikey='+MY_KEY+'&nonce='+nonce+sAddParams;

  hash := THMACUtils<TIDHMacSha512>.HMAC_HexStr(MY_SECRET,sURL);

  //Debug.Log('url = '+sUrl);
  //Debug.Log('hash = '+hash);
  QuickHTTPSGet(sURL, res, 'apisign', hash);

  result := res;

end;
这个俗气的函数,是我从自己的https单元借用的,它展示了如何处理头参数

function QuickHTTPSGet(sURL: ansistring; out sOutREsponse: string; 
  addHead: string =''; addHeadValue: string = ''): boolean;
var
  htp: IXMLhttprequest;
begin

  htp := ComsXMLHTTP30.create();
  try
    htp.open('GET', sURL, false, null, null);
    if addHead <> '' then
      htp.setRequestHeader(addHead, addHeadValue);
    htp.send('');
    result := htp.status = 200;
    if result then
      sOutREsponse := htp.responsetext
    else
      soutResponse := 'error '+inttostr(htp.status);
  except
    on e: Exception do begin
      result := false;
      sOutResponse := 'error '+e.message;
    end;
  end;

end;
函数QuickHTTPSGet(sURL:ansisting;out sOutREsponse:string;
addHead:string='';addHeadValue:string='':布尔值;
变量
htp:IXMLhttprequest;
开始
htp:=ComsXMLHTTP30.create();
尝试
htp.open('GET',sURL,false,null,null);
如果添加头“”,则
htp.setRequestHeader(addHead,addHeadValue);
htp.send(“”);
结果:=htp.status=200;
如果结果是这样的话
sOutREsponse:=htp.responsetext
其他的
soutResponse:=“错误”+inttostr(htp.状态);
除了
在e上:异常确实开始
结果:=假;
sOutResponse:=“错误”+e.message;
结束;
结束;
结束;

您是否考虑使用Unicode?对于字符值>#127,Ansi字符串散列与Unicode字符串散列不同。请注意,如果
:=nilfunction TBTXClient.Get(sCommand, sAddParams: string): string;
var
  sURL: string;
  nonce: string;
  res: string;
  sec2: string;
  sha: TIDHashSha256;
  hmac: TIdHMAC;
  hash: string;
  ms: TMemoryStream;
begin
  nonce := inttostr(getticker);
  sURL := 'https://bittrex.com/api/v1.1/'+sCommand+'?apikey='+MY_KEY+'&nonce='+nonce+sAddParams;

  hash := THMACUtils<TIDHMacSha512>.HMAC_HexStr(MY_SECRET,sURL);

  //Debug.Log('url = '+sUrl);
  //Debug.Log('hash = '+hash);
  QuickHTTPSGet(sURL, res, 'apisign', hash);

  result := res;

end;
unit hmac;

interface

uses
  System.SysUtils,
  EncdDecd,
  IdHMAC,
  IdSSLOpenSSL,
  helpers.indy,
  idglobal,
  IdHash;

type
  localstringtype = ansistring;

  THMACUtils<T: TIdHMAC, constructor> = class
  public
    class function HMAC(aKey, aMessage: localstringtype): TIdBytes;
    class function HMAC_HexStr(aKey, aMessage: localstringtype): localstringtype;
    class function HMAC_Base64(aKey, aMessage: localstringtype): localstringtype;
  end;

implementation

class function THMACUtils<T>.HMAC(aKey, aMessage: localstringtype): TIdBytes;
var
  _HMAC: T;
begin
  if not IdSSLOpenSSL.LoadOpenSSLLibrary then Exit;
  _HMAC:= T.Create;
  try
    _HMAC.Key := AnsiStringToIDBytes(aKey);
    Result:= _HMAC.HashValue(AnsiStringToIDBytes(aMessage));
  finally
    _HMAC.Free;
  end;
end;

class function THMACUtils<T>.HMAC_HexStr(aKey, aMessage: localstringtype):     localstringtype;
var
  I: Byte;
begin
  Result:= '';//'0x';
  for I in HMAC(aKey, aMessage) do
    Result:= Result + IntToHex(I, 2);
end;

class function THMACUtils<T>.HMAC_Base64(aKey, aMessage: localstringtype):     localstringtype;
var
  _HMAC: TIdBytes;
begin
  _HMAC:= HMAC(aKey, aMessage);
  Result:= EncodeBase64(_HMAC, Length(_HMAC));
end;

end.
unit helpers.indy;

interface

uses
  idglobal, types, classes, sysutils, typex;


function TBytesToIDBytes(b: TBytes): TIDBytes;
function AnsiStringToIDBytes(a: ansistring): TIDBytes;

implementation


function TBytesToIDBytes(b: TBytes): TIDBytes;
var
  t: ni;
begin
  setlength(result, length(b));
  for t := low(b) to high(b) do
    result[t] := b[t];

end;
function AnsiStringToIDBytes(a: ansistring): TIDBytes;
var
  t: ni;
begin
  setlength(result, length(a));
  for t := 0  to length(a)-1 do
    result[t] := ord(a[STRZ+t]);

end;
function QuickHTTPSGet(sURL: ansistring; out sOutREsponse: string; 
  addHead: string =''; addHeadValue: string = ''): boolean;
var
  htp: IXMLhttprequest;
begin

  htp := ComsXMLHTTP30.create();
  try
    htp.open('GET', sURL, false, null, null);
    if addHead <> '' then
      htp.setRequestHeader(addHead, addHeadValue);
    htp.send('');
    result := htp.status = 200;
    if result then
      sOutREsponse := htp.responsetext
    else
      soutResponse := 'error '+inttostr(htp.status);
  except
    on e: Exception do begin
      result := false;
      sOutResponse := 'error '+e.message;
    end;
  end;

end;