Jump to content

Recommended Posts

Posted (edited)

When searching here, I saw several requests for an MD5 routine, and since I needed one myself I just ported one over from PowerBASIC to FreeBASIC so that everyone here could use it also.

Here's the AutoIt code to test it with:

;=====================================================
; Test_MD5_Hash_DLL.au3
; Bruce Huber  September 18, 2008
;=====================================================

; CalcMD5("This is a test", MD5_Digest)
; Expected output for that input string = 'ce114e4501d2f4e2dcea3e17b546f339'

; MD5_Digest string is 33 bytes.
; So you should pre-fill that parameter string with at least 35 characters
; to allow for additional null bytes at the end of the DLL's ASCIIZ string.

;==============================================
; INCLUDES
;==============================================

#include <String.au3>

;==============================================
; INIT CODE
;==============================================

Dim $parm1, $parm2, $result, $save_error

;=====================================================
; FUNCTIONS
;=====================================================

Func dp( $dbgTXT)
DllCall( "kernel32.dll", "none", "OutputDebugString", "str", $dbgTXT)
EndFunc

;=====================================================
; MAIN()
;=====================================================

dp( "DBGVIEWCLEAR")

;   ---------------------------------------------------------
;   -----  This is the only part you need to get MD5 hashes
;   -----  The rest is Debug output
$parm1 = "This is a test"
$parm2 = _StringRepeat( " ", 50)

$result = DllCall("MD5_Hash.dll", "none:cdecl", "CalcMD5", "str", $parm1, "str", $parm2)
$save_error = @error
;   ---------------------------------------------------------

dp( "MD5_Hash.dll")
dp( "@error = " & $save_error)
dp( "1 = " & $result[1])
dp( "2 = " & $result[2])
dp( "$parm2 = " & $parm2)
dp( "R = " & $result[0])

; As you can see, $parm2 does NOT contain the returned value.
;
; $result[2] will contain the MD5_Digest string value after the function call.

#cs
------------  Sample output  -------------
MD5_Hash.dll
@error = 0
1 = This is a test
2 = CE114E4501D2F4E2DCEA3E17B546F339
$parm2 =                                                   
R = 
#ce

And here's the FreeBASIC MD5 Hash DLL code:

'=====================================================
' MD5_Hash.dll
' Bruce Huber  September 18, 2008
'=====================================================

' MD5 Message Digest Algorithm.

' FreeBASIC command line to compile the DLL:
' fbc -s gui -dll -export MD5_Hash.bas

' Original PowerBASIC version - Trevor Lane - Aug 27th, 2001, 08:50 AM
' [url="http://www.powerbasic.com/support/pbforums/showthread.php?t=23119"]http://www.powerbasic.com/support/pbforums/showthread.php?t=23119[/url]
'
' Converted from:
' A Javascript implementation of the RSA Data Security, Inc. MD5 Message
' Digest Algorithm, as defined In RFC 1321.
' Copyright (C) Paul Johnston 1999 - 2000.
' Updated by Greg Holt 2000 - 2001.
' See [url="http://pajhome.org.uk/site/legal.html"]http://pajhome.org.uk/site/legal.html[/url] for details.

' CalcMD5("This is a test", MD5_Digest)
' Expected output with that input string = 'ce114e4501d2f4e2dcea3e17b546f339'

'==============================================
' INCLUDES and USING
'==============================================

'==============================================
' STANDARD DEFINES
'==============================================

#Define BEH_DEBUG_00
#If Defined( BEH_DEBUG_00)
#Include Once "windows.bi"
#Define dp( dbgTXT) OutputDebugString( dbgTXT)
#Else
#Define dp( dbgTXT) Print dbgTXT
#EndIf

'==============================================
' DECLARES
'==============================================

' Public functions.
Declare Sub CalcMD5 Cdecl Alias "CalcMD5" ( ByVal SourceStr As String, MD5Digest As ZString Ptr)

' Private functions.
Declare Function rhex( ByVal num As Long) As String
Declare Function rol( ByVal num As Long, ByVal cnt As Long) As Long
Declare Function Add32( x As Long, y As Long) As Long
Declare Function cmn( q As Long, a As Long, b As Long, x As Long, s As Long, t As Long) As Long
Declare Function ff( a As Long, b As Long, c As Long, d As Long, x As Long, s As Long, t As Long) As Long
Declare Function gg( a As Long, b As Long, c As Long, d As Long, x As Long, s As Long, t As Long) As Long
Declare Function hh( a As Long, b As Long, c As Long, d As Long, x As Long, s As Long, t As Long) As Long
Declare Function ii( a As Long, b As Long, c As Long, d As Long, x As Long, s As Long, t As Long) As Long

'=====================================================
' SCREEN SETUP
'=====================================================

