-1

My project needs to connect the Azure Cosmo DB by REST API. The Azure Cosmo DB connection requires to pass a HMACSHA256 signature to the HTTP header. I tried to use THashSHA2.GetHMAC(Data, Key) function in Delphi 10.2 to get this signature. In order to verify the result, I run the sample code in C# (downloaded from MS) to verify the result generated by Delphi. Unfortunately, they are not the same! C# : 2LuKbSl8RkLc0eKhjQv4oCpXzRcmR02L9sDfSxSB5HA= Delphi: 2ca409c9a26aa3ed6c772b6bda5bbe66bcd0d929c3ca4359f19ea42314437e5a I verify the Delphi result by the online HMACSHA256 generator. Delphi is correct.

I searched over the web to find another way to generate the signature. I got TIdHMACSHA256 (using IdSSLOpenSSL.LoadOpenSSLLibrary). I tried the code but also no luck. The result (96OyCOmXzODAP9CljJgleuG5J5c4nIDeiSlr3hdcpYY=) is also not the same as the one generated by C#.

I noticed that C# code run Convert.FromBase64String(key) to convert the key to byte, generate the hash and then Convert.ToBase64String(hashPayLoad) to signature. I suspect the wrong result in Delphi is missing this kind of steps. But I do not know how to do it.

Do anyone have experience generating Azure Cosmo DB signature by Delphi? Please help!

huysmania
  • 1,054
  • 5
  • 11
  • You have misspelled "Cosmos", neglected to mention whether *any* of those results actually work, and not shown what you're actually including to generate the hash – Dave Nottage May 08 '18 at 03:58
  • Have you seen [this question](https://stackoverflow.com/q/2003194/8041231)? – Victoria May 08 '18 at 05:41
  • Sorry for my typo. I'm new to stackoverflow. I can't find any edit link to update my question. I've used two procedures that I find on the web to hash the signature. – Leo Lui May 08 '18 at 11:40
  • The first one function GenerateSignature(const AData, AKey: string): string; var AHMAC: TIdBytes; bytes: TBytes; begin IdSSLOpenSSL.LoadOpenSSLLibrary; if not TIdHashSHA256.IsAvailable then ...; with TIdHMACSHA256.Create do Key := IndyTextEncoding_UTF8.GetBytes(AKey); AHMAC := HashValue(IndyTextEncoding_UTF8.GetBytes(AData)); ..... result := TNetEncoding.Base64.Encode(AHMAC); end; The second one result:= THashSHA2.GetHMAC(ACode, AKey); None of them produce the same result as C# – Leo Lui May 08 '18 at 12:02
  • I'm sorry that I do not know how to add a line feed to my above code. – Leo Lui May 08 '18 at 12:04

2 Answers2

0

After searching all possible websites and a lot of trial and error, I get the solution finally. The result is same as the signature generated from C#. The code was modified from "https://www.delphipraxis.net/190563-dxe7-indy-hmac-sha256-encoding.html"

function GenerateCosmosDBSignature(const AData, AKey: string): string; var AHMAC: TIdBytes; bytes: TBytes;

begin

IdSSLOpenSSL.LoadOpenSSLLibrary;

if not TIdHashSHA256.IsAvailable then

raise Exception.Create('SHA-256 hashing is not available!');

with TIdHMACSHA256.Create do

try

//original
//Key := IndyTextEncoding_UTF8.GetBytes(AKey);
//AHMAC := HashValue(IndyTextEncoding_UTF8.GetBytes(AData));

//after modified
Key := TIdBytes(TNetEncoding.Base64.DecodeStringToBytes(AKey));
AHMAC := HashValue(IndyTextEncoding_UTF8.GetBytes(AData));

finally

Free;

end;

//original

//result := TIdEncoderMIME.EncodeBytes(AHMAC);

//after modified

result:= AnsiString(TNetEncoding.Base64.EncodeBytesToString(System.TArray(AHMAC)));

end;

0

Another way to get the Cosmos DB signature by using Delphi System.Hash

function GenerateCosmosDBSignature(const AData, AKey: string): string; var keyBytes, dataBytes: TBytes;

begin

keyBytes:=TNetEncoding.Base64.DecodeStringToBytes(AKey); dataBytes:=TEncoding.UTF8.GetBytes(AData);

result:= AnsiString(TNetEncoding.Base64.EncodeBytesToString(THashSHA2.GetHMACAsBytes(dataBytes, keyBytes)));

end;