Monday, October 29, 2007

VBScript MD5Hash and IsHex Functions to Calculate MD5 File Hashes

Hash.... browns.... get it? *HASH* .... It's funny. Laugh.Recently I was tasked with synchronizing directories between two different servers. Because files can change, become corrupted or otherwise altered without changing any of their attributes, it was pretty essential to ensure that these files were exactly the same.

There are a few utilities out there that can do this for you but one of the best suited is the security algorithm MD5. Well, obviously, VBScript does not have a built in MD5 summing function. There are some .NET libraries that do this pretty easily but unfortunately their methods are not exposed to VBScript (someone correct me if I’m wrong).

So to facilitate this MD5 summing I tried a couple of different methods. The first one, a pure VBScript solution, was functional. The first couple of files I tried it on seemed to go off without a hitch. That was, until I tried a 1.9MB file. That file took 59 minutes to run through the pure VBScript solution. Obviously this is totally impractical considering the size of some files.

The next method I tried was a compiled command line implementation of MD5. You'll need to download this and make sure the "exe" is in the same directory as your VBS. This works great and is the method that I settled on. Hashing is quick, very quick. The same 1.9MB file happens well under a second. Several hundred meg files in just a second or two. Well within a reasonable margin. So here is the script and a quick example of usage:

sHash = MD5Hash("C:\config.sys")

Another side note, I wrote a "IsHash" function that returns true or false based on whether the string you pass is a valid hex value (since all MD5 hashes are returned as a hex string).
Public Function MD5Hash(sFileName)
  'This script is provided under the Creative Commons license located
  'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
  'be used for commercial purposes with out the expressed written consent
  'of NateRice.com

  Const OpenAsDefault = -2
  Const FailIfNotExist = 0
  Const ForReading = 1
 
  Dim oMD5CmdShell, oMD5CmdFSO, sTemp, sTempFile, fMD5CmdFile, sPath
  Dim fResultsFile, sResults

  Set oMD5CmdShell = CreateObject("WScript.Shell")
  Set oMD5CmdFSO = CreateObject("Scripting.FileSystemObject")
  sTemp = oMD5CmdShell.ExpandEnvironmentStrings("%TEMP%")
  sTempFile = sTemp & "\" & oMD5CmdFSO.GetTempName
 
  '------Verify Input File Existance-----
  If Not oMD5CmdFSO.FileExists(sFileName) Then
    MD5Hash = "Failed: Invalid Input File."
  Else
    Set fMD5CmdFile = oMD5CmdFSO.GetFile(sFileName)
    sPath = fMD5CmdFile.ShortPath
    sFileName = sPath
    Set fMD5CmdFile = Nothing
  End If
  '--------------------------------------
 
  oMD5CmdShell.Run "%comspec% /c md5.exe -n " & sFileName & _
  " > " & sTempFile, 0, True

  Set fResultsFile = _
  oMD5CmdFSO.OpenTextFile(sTempFile, ForReading, FailIfNotExist, OpenAsDefault)
  sResults = fResultsFile.ReadAll
  sResults = trim(Replace(sResults, vbCRLF,""))
  fResultsFile.Close
  oMD5CmdFSO.DeleteFile sTempFile
 
  If len(sResults) = 32 And IsHex(sResults) Then
    MD5Hash = sResults
  Else
    MD5Hash = "Failed."
  End If
 
  Set oMD5CmdShell = Nothing
  Set oMD5CmdFSO = Nothing
End Function

Private Function IsHex(sHexCheck)
  'This script is provided under the Creative Commons license located
  'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
  'be used for commercial purposes with out the expressed written consent
  'of NateRice.com


  Dim sX, bCharCheck, sHexValue, sHexValues, aHexValues
  sHexCheck = UCase(sHexCheck)
  sHexValues = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F"
  aHexValues = Split(sHexValues, ",")

  For sX = 1 To Len(sHexCheck)
    bCharCheck = False
    For Each sHexValue In aHexValues
      If UCase(Mid(sHexCheck,sX,1)) = sHexValue Then
        bCharCheck = True
        Exit For
      End If
    Next
   
    If bCharCheck <> True Then
      IsHex = False
      Exit Function
    End If
  Next
 
  IsHex = True
End Function
Send this to:                          

Comments

Duncan said...

Hey again,
This was something else I wasasked to add into my script. I actually found a good little company that has some useful dll's you can download for free. There is one for MD5 that I've used. Link to the MD5 one is here (there are others if you browse :P )
http://www.xstandard.com/en/documentation/xmd5/

10/31/2007 12:40:58 PM

Nathan+Rice said...

Sweet. This would work well for ASP based applications. Thanks :).

10/31/2007 2:12:24 PM

said...

I generate a MD5 Hash (file with 2MB) in 2 minutes with this VBScript solution:
http://www.scriptbox.at.tt/index.php?search=Calculate%20MD5%20Hash.vbs

10/2/2008 12:53:27 AM

said...

Hello. I''m using this scrip to calculate the hash of CD/DVD file contents. I''m always getting the error "Run-time ''62:input past end of file". Can you help me?

Thank you for your time.

Alberto

4/16/2012 11:19:34 AM

said...

I prefer monvig the folder where you store you users data out side the htdocs/ or public_html/ folder. Put the folder inside your home directory for example. and create a PHP page that calls file from inside that directory based on the userID.

9/26/2012 2:24:05 PM

Name
URL
Email
Email address is not published
Remember Me
Comments

CAPTCHA
Write the characters in the image above