Results 1 to 1 of 1

Thread: Here's some code for calculating hashes.

Threaded View

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Here's some code for calculating hashes.

    It works with MD2, MD4, MD5, SHA1, SHA2-256, SHA2-384, and SHA2-512. Put the below code in a module (BAS file). It does everything that CAPICOM does regarding hashes, but without using any ActiveX DLL files. It depends entirely on the standard cryptographic API DLL files, using declare statements. There are several publicly accessible functions. These are
    HashBytes
    HashStringA
    HashStringU
    HashArbitraryData
    BytesToHex
    BytesToB64

    HashBytes computes a hash of a 1D byte array, who's lower bound is 0.

    HashStringA computes the hash of an Ascii/Ansi (1 byte per character) string. As VB6 strings are actually Unicode (2 bytes per character), and due to the fact that this function is intended to calculate the hash of the Ascii version of the string, the function first converts VB6's unicode characters to true Ascii characters via VB6's StrConv function. However, because characters with an Ascii value above 127 will differ between locales, the LocaleID is needed to be known for this conversion. As such, LocaleID is a parameter for this function. By default, the LocaleID used by the program is the LocaleID of the PC that the program is running on. This should be used in most situations, as this will generate a hash that will match the output of most other programs that generate a hash (such as the program called Easy Hash).

    HashStringU computes the hash of a Unicode (2 bytes per character) string. As VB6 strings are actually Unicode, there is no conversion needed, and thus is no need to specify LocaleID. Therefore, this function doesn't have a LocaleID parameter. Because each character is defined by 2 bytes, rather than 1, the output of this hash function will obviously differ from the hash calculated by HashStringA, and thus will differ from the hash calculated by most other hash calculating programs (such as the freeware one that I used for testing called Easy Hash). For example, a string with 3 spaces " " is represented as the byte array (shown in hex) 20 00 20 00 20 00 in Unicode encoding, but as 20 20 20 in Ascii encoding. These are 2 distinctly different byte arrays, and thus will produce 2 completely different hashes.
    Side-Note regarding Unicode in VB6: Despite this fact, that internally in VB6 all the strings are Unicode, the implementation of Unicode in VB6 is VERY LIMITED. That is, it won't display any Unicode character that can't also be displayed as an extended ascii character for the computer's current locale. Instead it will show it as a question mark. This won't effect how this function works (or the above function, as it's computing a hash, not displaying anything), but it will effect whether or not a given string will be properly displayed.

    HashArbitraryData computes the hash of absolutely anything. It just needs to know where in memory the first byte of data is, and how many bytes long the data is. It will work with multidimensional byte arrays, arrays of other data types, arrays that start with with a lower bound other than zero, user defined types, sections of memory allocated with API functions, etc. There's nothing that it can't compute the hash of. Of course this gives you the added responsibility of needing to know where exactly in memory the data is, and the size of the data in bytes.

    BytesToHex. This is a function intended to convert the raw bytes output from a hash function to a displayable hexadecimal string.

    BytesToB64. This is a function intended to convert the raw bytes output from a hash function to a displayable base64 string.



    Code:
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
    
    Private Declare Function CryptAcquireContext Lib "advapi32.dll" Alias "CryptAcquireContextA" (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptCreateHash Lib "advapi32.dll" (ByVal hProv As Long, ByVal Algid As Long, ByVal hKey As Long, ByVal dwFlags As Long, ByRef phHash As Long) As Long
    Private Declare Function CryptHashData Lib "advapi32.dll" (ByVal hHash As Long, ByRef pbData As Any, ByVal dwDataLen As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptGetHashParam Lib "advapi32.dll" (ByVal hHash As Long, ByVal dwParam As Long, ByRef pByte As Any, ByRef pdwDataLen As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptDestroyHash Lib "advapi32.dll" (ByVal hHash As Long) As Long
    Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptBinaryToString Lib "Crypt32.dll" Alias "CryptBinaryToStringA" (ByRef pbBinary As Any, ByVal cbBinary As Long, ByVal dwFlags As Long, ByVal pszString As String, ByRef pcchString As Long) As Long
    
    Private Const PROV_RSA_AES As Long = 24
    Private Const CRYPT_VERIFYCONTEXT As Long = &HF0000000
    
    Public Enum HashAlgo
        HALG_MD2 = &H8001&
        HALG_MD4 = &H8002&
        HALG_MD5 = &H8003&
        HALG_SHA1 = &H8004&
        HALG_SHA2_256 = &H800C&
        HALG_SHA2_384 = &H800D&
        HALG_SHA2_512 = &H800E&
    End Enum
    
    Private Const HP_HASHSIZE As Long = &H4&
    Private Const HP_HASHVAL As Long = &H2&
    
    
    Public Function HashBytes(ByRef Data() As Byte, Optional ByVal HashAlgorithm As HashAlgo = HALG_MD5) As Byte()
    Dim hProv As Long
    Dim hHash As Long
    Dim Hash() As Byte
    Dim HashSize As Long
    
    CryptAcquireContext hProv, vbNullString, vbNullString, 24, CRYPT_VERIFYCONTEXT
    CryptCreateHash hProv, HashAlgorithm, 0, 0, hHash
    CryptHashData hHash, Data(0), UBound(Data) + 1, 0
    CryptGetHashParam hHash, HP_HASHSIZE, HashSize, 4, 0
    ReDim Hash(HashSize - 1)
    CryptGetHashParam hHash, HP_HASHVAL, Hash(0), HashSize, 0
    CryptDestroyHash hHash
    CryptReleaseContext hProv, 0
    
    HashBytes = Hash()
    End Function
    
    
    
    Public Function HashStringA(ByVal Text As String, Optional ByVal LocaleID As Long, Optional ByVal HashAlgorithm As HashAlgo = HALG_MD5) As Byte()
    Dim Data() As Byte
    Data() = StrConv(Text, vbFromUnicode, LocaleID)
    HashStringA = HashBytes(Data, HashAlgorithm)
    End Function
    
    Public Function HashStringU(ByVal Text As String, Optional ByVal HashAlgorithm As HashAlgo = HALG_MD5) As Byte()
    Dim Data() As Byte
    Data() = Text
    HashStringU = HashBytes(Data, HashAlgorithm)
    End Function
    
    Public Function HashArbitraryData(ByVal MemAddress As Long, ByVal ByteCount As Long, Optional ByVal HashAlgorithm As HashAlgo = HALG_MD5) As Byte()
    Dim Data() As Byte
    ReDim Data(ByteCount - 1)
    CopyMemory Data(0), ByVal MemAddress, ByteCount
    HashArbitraryData = HashBytes(Data, HashAlgorithm)
    End Function
    
    
    
    
    
    
    Public Function BytesToHex(ByRef Bytes() As Byte) As String
    Dim HexStringLen As Long
    Dim HexString As String
    
    CryptBinaryToString Bytes(0), UBound(Bytes) + 1, 12, vbNullString, HexStringLen
    HexString = String$(HexStringLen, vbNullChar)
    CryptBinaryToString Bytes(0), UBound(Bytes) + 1, 12, HexString, HexStringLen
    
    BytesToHex = UCase$(HexString)
    End Function
    
    Public Function BytesToB64(ByRef Bytes() As Byte) As String
    Dim B64StringLen As Long
    Dim B64String As String
    
    CryptBinaryToString Bytes(0), UBound(Bytes) + 1, 1, vbNullString, B64StringLen
    B64String = String$(B64StringLen, vbNullChar)
    CryptBinaryToString Bytes(0), UBound(Bytes) + 1, 1, B64String, B64StringLen
    
    BytesToB64 = B64String
    End Function
    Last edited by Ben321; May 13th, 2015 at 01:35 AM. Reason: Improved BytesToHex and added BytesToB64

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width