How to hash a string using RSA-SHA1?

How to hash a string using RSA-SHA1?

Delphi supports HMAC-SHA1 through TRESTHTTPProcs.HashHMACSHA1(). Is there a similar function for RSA-SHA1?

Comments

  1. Finally got it working. Add this unit to your project and add 'OAuth1SignatureMethod_RSA_SHA1' to the uses. Then set TOAuth1Authenticator.SigningClassName to '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);

    EVP_Cleanup();

    SetLength(outbuf, mdLength);
    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.

    ReplyDelete

Post a Comment