Click to See Complete Forum and Search --> : MD5 Hashing not quite working out ...


GremlinSA
September 7th, 2008, 12:15 PM
I have a requirement to MD5Hash certain parts of a file .. (so i need some control over what gets hashed)..

So i looked up the specs ... Pseudo Code
'//Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating
'var int[64] r, k

'//r specifies the per-round shift amounts
'r[ 0..15] := {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22}
'r[16..31] := {5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20}
'r[32..47] := {4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23}
'r[48..63] := {6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}

'//Use binary integer part of the sines of integers (Radians) as constants:
'for i from 0 to 63
' k[i] := floor(abs(sin(i + 1)) × (2 pow 32))

'//Initialize variables:
'var int h0 := 0x01234567
'var int h1 := 0x89ABCDEF
'var int h2 := 0xFEDCBA98
'var int h3 := 0x76543210

'//Pre-processing:
'append "1" bit to message
'append "0" bits until message length in bits ≡ 448 (mod 512)
' 56 (mod 64)
'append bit /* bit, not byte */ length of unpadded message as 64-bit little-endian integer to message

'//Process the message in successive 512-bit chunks:
'for each 512-bit chunk of message
' break chunk into sixteen 32-bit little-endian words w[i], 0 ≤ i ≤ 15

' //Initialize hash value for this chunk:
' var int a := h0
' var int b := h1
' var int c := h2
' var int d := h3

' //Main loop:
' for i from 0 to 63
' if 0 ≤ i ≤ 15 then
' f := (b and c) or ((not b) and d)
' g := i
' else if 16 ≤ i ≤ 31
' f := (d and b) or ((not d) and c)
' g := (5×i + 1) mod 16
' else if 32 ≤ i ≤ 47
' f := b xor c xor d
' g := (3×i + 5) mod 16
' else if 48 ≤ i ≤ 63
' f := c xor (b or (not d))
' g := (7×i) mod 16

' temp := d
' d := c
' c := b
' b := b + leftrotate((a + f + k[i] + w[g]) , r[i])
' a := temp

' //Add this chunk's hash to result so far:
' h0 := h0 + a
' h1 := h1 + b
' h2 := h2 + c
' h3 := h3 + d

'var int digest := h0 append h1 append h2 append h3 //(expressed as little-endian)

' //leftrotate function definition
' leftrotate (x, c)
' return (x << c) or (x >> (32-c));

I've pretty much got most of the core of this working.. However when running a few test strings i'm getting the wrong hash back ..

running MD5 on ("") should give "d41d8cd98f00b204e9800998ecf8427e" however i'm getting "E0BA2C792CFD07E92768A891C861AB11"

I've previously done a CRC 16 Module from simular pseudo code, that worked 100%, but i'm batteling with this one for several days now..

Public Class MD5Hash
Private R() As UInt32
Private K() As UInt32
Private H() As UInt32
Private Pre() As UInt32
Private A() As UInt32
Private _Size As Integer
Private _Current As Integer

Public Sub New()
InitK()
InitR()
End Sub

Public Sub Reset(ByVal FinSize As Integer)
ReDim H(3)
ReDim Pre(3)
ReDim A(3)
'ReDim Block(15)
_Size = FinSize
_Current = 0

H(0) = &H1234567&
H(1) = &H89ABCDEF&
H(2) = &HFEDCBA98&
H(3) = &H76543210&

End Sub

Private Sub InitR()
Dim S() As String
Dim TmpInt As Integer
ReDim R(63)

S = Split("7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22," & _
"5,9,14,20, 5,9,14,20, 5,9,14,20, 5,9,14,20," & _
"4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23," & _
"6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21 ", ",")

For TmpInt = 0 To 63
R(TmpInt) = Val(S(TmpInt))
Next
End Sub

Private Sub InitK()
Dim TmpInt As Integer
Dim S() As String
S = Split("D76AA478,E8C7B756,242070DB,C1BDCEEE,F57C0FAF,4787C62A,A8304613,FD469501," & _
"698098D8,8B44F7AF,FFFF5BB1,895CD7BE,6B901122,FD987193,A679438E,49B40821," & _
"F61E2562,C040B340,265E5A51,E9B6C7AA,D62F105D,02441453,D8A1E681,E7D3FBC8," & _
"21E1CDE6,C33707D6,F4D50D87,455A14ED,A9E3E905,FCEFA3F8,676F02D9,8D2A4C8A," & _
"FFFA3942,8771F681,6D9D6122,FDE5380C,A4BEEA44,4BDECFA9,F6BB4B60,BEBFBC70," & _
"289B7EC6,EAA127FA,D4EF3085,04881D05,D9D4D039,E6DB99E5,1FA27CF8,C4AC5665," & _
"F4292244,432AFF97,AB9423A7,FC93A039,655B59C3,8F0CCC92,FFEFF47D,85845DD1," & _
"6FA87E4F,FE2CE6E0,A3014314,4E0811A1,F7537E82,BD3AF235,2AD7D2BB,EB86D391", ",")

ReDim K(63)
For TmpInt = 0 To 63
K(TmpInt) = CUint32(S(TmpInt))
Next
End Sub

