There are times when one needs to add to an existing hash, such as when calculating the HMAC hashes for TLS. With CAPI, the hash function could be easily split into separate functions; create the hash, add to the hash, and finish the hash. All you had to do was save the Hash Handle. Using CNG, it is a little more involved.
CNG uses objects extensively, and although the Hash Handle is the only element required for the BCryptFinishHash function, it is useless without the Hash Object. In the attached test program, the Hash Handle, the Hash Length, and the Hash Object are saved by the calling function. In reality, the Hash Object is the only thing that needs to be preserved, because the other two values are both contained within:
Thanks for this bit of code, I found it interesting and helpful. I've been working out how to get CNG working from within VB6 for hashing large files and being able to add to a hash is of course important in this context.
I do have a question: In the "DisplayHex" sub there are two comment lines at the top that say, "Some ANSI characters in the range &H80 to &H9F get converted to Unicode." and, "This routine flags those characters with an Asterisk "*" following the byte."
I'm afraid I don't understand why these need to be flagged. Do characters returned as unicode invalidate the returned hex values thus meaning the returned hash is invalid? Is there some other reason they need to be flagged?
Thanks again for the snippet of code, it was very helpful in understanding the process to add to hashes with CNG.
Thanks for this bit of code, I found it interesting and helpful. I've been working out how to get CNG working from within VB6 for hashing large files and being able to add to a hash is of course important in this context.
I do have a question: In the "DisplayHex" sub there are two comment lines at the top that say, "Some ANSI characters in the range &H80 to &H9F get converted to Unicode." and, "This routine flags those characters with an Asterisk "*" following the byte."
I'm afraid I don't understand why these need to be flagged. Do characters returned as unicode invalidate the returned hex values thus meaning the returned hash is invalid? Is there some other reason they need to be flagged?
Thanks again for the snippet of code, it was very helpful in understanding the process to add to hashes with CNG.
This is quite an old post, and I had to download it to answer your question. I believe that this particular program was written to handle latin characters only. The StrToByte routine will not handle non-latin characters such as Chinese or Arabic. The characters &H80 to &H9F are Extended Latin characters which are considered Unicode characters, and have been known to cause problems. In this particular context, they would probably not be an issue. These days I use the following to convert Unicode string characters to byte array, including ASCII characters.
J.A. Coutts
Code:
Option Explicit
Private Const CP_UTF8 = 65001
Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, ByVal lpMultiByteStr As Long, ByVal cbMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
Private Function GetbSize(bArray() As Byte) As Long
On Error GoTo GetSizeErr
GetbSize = UBound(bArray) + 1
Exit Function
GetSizeErr:
GetbSize = 0
End Function
Public Function StrToUtf8(strInput As String) As Byte()
Dim nBytes As Long
Dim abBuffer() As Byte
If Len(strInput) < 1 Then Exit Function
' Get length in bytes *including* terminating null
nBytes = WideCharToMultiByte(CP_UTF8, 0&, ByVal StrPtr(strInput), -1, 0&, 0&, 0&, 0&)
' We don't want the terminating null in our byte array, so ask for `nBytes-1` bytes
ReDim abBuffer(nBytes - 2) ' NB ReDim with one less byte than you need
nBytes = WideCharToMultiByte(CP_UTF8, 0&, ByVal StrPtr(strInput), -1, ByVal VarPtr(abBuffer(0)), nBytes - 1, 0&, 0&)
StrToUtf8 = abBuffer
End Function
Public Function Utf8ToStr(abUtf8Array() As Byte) As String
Dim nBytes As Long
Dim nChars As Long
Dim strOut As String
' Catch uninitialized input array
nBytes = GetbSize(abUtf8Array)
If nBytes <= 0 Then Exit Function
' Get number of characters in output string
nChars = MultiByteToWideChar(CP_UTF8, 0&, VarPtr(abUtf8Array(0)), nBytes, 0&, 0&)
' Dimension output buffer to receive string
strOut = String(nChars, 0)
nChars = MultiByteToWideChar(CP_UTF8, 0&, VarPtr(abUtf8Array(0)), nBytes, StrPtr(strOut), nChars)
Utf8ToStr = Replace(strOut, Chr$(0), "") 'Remove Null terminating characters
End Function
Last edited by couttsj; Dec 6th, 2021 at 12:05 AM.