# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  [VB6] CryptoAPI MD5 Hash

## dilettante

The attached project is a simple demonstration of using the Windows Crypto functions to create a hash.  The example produces an MD5 hash of a file or a typed in string and returns it in hex.

It could easily be modified to return a Byte array of the hash, and could also easily perform an SHA1, etc. hash instead of MD5.

This can also be done easily via CAPICOM, which is a COM wrapper for the API calls used here.  You can download CAPICOM from Microsoft if you don't have it installed, but this program doesn't use or require it.

There is some confusion around the use of these Crypto functions on Win9X.  The documentation says Win95 OSR2 or later.  Other people suggest you must have a recent version of the UnicoWS.dll installed first.

"Your mileage may vary."  :Wink:

----------


## Taco

Thanks, I found this code very useful.

----------


## tanaya

nice code.useful

----------


## mustiback

this is very useful.

----------


## MarKoxX

Where can I use this code? Can I use it on a Commercial App? Is it under GPL licence?

----------


## dilettante

No license at all, consider it public domain.

----------


## buckwheat

Thank you for posting this, I was able to import this into an Access 2007 VBA application I have that signs webservice request for Flickr, had to make one minor adjustment to get it to calculate MD5 hash correct (since it didn't match what i had been using and fails) - 

  in HashBlock()  should not add + 1 to the the length because the Lbound()  is already starting with 0

Private Sub HashBlock(ByRef Block() As Byte)
'Attribute HashBlock.VB_Description = "Hash a block of data"
    If CryptHashData(m_hHash, _
                     Block(LBound(Block)), _
                     UBound(Block) - LBound(Block) *+ 0*, _
                     0&) = 0 Then
        Err.Raise vbObjectError Or &HC312&, _
                  "MD5Hash", _
                  "Failed to hash data block, system error " _
                & CStr(Err.LastDllError)
    End If
End Sub

----------


## Deliriumxx

I have a quick question.. I can see how to easily encrypt a string but is there a way to decrypt the string with this?

----------


## chacke

It is Hash. One way encryption. 
you should not use it to encrypt.

----------


## Deliriumxx

I figured out what I needed. And I didn't ask if I should do it or not. I asked how is that supposed to be done. 

The point of my particular question was how do I decrypt a string once it is encrypted. I can't use an encrypted string if it can't be matched to the original string based on which it was encrypted... What is the point of an encrypted string if at the end you need to actually know what the damn thing says.

For example..

You have a set of user names and passwords that are encrypted and stored in an x location. They are encrypted so no one can figure out that they really are in case they hack the x location. Then you have an actual owner of the user name and password. They will not be inputting the encrypted string as user name and password into the app that uses them, right??? So in order to, for example, validate them, you have to be able to decrypt the encrypted string and match it to their input...

I generally fail to see the logic of "one way" encryption as it is often interpreted. There is no such thing.. somewhere,, some time,, for some reason the string actually must be decrypted in order for it to have a purpose.

----------


## chacke

I had difficulties seeing the logic in the past as well. in fact it is easy and logical
you hash the login or pasw and store the outcome in a Database or whatever.

If the user input his plaintext pasw then you will have to hash it as well.

This hash you will have to compare it with the hash you had stored before.

hash is used to compare/match. You can also use hash to monitor/compare file changes.

----------


## Deliriumxx

Ah,, I see the logic of what you just explained. 

I am doing the SAME thing in reverse order (which seems to be something I do a lot with my code - use reversed logic - probably how my brain is wired..),,, I DECRYPT what is encrypted independently to find a match,, and your logic encrypts to create a match..

Gotha! Thanks for shedding some light on this topic for me  :Smilie:

----------


## thetechguru

Late to the party, but this was just what I was looking for.  I haven't learned .NET yet, but have a small project with a tight deadline that also won't be used for very long, so just wanted to fall back on my old VB6 skills to get it done this week.  Needed to be able to MD5 hash a string, and was running into brick walls at every turn.  This is working perfectly for me.

Thanks again,

Alan

----------


## dilettante

> in HashBlock()  should not add + 1 to the the length because the Lbound()  is already starting with 0


Umm...

There was no error here.  The length is UB - LB + 1, and this is correct no matter what your LB might be.

Hard to say where you went wrong there.

----------


## AccadaccA

Great work *dilettante* although I'm late to the party it works perfectly with my current project. Cheers.

edit: BTW, I'm using it on Windows 7, 64 bit but my VB6 is running in XP compatibility mode. It works a treat either when compiled or not.

----------


## dilettante

Glad it works for you.

One thing that can get VB6 programmers twisted around at times is text.  You need to use the appropriate encoding.  In VB6 we normally have UTF-16LE ("Unicode") but sometimes we are trying to match MD5 hashes with another system using ANSI or ASCII, or even UTF-8.

If we don't use the same encoding at each end, we naturally won't get the same MD5 hash.

----------


## DEXWERX

Here is the HashFile() Method updated to use dilettante's HugeBinaryFile class

http://www.vbforums.com/showthread.p...File-I-O-Class



```
Public Function HashFile(ByVal FileName As String) As String
    Const CHUNK As Long = 16384
    Dim HugeFile As HugeBinaryFile
    Dim cyWholeChunks As Currency
    Dim lngRemainder As Long
    Dim cyChunk As Currency
    Dim bytBlock() As Byte
    
    On Error Resume Next 'Does file exist?
    GetAttr FileName
    If Err.Number = 0 Then
        On Error GoTo 0

        Set HugeFile = New HugeBinaryFile
        HugeFile.OpenFile FileName
        cyWholeChunks = Int(HugeFile.FileLen / CHUNK)
        lngRemainder = HugeFile.FileLen - (CHUNK * cyWholeChunks)
        NewHash
        ReDim bytBlock(CHUNK - 1)
        For cyChunk = 1 To cyWholeChunks
            HugeFile.ReadBytes bytBlock
            HashBlock bytBlock
        Next
        If lngRemainder > 0 Then
            ReDim bytBlock(lngRemainder - 1)
            HugeFile.ReadBytes bytBlock
            HashBlock bytBlock
        End If
        HugeFile.CloseFile
        
        HashFile = HashValue()
    Else
        Err.Raise vbObjectError Or &HC342&, _
                  "MD5Hash.HashFile", _
                  "File doesn't exist"
    End If
End Function
```

----------

