New baby for the CNG family

Windows specific questions.
Post Reply
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

New baby for the CNG family

Post by deltarho[1859] »

I was adding some APIs to WinFBE's keywords list the other day and did not spot something. I don't know why but today the penny dropped. There was mention of BCryptHash. Well, I have been using Windows CNG long enough to know that there is no BCryptHash.

The sequence for hashing is:-

Code: Select all

BCryptOpenAlgorithmProvider
BCryptCreateHash
BCryptHashData
BcryptFinishHash
BCryptDestroyHash
BcryptCloseAlgorithmProvider
The CryptoAPI has a similar sequence except for the first and last statements.

So, I went to MSDN and found BCryptHash.

This is what Microsoft had to say for themselves:
Performs a single hash computation. This is a convenience function that wraps calls to BCryptCreateHash, BCryptHashData, BCryptFinishHash, and BCryptDestroyHash.
So, for a single hash computation it seems that we can use.

Code: Select all

BCryptOpenAlgorithmProvider
BCryptHash
BcryptCloseAlgorithmProvider
So, yes Microsoft it is convenient.

For streaming data from large files we need multiple passes of BCryptHashData so we will still have to use the old method.

At the bottom of the APIs we have 'Requirements'. Flaming Microsoft sneaked it into Windows 10 and did not tell me - one of their CNG fans. They are no longer on my Christmas list. "David". "What?". "They weren't anyway". "Oh yeah, I forgot".

Did anybody here know about this and, if so, why didn't you tell me either? <smile>

Well, needless to say, we will not find BCryptHash in any of the bi files so here is an example of a HMAC and the necessary library load.

I checked the result against SlavaSoft's HashCalc - not that I was questioning Microsoft but I was questioning my libary load - and all is well.

MSDN refers to 'BCRYPT_ALG_HANDLE_HMAC flag'. That should read BCRYPT_ALG_HANDLE_HMAC_FLAG.

Full details here.

Added: I went through the B-Suite and could not find any other sneaky insertions into Windows 10.

Example

Code: Select all

#Include Once "windows.bi"
#Inclib "bcrypt"
#Include Once "win/wincrypt.bi"
#Inclib "crypt32"
 
Dim As Any Ptr library = Dylibload( "BCrypt.dll" )
If library = 0  Then Print "Failed To load BCrypt.dll" : Sleep : End 1
Dim BCryptHash As Function( As BCRYPT_ALG_HANDLE, As Byte Ptr, As Ulong, As Byte Ptr, As Ulong, As Byte Ptr, As Ulong ) As NTSTATUS
BCryptHash = Dylibsymbol( library, "BCryptHash" )
If BCryptHash = 0 Then Print "Could Not retrieve the entry Point of BCryptHash" : Sleep : End 1
 
' Parameters
' 1 hAlgorithm
' 2 pbSecret: Pointer to HMAC key
' 3 cbSecret: Length of pbSecret
' 4 pbInput: Pointer to Data to hash
' 5 cbInput: Length of pbInput
' 6 pbOutput: Pointer to Output buffer
' 7 cbOutput: Length of pbOutput
 
Dim As BCRYPT_ALG_HANDLE Ptr hAlg
Dim As String sHMACKey, sDataToHash
Dim As String*32 sOutput
 
sHMACKey = "Merry Christmas"
sDataToHash = "FreeBASIC"
 
' Only three statements needed. Bit naughty Using 32, above And below, but I almost invariably use SHA256.
BcryptOpenAlgorithmprovider @hAlg, Wstr("SHA256"), 0, BCRYPT_ALG_HANDLE_HMAC_FLAG ' We need hAlg
BCryptHash( hAlg, Strptr(sHMACKEY), Len(sHMACKey), Strptr(sDataToHash), Len(sDaTaToHash), Strptr(sOutPut), 32 )
BcryptCloseAlgorithmprovider hAlg, 0
 
' Convert Output To Hex. I normally stay in Binary mode but I wanted To see what we are getting.
Dim As Dword nlength = Len(sOutPut)*2 + 1 ' Hex length of SHA256 + 1; To accomodate a null terminator
Dim As String shex = Space$( nlength )
' At MSDN nlength 'Out' Is Len(sOutPut) * 2, so
CryptBinaryToString Strptr(sOutPut), Len(sOutPut), CRYPT_STRING_HEXRAW + CRYPT_STRING_NOCRLF, Strptr(shex), @nlength
Print Ucase$( Left$( shex, nlength ) )
 
Sleep
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: New baby for the CNG family

Post by deltarho[1859] »

Just to mention that I tried