'=====================================================
' INIT CODE
'=====================================================

'=====================================================
' FUNCTIONS
'=====================================================

'
' Rotate HEX.
' Convert a 32-Bit number to a hex string with the least significant byte first.
'
Function rhex ( ByVal num As Long) As String

Dim s As String
Dim t As String

s = Right$( "00000000" & Hex$( num), 8)
t = Right$( s,2) & Mid$( s,5,2) & Mid$( s,3,2) & Left$( s,2)
Function = t

End Function

'
' Rotate Bits Left
'
Function rol (ByVal num As Long, ByVal cnt As Long) As Long

Asm
  mov eax, [num]
  mov ecx, 0
  add ecx, [cnt]
  jz end_rol
more_rol:
  rol eax, 1
  Loop more_rol
end_rol:
  mov [Function], eax
End Asm

End Function

'
' Add integers, wrapping At 2^32. This uses 16-Bit operations internally
' to work around bugs in some JS interpreters.
'
Function Add32( x As Long, y As Long) As Long

Dim lsw As ULong
Dim lswy As ULong
Dim msw As ULong

lswy = (y And &HFFFF)
lsw = (x And &HFFFF) + lswy
msw = (x Shr 16) + (y Shr 16) + (lsw Shr 16)

Function = (msw Shl 16) Or (lsw And &HFFFF)

End Function

'
' Convert a string to a sequence of 16-Word blocks, stored as an array.
' Append padding bits and the length, as described in the MD5 standard.
'
Sub str2blks_MD5( strSrc As String, blks() As Long)

Dim nblk As Long
Dim i As Long

nblk = ((Len(strSrc) + 8) Shr 6) + 1
ReDim blks(nblk * 16)

For i = 0 To UBound(blks)
  blks(i) = 0
Next i

For i = 0 To (Len(strSrc)-1)
  blks(i Shr 2) = blks(i Shr 2) Or (Asc(Mid$(strSrc,i+1,1)) Shl ((i Mod 4) * 8))
Next

i = Len(strSrc)
blks(i Shr 2) = blks(i Shr 2) Or (&H80 Shl ((i Mod 4) * 8))
blks(nblk * 16 - 2) = Len(strSrc) * 8

End Sub

'
' These functions implement the basic operation for each round of the algorithm.
'
Function cmn( q As Long, a As Long, b As Long, x As Long, s As Long, t As Long) As Long
Function =  Add32( rol( Add32( Add32( a, q) , Add32( x, t)), s) , b)
End Function
Function ff( a As Long, b As Long, c As Long, d As Long, x As Long, s As Long, t As Long) As Long
Function = cmn( (b And c) Or ((Not(b)) And d), a, b, x, s, t)
End Function
Function gg( a As Long, b As Long, c As Long, d As Long, x As Long, s As Long, t As Long) As Long
Function = cmn( (b And d) Or (c And (Not(d))), a, b, x, s, t)
End Function
Function hh( a As Long, b As Long, c As Long, d As Long, x As Long, s As Long, t As Long) As Long
Function = cmn( b Xor c Xor d, a, b, x, s, t)
End Function
Function ii( a As Long, b As Long, c As Long, d As Long, x As Long, s As Long, t As Long) As Long
Function = cmn( c Xor (b Or Not(d)), a, b, x, s, t)
End Function

'
' CalcMD5() is the entry point for the MD5 routine.
'
Sub CalcMD5 Cdecl Alias "CalcMD5" ( ByVal SourceStr As String, MD5Digest As ZString Ptr) Export

Dim a As Long
Dim b As Long
Dim c As Long
Dim d As Long
Dim olda As Long
Dim oldb As Long
Dim oldc As Long
Dim oldd As Long
Dim i As Long
Dim x() As Long

a = 1732584193
b = -271733879
c = -1732584194
d = 271733878

ReDim x(1)

str2blks_MD5 SourceStr, x()