Private Function LeftRotate(ByVal InVal As UInt32, ByVal Bits As Integer) As UInt32
Dim TmpInt As Integer
For TmpInt = 1 To Bits
If InVal And &H80000000& Then
InVal = (InVal << 1) Or &H1
Else
InVal = (InVal << 1)
End If
Next
Return InVal
End Function

Private Function F1(ByVal X As UInt32, ByVal Y As UInt32, ByVal Z As UInt32) As UInt32
Return (X And Y) Or (Not (X) And Z)
End Function

Private Function F2(ByVal X As UInt32, ByVal Y As UInt32, ByVal Z As UInt32) As UInt32
Return (X And Z) Or (Not (Y) And Z)
End Function

Private Function F3(ByVal X As UInt32, ByVal Y As UInt32, ByVal Z As UInt32) As UInt32
Return X Xor Y Xor Z
End Function

Private Function F4(ByVal X As UInt32, ByVal Y As UInt32, ByVal Z As UInt32) As UInt32
Return Y Xor (X Or (Not Z))
End Function

Private Function Hex8(ByVal Value As UInt32) As String
Dim s As String

s = Hex(Value)
Do While (Len(s) < 8)
s = "0" & s
Loop
Return s
End Function

Private Function Hex16(ByVal Value As UInt64) As String
Dim s As String

s = Hex(Value)
Do While (Len(s) < 16)
s = "0" & s
Loop
Return s

End Function

Private Function CUint32(ByVal Hex As String) As UInt32
Dim tmpInt As Integer

CUint32 = 0
For tmpInt = 0 To Hex.Length - 1
CUint32 = (CUint32 * &H10) + Val("&H" & Hex.Substring(tmpInt, 1))
Next
End Function

Public ReadOnly Property GetHash() As String
Get
Return Hex8(H(0)) & Hex8(H(1)) & Hex8(H(2)) & Hex8(H(3))
End Get
End Property

Private Sub Core(ByVal Block() As UInt32)
Dim Tmpint As Integer
Dim TmpUint As UInt32
Dim F As UInt32
Dim G As UInt32
Dim Tmp1Int64 As Int64
Dim Tmp2Int64 As Int64


If Block.Length <> 16 Then
MsgBox("MD5 Data Object Incorect Size")
Exit Sub
End If
For Tmpint = 0 To 63
Select Case Tmpint
Case 0 To 15
F = F1(A(1), A(2), A(3))
G = Tmpint
Case 16 To 31
F = F2(A(1), A(2), A(3))
G = (5 * Tmpint + 1) Mod 16
Case 32 To 47
F = F3(A(1), A(2), A(3))
G = (3 * Tmpint + 5) Mod 16
Case 48 To 63
F = F4(A(1), A(2), A(3))
G = (7 * Tmpint) Mod 16

End Select
TmpUint = A(3)
A(3) = A(2)
A(2) = A(1)
Tmp1Int64 = F
Tmp1Int64 += A(0)
Tmp1Int64 += K(Tmpint)
Tmp1Int64 += Block(G)
Tmp1Int64 = Tmp1Int64 And &HFFFFFFFF&
Tmp2Int64 = A(1)
Tmp2Int64 += LeftRotate(CUInt(Tmp1Int64), R(Tmpint))
A(1) = Tmp2Int64 And &HFFFFFFFF&
A(0) = TmpUint
Next
End Sub

Public Sub MD5(ByVal Data() As UInt32)
Dim TmpInt64 As Int64
Dim TmpInt As Integer
If Data.Length <> 16 Then
MsgBox("MD5 Data Object Incorect Size")
Exit Sub
End If
A(0) = H(0)
A(1) = H(1)
A(2) = H(2)
A(3) = H(3)
Core(Data)
For TmpInt = 0 To 3
TmpInt64 = H(TmpInt)
TmpInt64 += A(TmpInt)
H(TmpInt) = TmpInt64 And &HFFFFFFFF
Next

End Sub

Public Sub MD5(ByVal Data() As Byte)
Dim DataInt32() As UInt32
Dim Tmpint As Integer
Dim Tmpint2 As Integer
If Data.Length <> 64 Then
MsgBox("MD5 Data Object Incorect Size")
Exit Sub
End If

ReDim DataInt32(15)
For Tmpint = 0 To 15
For Tmpint2 = 0 To 3
DataInt32(Tmpint) = (DataInt32(Tmpint) * &H100) + Data(Tmpint * 4 + Tmpint2)
Next
Next
MD5(DataInt32)
End Sub

End Class

Could someone please check where i'm going wrong here ...

Thanks
Gremmy....

javajawa
September 7th, 2008, 12:52 PM
If you think It would be of help, I could post the VB6 MD5 code for you to compare against. But I can't see that being of much use.

GremlinSA
September 7th, 2008, 01:33 PM
If you've got VB6 MD5 Hashing code .. Please, I'd like to use it to compare...

Thanks..

javajawa
September 7th, 2008, 01:38 PM
Here we go...
Enjoy!

GremlinSA
September 8th, 2008, 04:16 AM
Okay i found where i'm going wrong .. :( ..

I forgot about Little endian and big endian .. I'm working almost everything in big ...

Ouch ...

Time to sort it all out...

Gremmy

GremlinSA
September 8th, 2008, 09:05 AM
Ya hoo ... I got it sorted ..

Thank javajawa, that module did help, i now get the correct MD5 Hash for the test strings...

Now to finilise the complete MD5 Class....

Gremmy....