Code: Select all

Declare Function BCryptHash Lib "bcrypt.dll" Alias "BCryptHash"( As BCRYPT_ALG_HANDLE, As Ubyte Ptr, _
As Ulong, As Ubyte Ptr, As Ulong, As Byyte Ptr, As Ulong ) As NTSTATUS
and got that very irritating '@': undefined reference to `BCryptHash@28'

I then tried

Code: Select all

Extern "Windows-MS"
Declare Function BCryptHash Lib "bcrypt.dll" Alias "BCryptHash"( As BCRYPT_ALG_HANDLE, As Ubyte Ptr, _
As Ulong, As Ubyte Ptr, As Ulong, As Byyte Ptr, As Ulong ) As NTSTATUS
End Extern
which got rid of the '@' but then got: undefined reference to `BCryptHash'

I noticed that 'Once' was used with the #Inclibs - I had removed them - otherwise no compilation. Weird!
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: New baby for the CNG family

Post by Josep Roca »

> and got that very irritating '@': undefined reference to `BCryptHash@28'

Have you tried to use:

Declare Function BCryptHash Lib "bcrypt.dll" Alias "BCryptHash@28"
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: New baby for the CNG family

Post by deltarho[1859] »

I hadn't but tried it and got more errors than you can shake a stick at, the first one referring to 'error: stray '@' in program' followed by nonsense errors obviously cascading from the first one.

The full test being:

Code: Select all

Declare Function BCryptHash Lib "bcrypt.dll" Alias "BCryptHash@28"( As BCRYPT_ALG_HANDLE, As Byte Ptr, _
As Ulong, As Byte Ptr, As Ulong, As Byte Ptr, As Ulong ) As NTSTATUS
deltarho[1859]
Posts: 4310
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: New baby for the CNG family

Post by deltarho[1859] »

Here is a wrapper of the wrapper for simple hashing; no HMAC.

Only three parameters are used: Hash algorithm, Data to hash and a mode.

The hash algorithm must be uppercase so I covered ourselves by including Ucase in the second parameter of BcryptOpenAlgorithmprovider.

If Mode is False the return is binary else hexadecimal.

The example uses MD5. That is still OK for comparing values like a file download which comes with a digest; most of which are either MD5 or SHA1. SHA256 may be used by some sites but precious few do.

Example ( Don't forget: Win10 only )

Code: Select all

#Include Once "windows.bi"
#Inclib "bcrypt"
#Include Once "win/wincrypt.bi"
#Inclib "crypt32"

Dim As Any Ptr library = Dylibload( "BCrypt.dll" )
If library = 0  Then Print "Failed To load BCrypt.dll" : Sleep : End 1
Dim Shared BCryptHash As Function( As BCRYPT_ALG_HANDLE, As Byte Ptr, As Ulong, As Byte Ptr, As Ulong, As Byte Ptr, As Ulong ) As NTSTATUS
BCryptHash = Dylibsymbol( library, "BCryptHash" )
If BCryptHash = 0 Then Print "Could Not retrieve the entry Point of BCryptHash" : Sleep : End 1

Declare Function HashValue( As String, As String, As Boolean ) As String

Print HashValue( "md5", "FreeBASIC", True )

Sleep

Function HashValue( Alg As String, sDataToHash As String, Mode As Boolean ) As String
' Mode = False => Binary Return, Mode = True => Hex Return
Dim As BCRYPT_ALG_HANDLE Ptr hAlg
Dim As Ulong lhashlength, lresult
	BcryptOpenAlgorithmprovider @hAlg, Ucase(Wstr(Alg)), 0, 0 ' We need hAlg
	BcryptGetProperty( hAlg, bcrypt_hash_length, Cast( Puchar, @lhashlength ), 4, @lresult, 0 )
	Dim As String sOutput = String(lhashlength, 0)
	BCryptHash( hAlg, Null, 0, Strptr(sDataToHash), Len(sDaTaToHash), Strptr(sOutPut), lhashlength )
	BcryptCloseAlgorithmprovider hAlg, 0
	If mode = False Then
		Return sOutPut
	Else
		Dim As Long nlength = 2*lhashlength + 1 ' + 1 To accomodate a null terminator
		Dim As String shex = Space( nlength )
		CryptBinaryToStringa Strptr(sOutPut), Len(sOutPut), crypt_string_hexraw + crypt_string_nocrlf, _
			Strptr(shex), @nlength ' at msdn nlength 'Out' Is 2*lhashlength, so
		Return Ucase$( Left$( shex, nlength ) )
	End If
End Function
Post Reply