Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams IdGlobal, IdHashSHA, IdHMAC, IdHMACSHA1, IdSSLOpenSSL; function CalculateHMACSHA256(const value, salt: String): String; hmac: TIdHMACSHA256; hash: TIdBytes; begin LoadOpenSSLLibrary; if not TIdHashSHA256.IsAvailable then raise Exception.Create('SHA256 hashing is not available!'); hmac := TIdHMACSHA256.Create; hmac.Key := IndyTextEncoding_UTF8.GetBytes(salt); hash := hmac.HashValue(IndyTextEncoding_UTF8.GetBytes(value)); Result := ToHex(hash); finally hmac.Free; Be sure to call "IdOpenSSLSetLibPath(yourlibeaypathhere);" as well, as loadOpenSSLLibrary may not be able to find the required dll otherwise. T.S Dec 11, 2019 at 12:33 @T.S that is only necessary if the OpenSSL binaries are not in the same folder as your app executable Remy Lebeau Dec 11, 2019 at 13:07 @BrianOrion GetHMACAsBytes() returns a TBytes , which is an alias for array of Byte . TIdBytes is also an alias for array of Byte . The two types are distinct and not assignment compatible , but they are identical in memory layout, so you can typecast between them before assigning. There will be no data loss. Remy Lebeau Nov 3, 2022 at 14:42

After a little more searching I found OpenStreamSec - which looks like it was abandoned a few years ago but still compiles in D2007.

http://sourceforge.net/projects/openstrsecii/

Generating a HMAC-256 for Amazon is really simple:

StrToMime64(HMACString(haSHA256, SecretKey, 32, DataToHash));
                I got this work, but find I need to truncate some characters to get a proper signature.  For example, here is a signature I get: "t1mYmkG73To5eyukq1lbDrBYGPcAAAAAAAAAAAAAAAA=".  But it is actually that without the "A": t1mYmkG73To5eyukq1lbDrBYGPc=.  Is there a setting I need to change?  If I change the "32" parameter that does not seem to change things.
– M Schenkel
                Apr 6, 2012 at 2:05

My favourite answer - I would use the OpenSSL libraries, the HMAC function. I've successfully used the OpenSSL libraries in Delphi by adopting and adapting work from M Ferrante http://www.disi.unige.it/person/FerranteM/delphiopenssl/
For other OpenSSL signing etc see this link In D2010 it's something like this (libeay32 is the unit taken from the web site and slightly modified for unicode/D2010):

uses libeay32;
const
  LIBEAY_DLL_NAME = 'libeay32.dll';
  EVP_MAX_MD_SIZE = 64;
function EVP_sha256: pEVP_MD; cdecl; external LIBEAY_DLL_NAME;
function HMAC(evp: pEVP_MD; key: PByte; key_len: integer; 
              data: PByte; data_len: integer; 
              md: PByte; var md_len: integer): PByte; cdecl; external LIBEAY_DLL_NAME;
function GetHMAC(const AKey, AData: string): TBytes;
  key, data: TBytes;
  md_len: integer;
  res: PByte;
begin
  OpenSSL_add_all_algorithms;
  // Seed the pseudo-random number generator
  // This should be something a little more "random"!
  RAND_load_file('c:\windows\paint.exe', 512);
  key := TEncoding.UTF8.GetBytes(AKey);
  data := TEncoding.UTF8.GetBytes(AData);
  md_len := EVP_MAX_MD_SIZE;
  SetLength(result, md_len);
  res := HMAC(EVP_sha256, @key[0], Length(key), @data[0], Length(data), @result[0], md_len);
  if (res <> nil) then
  begin
    SetLength(result, md_len);

Then call it with a key phrase and data string. The result is a TBytes which can be converted as required eg to Base64 using something like JclMime or a simple HexToString type function.
For older version of Delphi you'll have to do a bit of changing of PBytes to PChars or something similar.
Disclaimer: I've got no reference data to test this on but it seems to work ok!

HMAC is just a function that uses SHA256 to calculate a hash according to some defined rules. If you look at Wikipedia it has a pseudocode example.

You could also call into .NET's HMAC Class in System.Security.Cryptography via COM interrop.

When searching the web I also found this, compiling correctly under Delphi10:

result:= (TNetEncoding.Base64.EncodeBytesToString(THashSHA2.GetHMACAsBytes(TEncoding.UTF8.GetBytes(StringToSign),TNetEncoding.Base64.DecodeStringToBytes(Key))));

Though I do have troubles in the ongoing process - not sure if it is related to this function..

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center. – Community Jan 14, 2022 at 21:42

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.