EldoS | Feel safer!

Software components for data protection, secure storage and transfer

HMAC SHA256 Hash

Also by EldoS: Rethync
The cross-platform framework that simplifies synchronizing data between mobile and desktop applications and servers and cloud storages
#29685
Posted: 06/04/2014 13:28:36
by Tommy Wu (Basic support level)
Joined: 06/04/2014
Posts: 4

Hi, I have a function that takes a value and a hex key and I need to hash it and convert it to base64 string for the authentication header of a RESTful webservice call. I don't get an error but the results do not match what I wrote in my C# sample (using .NET's HMACSHA256 function). Do you guys see anything wrong with my code below? (note: using the TElHashFunction without a key I am able to do a 'regular' sha256 hash and the results I get are as expected). Any help would be greatly appreciated.

function GetHMAC(SecretStr: string; ValueStr: string): string;
var
elKey: TElHMACKeyMaterial;
elHasher: TElHashFunction;
valueByte, hashByte: TBytes;
hashBuf: RawByteString;
begin
elKey := TElHMACKeyMaterial.Create();
try
elKey.Key := ByteArray(SecretStr);
elHasher := TElHashFunction.Create(SB_ALGORITHM_MAC_HMACSHA256, elKey);
try
valueByte := TEncoding.UTF8.GetBytes(ValueStr);
elHasher.Update(@valueByte[0], Length(valueByte) * SizeOf(valueByte[0]));
hashBuf := elHasher.Finish();
hashByte := BytesOf(hashBuf);
//convert to TIdBytes and use the TIdBytes to convert to base64 string
Result := TIdEncoderMIME.EncodeBytes(TIdBytes(hashByte));
finally
FreeAndNil(elHasher);
end;
finally
FreeAndNil(elKey);
end;
end;
#29686
Posted: 06/04/2014 13:46:03
by Eugene Mayevski (EldoS Corp.)

First thing to check is the conversion of SecretStr to the byte array. If you have only ASCII in SecretStr, then you can use SBUtils.BytesOfString() function to get ASCII bytes. If you have anything more complex, you need to perform proper conversion.

Use of hashBuf is also questionable.

You don't need Indy for Base64 encoding - use SBEncoding.Base64EncodeString or SBEncoding.Base64EncodeArray function.


Sincerely yours
Eugene Mayevski
#29687
Posted: 06/04/2014 15:40:17
by Tommy Wu (Basic support level)
Joined: 06/04/2014
Posts: 4

Hi Eugene, thank you for your quick reply...


Quote
Eugene Mayevski wrote:
If you have only ASCII in SecretStr, then you can use SBUtils.BytesOfString() function to get ASCII bytes.


Is there a way to convert to utf8 bytes?

*I tried this... SBTypes.ByteArray(TEncoding.UTF8.GetBytes(SecretStr));

but it didn't help

Quote
Eugene Mayevski wrote:
Use of hashBuf is also questionable.


I just need to convert the end result of the hash to a base64 string.. so do you know if there's a better way to get it from RawByteString(the result of TElHashFunction.Finish) to base64 string?

Quote
Eugene Mayevski wrote:
You don't need Indy for Base64 encoding - use SBEncoding.Base64EncodeString or SBEncoding.Base64EncodeArray function.


I couldn't figure out how to convert from TBytes to ByteArray.
#29688
Posted: 06/04/2014 16:32:19
by Mykola Olshevsky (Basic support level)
Joined: 07/07/2005
Posts: 450

Hi. Also please note that TElHMACKeyMaterial expects key in raw binary, so if it is hex-encoded in SecretStr you should first hex-decode it.
#29689
Posted: 06/04/2014 16:42:40
by Tommy Wu (Basic support level)
Joined: 06/04/2014
Posts: 4

Quote
Mykola Olshevsky wrote:
Hi. Also please note that TElHMACKeyMaterial expects key in raw binary, so if it is hex-encoded in SecretStr you should first hex-decode it.


yes, thanks, i tried with both a hex and an non-hex key (decoding the hex key) and it did not match what i produced using the .net libs.

fyi.. this works, only thing is it's not hmac it's just reg. sha256.

function StringToSha256(inputString: string): string;
var
elFunction : TElHashFunction;
hashByte: TBytes;
hashBuff: RawByteString;
begin
try
elFunction := TElHashFunction.Create(SB_ALGORITHM_DGST_SHA256);
hashByte := TEncoding.UTF8.GetBytes(inputString);
elFunction.Update(@hashByte[0], Length(hashByte) * SizeOf(hashByte[0]));
hashBuff := elFunction.Finish();
Result := TIdEncoderMIME.EncodeBytes(TIdBytes(hashBuff));
except
on E : Exception do
begin
Result := E.Message;
end;
end;
end;
#29690
Posted: 06/04/2014 17:42:57
by Tommy Wu (Basic support level)
Joined: 06/04/2014
Posts: 4

Hi All, I think I got it... code below, I still don't have everything working cause the real input value has return carriages in them but when i encode a "regular string" the results are as expected. Thanks again for your help.

Code
function GetHMAC(SecretStr: string; ValueStr: string): string;
var
  elKey: TElHMACKeyMaterial;
  elHasher: TElHashFunction;
  valueByte: TBytes;
  hashBuff: RawByteString;
begin
  elKey := TElHMACKeyMaterial.Create();
  try
    elKey.Key := SBTypes.ByteArray(TEncoding.UTF8.GetBytes(SecretStr));
    elHasher := TElHashFunction.Create(SB_ALGORITHM_MAC_HMACSHA256, elKey);
    try
      valueByte := TEncoding.UTF8.GetBytes(ValueStr);
      elHasher.Update(@valueByte[0], Length(valueByte) * SizeOf(valueByte[0]));
      hashBuff := elHasher.Finish();
      Result := TIdEncoderMIME.EncodeBytes(TIdBytes(hashBuff));
    finally
      FreeAndNil(elHasher);
    end;
  finally
    FreeAndNil(elKey);
  end;
end;
Also by EldoS: BizCrypto
Components for BizTalk® and SQL Server® Integration Services that let you securely store and transfer information in your business automation solutions.

Reply

Statistics

Topic viewed 1973 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!