如何将RSA密钥从Delphi传递给Jira

时间:2018-03-29 11:13:39

标签: delphi authentication oauth rsa jira

我正在尝试使用OAuth从Delphi应用程序登录Jira。获取请求令牌时失败。我无法弄清楚如何将私有RSA密钥正确编码到HTML标头中。

如何在Delphi中实现?

1 个答案:

答案 0 :(得分:0)

终于搞定了。将此单元添加到您的项目中,然后添加“OAuth1SignatureMethod_RSA_SHA1'用途。然后将TOAuth1Authenticator.SigningClassName设置为' TOAuth1SignatureMethod_RSA_SHA1'

unit OAuth1SignatureMethod_RSA_SHA1;

interface

uses System.Classes, System.SysUtils, REST.Authenticator.OAuth;

type

  TOAuth1SignatureMethod_RSA_SHA1 = class(TOAuth1SignatureMethod_HMAC_SHA1)
  protected
    // returns RSA-SHA1 signature (not HMAC-SHA1)
    function Hash_HMAC_SHA1(const AData, AKey: string): string; override;
  public
    class function GetName: string; override;
  end;

implementation

uses IdSSLOpenSSL, IdSSLOpenSSLHeaders, idCTypes, idGlobal, System.NetEncoding;

function TOAuth1SignatureMethod_RSA_SHA1.Hash_HMAC_SHA1(const AData, AKey: string): string;
var
  buffer: TBytes;
  mdLength: TIdC_UInt;
  mdctx: EVP_MD_CTX;
  outbuf: TBytes;
  KeyBuffer: pBIO;
  FRSA: PRSA;
  md: PEVP_MD;
  rc: Integer;
  key: EVP_PKEY;

begin
  if not IdSSLOpenSSL.LoadOpenSSLLibrary then
    raise Exception.Create('LoadOpenSSLLibrary failed');

  // Load private key (key must include header and footer)
  //-----BEGIN PRIVATE KEY-----
  // ....
  // ....
  //-----END PRIVATE KEY-----

  buffer := TEncoding.ANSI.GetBytes(AKey);
  KeyBuffer := BIO_new_mem_buf(buffer, Length(buffer));

  if KeyBuffer = nil then
    raise Exception.Create('RSA out of memory');

  try
    FRSA := PEM_read_bio_RSAPrivateKey(KeyBuffer, nil, nil, nil);
    if not Assigned(FRSA) then
      raise Exception.Create('Private key error');
  finally
    BIO_free(KeyBuffer);
  end;

  md := EVP_get_digestbyname('SHA1');

  rc := EVP_DigestInit(@mdctx, md);
  if rc <> 1 then
    raise Exception.Create('EVP_DigestInit failed: ' + rc.ToString);

  rc := EVP_PKEY_set1_RSA(@key, FRSA);
  if rc <> 1 then
    raise Exception.Create('EVP_PKEY_set1_RSA failed: ' + rc.ToString);

  rc := EVP_DigestSignInit(@mdctx, nil, md, nil, @key);
  if rc <> 1 then
    raise Exception.Create('EVP_DigestSignInit failed: ' + rc.ToString);

  buffer := TEncoding.ANSI.GetBytes(AData);
  rc := EVP_DigestSignUpdate(@mdctx, buffer, Length(buffer));
  if rc <> 1 then
    raise Exception.Create('EVP_DigestSignUpdate failed: ' + rc.ToString);

  rc := EVP_DigestSignFinal(@mdctx, nil, @mdLength);
  if rc <> 1 then
    raise Exception.Create('EVP_DigestFinal failed: ' + rc.ToString);

  SetLength(outbuf, mdLength);
  rc := EVP_DigestSignFinal(@mdctx, PIdAnsiChar(@outbuf[0]), @mdLength);
  if rc <> 1 then
    raise Exception.Create('EVP_DigestFinal failed: ' + rc.ToString);

  Result := TNetEncoding.Base64.EncodeBytesToString(outbuf);
end;

class function TOAuth1SignatureMethod_RSA_SHA1.GetName: string;
begin
  result := 'RSA-SHA1'; // do not localize
end;

initialization
  RegisterClasses([TOAuth1SignatureMethod_RSA_SHA1]);

end.