For i = 0 To UBound(x)-1 Step 16

  olda = a
  oldb = b
  oldc = c
  oldd = d

  a = ff(a, b, c, d, x(i+ 0), 7 , -680876936)
  d = ff(d, a, b, c, x(i+ 1), 12, -389564586)
  c = ff(c, d, a, b, x(i+ 2), 17,  606105819)
  b = ff(b, c, d, a, x(i+ 3), 22, -1044525330)
  a = ff(a, b, c, d, x(i+ 4), 7 , -176418897)
  d = ff(d, a, b, c, x(i+ 5), 12,  1200080426)
  c = ff(c, d, a, b, x(i+ 6), 17, -1473231341)
  b = ff(b, c, d, a, x(i+ 7), 22, -45705983)
  a = ff(a, b, c, d, x(i+ 8), 7 ,  1770035416)
  d = ff(d, a, b, c, x(i+ 9), 12, -1958414417)
  c = ff(c, d, a, b, x(i+10), 17, -42063)
  b = ff(b, c, d, a, x(i+11), 22, -1990404162)
  a = ff(a, b, c, d, x(i+12), 7 ,  1804603682)
  d = ff(d, a, b, c, x(i+13), 12, -40341101)
  c = ff(c, d, a, b, x(i+14), 17, -1502002290)
  b = ff(b, c, d, a, x(i+15), 22,  1236535329)

  a = gg(a, b, c, d, x(i+ 1), 5 , -165796510)
  d = gg(d, a, b, c, x(i+ 6), 9 , -1069501632)
  c = gg(c, d, a, b, x(i+11), 14,  643717713)
  b = gg(b, c, d, a, x(i+ 0), 20, -373897302)
  a = gg(a, b, c, d, x(i+ 5), 5 , -701558691)
  d = gg(d, a, b, c, x(i+10), 9 ,  38016083)
  c = gg(c, d, a, b, x(i+15), 14, -660478335)
  b = gg(b, c, d, a, x(i+ 4), 20, -405537848)
  a = gg(a, b, c, d, x(i+ 9), 5 ,  568446438)
  d = gg(d, a, b, c, x(i+14), 9 , -1019803690)
  c = gg(c, d, a, b, x(i+ 3), 14, -187363961)
  b = gg(b, c, d, a, x(i+ 8), 20,  1163531501)
  a = gg(a, b, c, d, x(i+13), 5 , -1444681467)
  d = gg(d, a, b, c, x(i+ 2), 9 , -51403784)
  c = gg(c, d, a, b, x(i+ 7), 14,  1735328473)
  b = gg(b, c, d, a, x(i+12), 20, -1926607734)

  a = hh(a, b, c, d, x(i+ 5), 4 , -378558)
  d = hh(d, a, b, c, x(i+ 8), 11, -2022574463)
  c = hh(c, d, a, b, x(i+11), 16,  1839030562)
  b = hh(b, c, d, a, x(i+14), 23, -35309556)
  a = hh(a, b, c, d, x(i+ 1), 4 , -1530992060)
  d = hh(d, a, b, c, x(i+ 4), 11,  1272893353)
  c = hh(c, d, a, b, x(i+ 7), 16, -155497632)
  b = hh(b, c, d, a, x(i+10), 23, -1094730640)
  a = hh(a, b, c, d, x(i+13), 4 ,  681279174)
  d = hh(d, a, b, c, x(i+ 0), 11, -358537222)
  c = hh(c, d, a, b, x(i+ 3), 16, -722521979)
  b = hh(b, c, d, a, x(i+ 6), 23,  76029189)
  a = hh(a, b, c, d, x(i+ 9), 4 , -640364487)
  d = hh(d, a, b, c, x(i+12), 11, -421815835)
  c = hh(c, d, a, b, x(i+15), 16,  530742520)
  b = hh(b, c, d, a, x(i+ 2), 23, -995338651)

  a = ii(a, b, c, d, x(i+ 0), 6 , -198630844)
  d = ii(d, a, b, c, x(i+ 7), 10,  1126891415)
  c = ii(c, d, a, b, x(i+14), 15, -1416354905)
  b = ii(b, c, d, a, x(i+ 5), 21, -57434055)
  a = ii(a, b, c, d, x(i+12), 6 ,  1700485571)
  d = ii(d, a, b, c, x(i+ 3), 10, -1894986606)
  c = ii(c, d, a, b, x(i+10), 15, -1051523)
  b = ii(b, c, d, a, x(i+ 1), 21, -2054922799)
  a = ii(a, b, c, d, x(i+ 8), 6 ,  1873313359)
  d = ii(d, a, b, c, x(i+15), 10, -30611744)
  c = ii(c, d, a, b, x(i+ 6), 15, -1560198380)
  b = ii(b, c, d, a, x(i+13), 21,  1309151649)
  a = ii(a, b, c, d, x(i+ 4), 6 , -145523070)
  d = ii(d, a, b, c, x(i+11), 10, -1120210379)
  c = ii(c, d, a, b, x(i+ 2), 15,  718787259)
  b = ii(b, c, d, a, x(i+ 9), 21, -343485551)

  a = Add32(a,olda)
  b = Add32(b,oldb)
  c = Add32(c,oldc)
  d = Add32(d,oldd)

Next i

*MD5Digest = rhex(a) & rhex(b) & rhex(c) & rhex(d)

End Sub

I've also attached a ZIP with the source code plus a compiled version of the DLL for those that don't want to build it themsleves.

Bruce Huber (cbruce)

MD5_Hash.zip

Edited by cbruce
Posted

Thanks a lot cbruce. This is very usefull !!

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...