MS Crypto API - CryptGetHashParam method

Forums for specific tips, techniques and example code
ChrisClark
Posts: 11
Joined: Tue Apr 20, 2010 8:14 pm

MS Crypto API - CryptGetHashParam method

Postby ChrisClark » Fri Sep 02, 2011 2:09 pm

I've used a couple of posts in the forum to help me understand how to make use of the Windows cryptographic API facility, in particular
https://forums.jadeworld.com/viewtopic.php?f=9&t=1256 and https://forums.jadeworld.com/viewtopic.php?f=11&t=594.

However I'm stuck on trying to get the hash value back using the CryptGetHashParam method. I've looked at the MSDN documentation for the method and example programs, however they are written in C and involve calling the method twice to set memory space up and then retrieving the actual value which I'm not sure is necessary in Jade as well.

The relevant external functions I have are

Code: Select all

cryptGetHashParam(hHash : Integer;dwParam: Integer; pbData : Binary;pdwDataLen : Integer io;dwFlags : Integer):Integer is CryptGetHashParam in advapi32 applicationServerExecution; cryptAcquireContext(phProv : Integer io;pszContainer : String;pszProvider : String;dwProvType : Integer;dwFlags : Integer) : Integer is CryptAcquireContextA in advapi32 applicationServerExecution; cryptCreateHash(hProv : Integer;algid : Integer;hKey : Integer;dwFlags : Integer;phHash : Integer io) : Integer is CryptCreateHash in advapi32 applicationServerExecution; cryptHashData(hHash : Integer;pbData : String;dwDataLen : Integer;dwFlags : Integer) : Integer is CryptHashData in advapi32 applicationServerExecution; cryptDestroyHash(hHash : Integer): Integer is CryptDestroyHash in advapi32 applicationServerExecution; cryptReleaseContext(hProv : Integer;dwFlags : Integer) : Integer is CryptReleaseContext in advapi32 applicationServerExecution;
and where it is being called is

Code: Select all

constants MS_DEF_PROV : String = "Microsoft Base Cryptographic Provider v1.0"; MS_ENHANCED_PROV : String = "Microsoft Enhanced Cryptographic Provider"; MS_STRONG_PROV : String = "Microsoft Strong Cryptographic Provider"; PROV_RSA_FULL : Integer = 1; CRYPT_NEWKEYSET : Integer = 8; CALG_MD5 : Integer = 32771; //ALG_CLASS_HASH.bitOr(ALG_TYPE_ANY).bitOr(ALG_SID_MD5) Key_Length : Integer = 8388608; // 128bit - 0x00800000 vars message: String; hProv : Integer; hHash : Integer; hKey : Integer; tmpBinary: Binary; tmpLength : Integer; container: String; begin message := "Message Body to generate a MD5 hash for"; container := 'Container'; // connect to CSP if call cryptAcquireContext(hProv, container, MS_STRONG_PROV, PROV_RSA_FULL, 0) = 0 then if call cryptAcquireContext(hProv, container, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) = 0 then write "Error during CryptAcquireContext for a new key container."; endif; endif; // create a hash object if call cryptCreateHash(hProv, CALG_MD5, 0, 0, hHash) = 0 then write "Error during CryptCreateHash"; endif; // hash the message if call cryptHashData(hHash, message, message.length, 0) = 0 then write "Error during CryptHashData"; endif; //call cryptGetHashParam(hHash, 4, null, tmpLength, 0); //4 is constant for getting hash size call cryptGetHashParam(hHash, 2, tmpBinary, tmpLength, 0); //2 is constant for getting hash value write tmpLength; write tmpBinary.String; epilog // destroy hash object if hHash <> 0 then call cryptDestroyHash(hHash); endif; // disconnect from CSP if hProv <> 0 then call cryptReleaseContext(hProv, 0); endif; end;
Interestingly the tmpLength comes back as 16 which sounds as though it is the correct value however tmpBinary is empty.

