AWS Signature 4 API Calls - BC Online

Hi all,

This question is for latest BC cloud implementation.

Has anyone had experience with calling an AWS API which requires a signing key for Signature 4 without using a .net dll?

It needs to use an algorithm of HMACSHA256. Which is fine, as it is possible to do this via the GenerateHash function within the Cryptography Management codeunit. However, it looks like due to the way it returns a text string it causes an issue when you need to reuse the return as a key to your next hash request.

For AWS you creating a signing key via the following (HMAC function param. is (Key, Value):

kSecret = your secret access key
kDate = HMAC(“AWS4” + kSecret, Date)
kRegion = HMAC(kDate, Region)
kService = HMAC(kRegion, Service)
kSigning = HMAC(kService, “aws4_request”)

I have translated this in BC code as follows:

KDate := CryptographyManagement.GenerateHash(SignDate, Secret, HashAlgorithmType::HMACSHA256);
KRegion := CryptographyManagement.GenerateHash(Region, KDate, HashAlgorithmType::HMACSHA256);
KService := CryptographyManagement.GenerateHash(Service, KRegion, HashAlgorithmType::HMACSHA256);
KSigning := CryptographyManagement.GenerateHash(Signing, KService, HashAlgorithmType::HMACSHA256);

KDates gets the right return result, but this has been converted into a string rather than the Byte array required in the next call. When I call the next function to get “KRegion”, I get the incorrect result.

The AWS example is for the following data:

Secret = ‘AWS4’ + ‘wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY’
Date = ‘20120215’
Region = ‘us-east-1’
Service name= ‘iam’

KDate should return “969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d”, which is does, so I thought it would be all working.

However, when you call the next it does not match, it should return ‘69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c’.

In C# this works as expected, but this does not convert the result its return back when doing the next hash algorithm. So it could work if could call the correct .net library, but the mains one that “Generatehash” uses are not available on cloud version.

I’m starting to think an azure function will be required, but if anyone has any experience with this that would be of great help!

Thanks in advance!

Hi Jon,
Hope you are doing good.
I am facing the same issue. Did you find any solution to this?

Thanks

It seems like you are trying to call an AWS API that requires a signing key for Signature 4 in Microsoft Dynamics 365 Business Central cloud implementation. You are facing an issue where the return from Cryptography Management codeunit’s GenerateHash function is in text format, which causes problems when you try to reuse it as a key for your next hash request.

One possible solution to this issue could be to convert the text string returned by GenerateHash function into a byte array using the Convert.FromBase64String method. This would ensure that the correct result is returned when you call the next function to get KRegion.

Here is an example of how you can modify your code to convert the text string to a byte array:

KDateText := CryptographyManagement.GenerateHash(SignDate, Secret, HashAlgorithmType::HMACSHA256);
KDateByteArray := Convert.FromBase64String(KDateText);

KRegionText := CryptographyManagement.GenerateHash(Region, KDateByteArray, HashAlgorithmType::HMACSHA256);
KRegionByteArray := Convert.FromBase64String(KRegionText);

KServiceText := CryptographyManagement.GenerateHash(Service, KRegionByteArray, HashAlgorithmType::HMACSHA256);
KServiceByteArray := Convert.FromBase64String(KServiceText);

KSigningText := CryptographyManagement.GenerateHash(Signing, KServiceByteArray, HashAlgorithmType::HMACSHA256);

This should ensure that the correct byte array is passed as a key to the next hash request. I hope this helps!

Hey Any one get solution to this? i am also stuck here , Regards

I would try lowercasing the hex that is returned by the BC Cryptography Management procedure, for some reason it returns it in all caps which would cause an issue with the next hash.

Hi, I’m calling an AWS API which requires a signing key for Signature 4 on cloud.

Everything seems to be fine but when I add the Authorization token I have composed as a header, I get the error: “the format of value ‘XXXX’ is invalid”, any idea what can be happening?

Even if I paste a right Authorization Header that works on Postman, I get the same error. With a blank header also gets the error.

I add the headers like that:

Request.GetHeaders(Headers);
        Headers.Clear();
        Headers.Add('Accept', '*/*');
        Headers.Add('Accept-Encoding', 'gzip, deflate, br');
        Headers.Add('User-Agent', 'Dynamics 365');
        Headers.Add('Connection', 'keep-alive');
        Headers.Add('X-Amz-Date', dateformat);
        Headers.Add('x-api-key', xapikey);
        Headers.Add('Authorization', Authorization);
        //Headers.TryAddWithoutValidation('Authorization', Authorization);
        Request.SetRequestUri(URL);
        Request.Method := 'GET';

Authorization is a Text variable with AWS Signing 4 syntax.

If I use the TryAddWithoutValidation method, it works but I get a 403 error like no sending Authorization.

Thanks

Format invalid was about date format not in UTC ISO 8601, and seems that TryAddWithoutValidation is ok to add the Authorization Header.

Now I’m facing the original problem of having a hex key in text format, and when it’s reused returns a wrong hash value.

Did someone find any solution to this?

Thanks!

Hi Daniel,

In the end i created an Azure Function to create the key for me, then sent the request from BC.

It was quite straight forward c# code to accomplish this, though it was a few years ago I wrote this!

Thanks.

1 Like