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."
Last edited by dilettante; May 31st, 2008 at 01:09 PM.
Reason: Small change made in raised exception text.
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
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.
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.
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
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.
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.
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