Is anyone able to provide further information around how to use this method please.

Thanks.

murray
Posts: 144
Joined: Fri Aug 14, 2009 6:58 pm
Location: New Plymouth, New Zealand

Re: MS Crypto API - CryptGetHashParam method

Postby murray » Fri Sep 02, 2011 2:35 pm

This is not a direct solution for you, but I have been using calls to the openssl library 'libeay32' (shipped with Jade) to compute hashes.

Code: Select all

sha1(data: Binary; length: Integer; digest: Binary[20] output) is SHA1 in libeay32; md5(data: Binary; length: Integer; digest: Binary[16] output) is MD5 in libeay32;
Murray (N.Z.)

allistar
Posts: 156
Joined: Fri Aug 14, 2009 11:02 am
Location: Mount Maunganui, Tauranga

Re: MS Crypto API - CryptGetHashParam method

Postby allistar » Fri Sep 02, 2011 3:15 pm

Hi Chris,
If you're doing this on a 64bit install of JADE, instead of defining the handles as as Integer, define them as a HANDLE. If it doesn't work, I would recommend writing a single C/C++ external function that calls the MS crypto API instead of making multiple calls from within JADE.

Regards,
Allistar.

torrie
Posts: 92
Joined: Fri Aug 14, 2009 11:24 am

Re: MS Crypto API - CryptGetHashParam method

Postby torrie » Fri Sep 02, 2011 4:17 pm

Hi


When calling external functions, Jade needs to know how much memory to allocate to the output parameters, hence the need to define them as a fixed size.

According to the documentation, the buffer returned is normally 16 or 20 bytes so I would define the cryptGetHashParam external function with at least 20 bytes for the tmpBinary parameter which allows a hash of 16 or 20 bytes to be returned. The code would then be.

Code: Select all

call cryptGetHashParam(hHash, 4, null, tmpLength, 0); //4 is constant for getting hash size if tmpLength <= 20 then // Buffer is large enough call cryptGetHashParam(hHash, 2, tmpBinary, tmpLength, 0); //2 is constant for getting hash value else // Buffer is too small. Cannot get data. endif;
We've sometimes defined multiple functions calling the same external function with different buffer sizes to handle these sorts of cases.

ChrisClark
Posts: 11
Joined: Tue Apr 20, 2010 8:14 pm

Re: MS Crypto API - CryptGetHashParam method

Postby ChrisClark » Fri Sep 02, 2011 7:41 pm

Thanks for all the feedback. It was all helpful. I didn't know about the libeay32 library and that works well. But also was able to get the original method going too - declaring the parameter to the external function as an output Binary of size 20 was the issue.

Code: Select all

cryptGetHashParam(hHash : Integer;dwParam: Integer; pbData : Binary[20] output;pdwDataLen : Integer io;dwFlags : Integer):Integer is CryptGetHashParam in advapi32 applicationServerExecution;
It turned out though, once the external function was correct, that calling the method with 4 (constant to get size) stuffs something up but calling with 2 both times gets the correct size and then after the second call the binary value is populated.

Code: Select all

call cryptGetHashParam(hHash, 2, buffer, tmpLength, 0); write tmpLength; //now 16 and buffer is 20 bytes of nothing call cryptGetHashParam(hHash, 2, buffer, tmpLength, 0); write buffer; //populated with correct hash value (16 bytes long)
(Not using 64 bit Jade)
Appreciate the assistance.

murray
Posts: 144
Joined: Fri Aug 14, 2009 6:58 pm
Location: New Plymouth, New Zealand

Re: MS Crypto API - CryptGetHashParam method

Postby murray » Fri Sep 02, 2011 8:37 pm

An MD5 digest is 16 bytes long. An SHA1 digest is 20 bytes long.
That may be obvious to you. Please excuse me if it is, but I can't quite tell from here.
Murray (N.Z.)


Return to “Tips and Techniques”

Who is online

Users browsing this forum: No registered users and 10 guests

cron