Generating a SHA1 hash

AitorEG
Member Posts: 342
Hi everyoe,
I'm trying to connect with a webService, and I must encode a part of the header with SHA1 encoding. I have an example in .NET, and I'm trying to convert it into C/AL, but I'm receiving an error from the webService. The code in .NET is this:
The value I must include into the header of the HTTP request is "hmac_encode_base64"
This is how I'm trying to generate the hash in NAV:
secret Text
key DotNet System.Array.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
hmac_encode_base64 Text
hmacSHA1 DotNet System.Security.Cryptography.HMACSHA1.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
concat Text
hmac_encode DotNet System.Array.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Afer this try, I realizes that "ComputeHash" method in C# was receiving a MemoryStream. So I change my code to this:
But I'm havieng a "DotNEt type is not compatible" error in the "Instr.READ(ConcatByte);" sentence.
Any hint please?
I'm trying to connect with a webService, and I must encode a part of the header with SHA1 encoding. I have an example in .NET, and I'm trying to convert it into C/AL, but I'm receiving an error from the webService. The code in .NET is this:
byte[] key = Encoding.UTF8.GetBytes(secret); byte[] hmac_encode = Sha1Hash_Raw(concat, key); string hmac_encode_base64 = System.Convert.ToBase64String(hmac_encode); private static byte[] Sha1Hash_Raw(string input, byte[] key) { HMACSHA1 sha1 = new HMACSHA1(key); byte[] byteArray = Encoding.UTF8.GetBytes(input); MemoryStream stream = new MemoryStream(byteArray); return sha1.ComputeHash(stream); }
The value I must include into the header of the HTTP request is "hmac_encode_base64"
This is how I'm trying to generate the hash in NAV:
key := Encoding.UTF8.GetBytes(secret); hmacSHA1 := hmacSHA1.Create; hmacSHA1.Key := key; hmac_encode := hmacSHA1.ComputeHash(Encoding.UTF8.GetBytes(concat)); hmac_encode_base64 := Convert.ToBase64String(hmac_encode);This are the variables:
secret Text
key DotNet System.Array.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
hmac_encode_base64 Text
hmacSHA1 DotNet System.Security.Cryptography.HMACSHA1.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
concat Text
hmac_encode DotNet System.Array.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Afer this try, I realizes that "ComputeHash" method in C# was receiving a MemoryStream. So I change my code to this:
key := Encoding.UTF8.GetBytes(secret); hmacSHA1 := hmacSHA1.Create; hmacSHA1.Key := key; ConcatByte := Encoding.UTF8.GetBytes(concat); Instr.READ(ConcatByte); COPYSTREAM(MemoryStream,Instr); hmac_encode := hmacSHA1.ComputeHash(MemoryStream); hmac_encode_base64 := Convert.ToBase64String(hmac_encode);
But I'm havieng a "DotNEt type is not compatible" error in the "Instr.READ(ConcatByte);" sentence.
Any hint please?
0
Answers
-
There are ready-made functions in D365BC which can be easily copied to NAV 2016 or higher (tested). You may be able to downgrade them further, but I haven't tested that.
Look for functions GenerateHash/GenerateKeyedHash in codeunit 1266 Encryption Management, I found them useful.
Note that GenerateKeyedHash works fine when generating just one hash from secret key.
If you need to loop the hash generation (e.g. as required by AWS), the Bytes value must not be converted to String between the steps.
To handle this I ended up writing my own function:PROCEDURE GenerateKeyedHashLooped@1000000007(DateStamp@1000 : Text;RegionName@1000000000 : Text;ServiceName@1000000001 : Text;Terminator@1000000002 : Text;BodyToSign@1000000007 : Text;Key@1005 : Text;HashAlgorithmType@1001 : 'HMACMD5,HMACSHA1,HMACSHA256,HMACSHA384,HMACSHA512') : Text; VAR Encoding@1002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Text.Encoding"; DateHashBytes@1000000003 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; RegionHashBytes@1000000004 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; ServiceHashBytes@1000000005 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; TerminatorHashBytes@1000000006 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; FinalHashBytes@1000000008 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; BEGIN GenerateKeyedHashBytes(DateHashBytes,DateStamp,Encoding.UTF8.GetBytes(Key),HashAlgorithmType); GenerateKeyedHashBytes(RegionHashBytes,RegionName,DateHashBytes,HashAlgorithmType); GenerateKeyedHashBytes(ServiceHashBytes,ServiceName,RegionHashBytes,HashAlgorithmType); GenerateKeyedHashBytes(TerminatorHashBytes,Terminator,ServiceHashBytes,HashAlgorithmType); GenerateKeyedHashBytes(FinalHashBytes,BodyToSign,TerminatorHashBytes,HashAlgorithmType); EXIT(ConvertByteHashToString(FinalHashBytes)); END;
0 -
jurica_bogunovic wrote: »There are ready-made functions in D365BC which can be easily copied to NAV 2016 or higher (tested). You may be able to downgrade them further, but I haven't tested that.
Look for functions GenerateHash/GenerateKeyedHash in codeunit 1266 Encryption Management, I found them useful.
Note that GenerateKeyedHash works fine when generating just one hash from secret key.
If you need to loop the hash generation (e.g. as required by AWS), the Bytes value must not be converted to String between the steps.
To handle this I ended up writing my own function:PROCEDURE GenerateKeyedHashLooped@1000000007(DateStamp@1000 : Text;RegionName@1000000000 : Text;ServiceName@1000000001 : Text;Terminator@1000000002 : Text;BodyToSign@1000000007 : Text;Key@1005 : Text;HashAlgorithmType@1001 : 'HMACMD5,HMACSHA1,HMACSHA256,HMACSHA384,HMACSHA512') : Text; VAR Encoding@1002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Text.Encoding"; DateHashBytes@1000000003 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; RegionHashBytes@1000000004 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; ServiceHashBytes@1000000005 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; TerminatorHashBytes@1000000006 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; FinalHashBytes@1000000008 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; BEGIN GenerateKeyedHashBytes(DateHashBytes,DateStamp,Encoding.UTF8.GetBytes(Key),HashAlgorithmType); GenerateKeyedHashBytes(RegionHashBytes,RegionName,DateHashBytes,HashAlgorithmType); GenerateKeyedHashBytes(ServiceHashBytes,ServiceName,RegionHashBytes,HashAlgorithmType); GenerateKeyedHashBytes(TerminatorHashBytes,Terminator,ServiceHashBytes,HashAlgorithmType); GenerateKeyedHashBytes(FinalHashBytes,BodyToSign,TerminatorHashBytes,HashAlgorithmType); EXIT(ConvertByteHashToString(FinalHashBytes)); END;
First of all, thnaks for your answer jurica.
I've read that this was easier as you said in BC365, but I didn't understand well. I've copied from the 1266 CU to my CU the methods GenerateKeyedHashBytes and TryGenerateKeyedHash, and I changed my code in this way:key := Encoding.UTF8.GetBytes(secret); //hmacSHA1 := hmacSHA1.Create; //hmacSHA1.Key := key; //hmac_encode := hmacSHA1.ComputeHash(Encoding.UTF8.GetBytes(concat)); TryGenerateKeyedHash(hmac_encode,concat,key,'HMACSHA1'); hmac_encode_base64 := Convert.ToBase64String(hmac_encode);
But I get the same value in "hmac_encode_base64". Am I loosing something? Our somethin that I'm using wrong?
THnak you very much again, really appreciate your help0 -
Hello @AitorEG ,
You can use the codeunit 1266 from NAV2018, there is this function that return the base64 already, you could need the table 1805
Regards
Muchas gracias!
I've used the function you hace told me, but aniway, the result it's being the same. I'm starting to think that the problem is in other field of the request header, but that is not the answer I'm receiveing from the aplication support...0 -
Hi @ftornero
As you can see in my frist message, I have an example in C# that I must translate it into C A/L.
My first try was this:key := Encoding.UTF8.GetBytes(secret); hmacSHA1 := hmacSHA1.Create; hmacSHA1.Key := key; hmac_encode := hmacSHA1.ComputeHash(Encoding.UTF8.GetBytes(concat)); hmac_encode_base64 := Convert.ToBase64String(hmac_encode);
And after the discover of the 1266 Cu in BC, I'eve done this:key := Encoding.UTF8.GetBytes(secret); TryGenerateKeyedHash(hmac_encode,concat,key,'HMACSHA1'); hmac_encode_base64 := Convert.ToBase64String(hmac_encode);
And weith the function you've shown me:hmac_encode_base64 := GenerateKeyedHashAsBase64String(concat,secret,1);
In all the cases, I ahve the same value into hmac_encode_base64 , but they are etlling me that it is incorrect...
0 -
Hello @AitorEG ,
Then I think that should be other issue in the call to the web service, because the last function that you are using give back the encrypted value
You can run this example in Pythonimport hmac from hashlib import sha1 def hmac_encrypt(key, msg): return hmac.HMAC(key, msg, sha1) if __name__ == "__main__": h = hmac_encrypt(b"Jefe", b"what do ya want for nothing?") print(h.hexdigest()) # effcdf6ae5eb2fa2d27416d5f184df9c259a7c79
And do the same in NAV and you get the same result.MESSAGE(CU1266.GenerateKeyedHash('what do ya want for nothing?', 'Jefe', 1));
It's not in base64 but does not matter.
Regards0 -
Hello @AitorEG ,
Then I think that should be other issue in the call to the web service, because the last function that you are using give back the encrypted value
You can run this example in Pythonimport hmac from hashlib import sha1 def hmac_encrypt(key, msg): return hmac.HMAC(key, msg, sha1) if __name__ == "__main__": h = hmac_encrypt(b"Jefe", b"what do ya want for nothing?") print(h.hexdigest()) # effcdf6ae5eb2fa2d27416d5f184df9c259a7c79
And do the same in NAV and you get the same result.MESSAGE(CU1266.GenerateKeyedHash('what do ya want for nothing?', 'Jefe', 1));
It's not in base64 but does not matter.
Regards
That is what I think, ansd I'm trying to find or demostrate that the error is in another variable....
Thank you anyway, really appreciate.
Gracias!!0 -
Hi everyone,
I'm still having problems, so I will try to start from the beginnig, checking the different steps. My first goal is to get the MD5 hash of a string.
In C# is this part of the code:byte[] md5 = Md5Hash_Raw(json); string md5_base64 = System.Convert.ToBase64String(md5);
And I'm trying to convert into CA/L like this:MD5 := MD5.Create; Hash := MD5.ComputeHash(Encoding.UTF8.GetBytes(JsonString)); md5_base64 := Convert.ToBase64String(Hash);
variables:
JsonString BigText
Hash DotNet System.Array.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
md5_base64 Text
MD5 DotNet System.Security.Cryptography.MD5.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
From support they are giving me a valuea for md5_base64 different to the one I'm getting...
Am I loosing something?
Thank you very much0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions