|
|
|
VB6 MD5 存在的问题
jangogo @ 2009-12-5 15:31:00
十年前,在开发财务软件的时候在网上找到一个 作者是: Robert Hubley. 的 VB6 的MD5算法,经过十年的使用,没有发现问题,因为我们使用MD5算法都只是用于密码加密,当近日做Dotnet应用的时候,居然发现这个算法有Bug! 当需要计算的字符串的长度为120-127之间的时候,或者是120的整数倍的到127的整数倍之间的MD5的结果和C#出来的结果不对,又在网上找了很多VB的MD5实现,发现当字符串长度为64*N+55 时候,计算结果和C#的结果也对不上。也就是说这两种实现都存在问题,网上基本上没有能够出来结果和C#完全一致的MD5 算法的VB实现。
费尽努力才找到一个:
经过测试,字符串长度1到1000都没有发现问题:
- Option Explicit
-
- Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
- Private Declare Sub ZeroMemory Lib "KERNEL32" Alias "RtlZeroMemory" (dest As Any, ByVal numBytes As Long)
-
-
- Private Const S11 As Long = 7
- Private Const S12 As Long = 12
- Private Const S13 As Long = 17
- Private Const S14 As Long = 22
- Private Const S21 As Long = 5
- Private Const S22 As Long = 9
- Private Const S23 As Long = 14
- Private Const S24 As Long = 20
- Private Const S31 As Long = 4
- Private Const S32 As Long = 11
- Private Const S33 As Long = 16
- Private Const S34 As Long = 23
- Private Const S41 As Long = 6
- Private Const S42 As Long = 10
- Private Const S43 As Long = 15
- Private Const S44 As Long = 21
-
- Private LongBits(0 To 31) As Long
-
- Private padding(0 To 63) As Byte
- Private Buffer(0 To 63) As Byte
- Private State(0 To 3) As Long
- Private Count As Long
-
-
- Private Function ROTATE_LEFT(ByVal X As Long, ByVal n As Long) As Long
- Dim Aftern As Long, Beforen As Long
- Aftern = X And (LongBits(31 - n) - 1)
- Beforen = (X And &H7FFFFFFF) \ LongBits(32 - n)
- ROTATE_LEFT = Aftern * LongBits(n) Or Beforen
- If X And LongBits(31 - n) Then ROTATE_LEFT = ROTATE_LEFT Or &H80000000
- If X And &H80000000 Then ROTATE_LEFT = ROTATE_LEFT Or LongBits(n - 1)
- End Function
-
-
-
- Private Sub FF(ByRef a As Long, _
- ByVal B As Long, _
- ByVal c As Long, _
- ByVal d As Long, _
- ByVal X As Long, _
- ByVal s As Long, _
- ByVal ac As Long)
- a = LongCycleAdd(a, B And c Or Not B And d, X, ac)
- a = ROTATE_LEFT(a, s)
- a = LongCycleAdd(a, B)
- End Sub
-
- Private Sub GG(ByRef a As Long, _
- ByVal B As Long, _
- ByVal c As Long, _
- ByVal d As Long, _
- ByVal X As Long, _
- ByVal s As Long, _
- ByVal ac As Long)
- a = LongCycleAdd(a, B And d Or c And Not d, X, ac)
- a = ROTATE_LEFT(a, s)
- a = LongCycleAdd(a, B)
- End Sub
-
- Private Sub HH(ByRef a As Long, _
- ByVal B As Long, _
- ByVal c As Long, _
- ByVal d As Long, _
- ByVal X As Long, _
- ByVal s As Long, _
- ByVal ac As Long)
- a = LongCycleAdd(a, B Xor c Xor d, X, ac)
- a = ROTATE_LEFT(a, s)
- a = LongCycleAdd(a, B)
- End Sub
-
- Private Sub ii(ByRef a As Long, _
- ByVal B As Long, _
- ByVal c As Long, _
- ByVal d As Long, _
- ByVal X As Long, _
- ByVal s As Long, _
- ByVal ac As Long)
- a = LongCycleAdd(a, c Xor B Or Not d, X, ac)
- a = ROTATE_LEFT(a, s)
- a = LongCycleAdd(a, B)
- End Sub
-
-
-
-
- Public Function DigestByteToHexStr(SourceByte() As Byte) As String
- Call ReSet
- Call Update(SourceByte, UBound(SourceByte) + 1)
- Call Final
- DigestByteToHexStr = LongToString(State(0)) & LongToString(State(1)) & LongToString(State(2)) & LongToString(State(3))
- End Function
-
-
- Public Function DigestStrToHexStr(SourceString As String) As String
- DigestStrToHexStr = DigestByteToHexStr(StrConv(SourceString, vbFromUnicode))
- End Function
-
-
- Public Function DigestFileToHexStr(FilePath As String) As String
- If Len(Dir$(FilePath)) Then
- Dim F1 As Long, FileBuffer(0 To 65535) As Byte, i As Long, j As Long
- F1 = FreeFile
- Open FilePath For Binary Access Read As #F1
- Call ReSet
-
- For i = 1 To LOF(F1) \ 65536
- Get #F1, , FileBuffer
- Call Update(FileBuffer, UBound(FileBuffer) + 1)
- Next
- i = LOF(F1) And &HFFFF&
- If i Then
- Get #F1, , FileBuffer
- Call Update(FileBuffer, i)
- End If
-
- Count = LOF(F1)
- Close #F1
- Call Final
- DigestFileToHexStr = LongToString(State(0)) & LongToString(State(1)) & LongToString(State(2)) & LongToString(State(3))
- End If
- End Function
-
-
- Private Sub ReSet()
-
- Count = 0
-
- State(0) = &H67452301
- State(1) = &HEFCDAB89
- State(2) = &H98BADCFE
- State(3) = &H10325476
- End Sub
-
-
-
- Private Sub Update(InputArr() As Byte, Length As Long)
- Dim i As Long, Index As Long, PartLen As Long
-
- Index = Count And &H3F
-
- Count = Count + Length
- PartLen = 64 - Index
-
- If Length >= PartLen Then
- Call CopyMemory(Buffer(Index), InputArr(0), PartLen)
- Call Transform(Buffer)
- For i = PartLen To Length - 64 Step 64
- Call CopyMemory(Buffer(Index), InputArr(i), 64)
- Call Transform(Buffer)
- Next
- Index = 0
- Else
- i = 0
- End If
-
- If Length - i > 0 Then Call CopyMemory(Buffer(Index), InputArr(i), Length - i)
- End Sub
-
-
-
-
- Private Sub Final()
-
-
-
- Dim Index As Long, PadLen As Long
- Dim TempCount As Long
- TempCount = Count
-
-
-
-
-
-
- Call ZeroMemory(padding(1), 7)
- padding(0) = &H80
-
- Index = Count And &H3F
- PadLen = IIf(Index < 56, 56 - Index, 120 - Index)
- Call Update(padding, PadLen)
-
-
- Call CopyMemory(padding(0), TempCount * 8, 4)
- Call Update(padding, 8)
-
-
-
-
-
-
-
- End Sub
-
-
- Private Sub Transform(Block() As Byte)
-
- Dim a As Long, B As Long, c As Long, d As Long
- a = State(0)
- B = State(1)
- c = State(2)
- d = State(3)
- Dim X(0 To 15) As Long
- Call Decode(Block, X, 64)
-
-
- Call FF(a, B, c, d, X(0), S11, &HD76AA478)
- Call FF(d, a, B, c, X(1), S12, &HE8C7B756)
- Call FF(c, d, a, B, X(2), S13, &H242070DB)
- Call FF(B, c, d, a, X(3), S14, &HC1BDCEEE)
- Call FF(a, B, c, d, X(4), S11, &HF57C0FAF)
- Call FF(d, a, B, c, X(5), S12, &H4787C62A)
- Call FF(c, d, a, B, X(6), S13, &HA8304613)
- Call FF(B, c, d, a, X(7), S14, &HFD469501)
- Call FF(a, B, c, d, X(8), S11, &H698098D8)
- Call FF(d, a, B, c, X(9), S12, &H8B44F7AF)
- Call FF(c, d, a, B, X(10), S13, &HFFFF5BB1)
- Call FF(B, c, d, a, X(11), S14, &H895CD7BE)
- Call FF(a, B, c, d, X(12), S11, &H6B901122)
- Call FF(d, a, B, c, X(13), S12, &HFD987193)
- Call FF(c, d, a, B, X(14), S13, &HA679438E)
- Call FF(B, c, d, a, X(15), S14, &H49B40821)
-
-
- Call GG(a, B, c, d, X(1), S21, &HF61E2562)
- Call GG(d, a, B, c, X(6), S22, &HC040B340)
- Call GG(c, d, a, B, X(11), S23, &H265E5A51)
- Call GG(B, c, d, a, X(0), S24, &HE9B6C7AA)
- Call GG(a, B, c, d, X(5), S21, &HD62F105D)
- Call GG(d, a, B, c, X(10), S22, &H2441453)
- Call GG(c, d, a, B, X(15), S23, &HD8A1E681)
- Call GG(B, c, d, a, X(4), S24, &HE7D3FBC8)
- Call GG(a, B, c, d, X(9), S21, &H21E1CDE6)
- Call GG(d, a, B, c, X(14), S22, &HC33707D6)
- Call GG(c, d, a, B, X(3), S23, &HF4D50D87)
- Call GG(B, c, d, a, X(8), S24, &H455A14ED)
- Call GG(a, B, c, d, X(13), S21, &HA9E3E905)
- Call GG(d, a, B, c, X(2), S22, &HFCEFA3F8)
- Call GG(c, d, a, B, X(7), S23, &H676F02D9)
- Call GG(B, c, d, a, X(12), S24, &H8D2A4C8A)
-
-
- Call HH(a, B, c, d, X(5), S31, &HFFFA3942)
- Call HH(d, a, B, c, X(8), S32, &H8771F681)
- Call HH(c, d, a, B, X(11), S33, &H6D9D6122)
- Call HH(B, c, d, a, X(14), S34, &HFDE5380C)
- Call HH(a, B, c, d, X(1), S31, &HA4BEEA44)
- Call HH(d, a, B, c, X(4), S32, &H4BDECFA9)
- Call HH(c, d, a, B, X(7), S33, &HF6BB4B60)
- Call HH(B, c, d, a, X(10), S34, &HBEBFBC70)
- Call HH(a, B, c, d, X(13), S31, &H289B7EC6)
- Call HH(d, a, B, c, X(0), S32, &HEAA127FA)
- Call HH(c, d, a, B, X(3), S33, &HD4EF3085)
- Call HH(B, c, d, a, X(6), S34, &H4881D05)
- Call HH(a, B, c, d, X(9), S31, &HD9D4D039)
- Call HH(d, a, B, c, X(12), S32, &HE6DB99E5)
- Call HH(c, d, a, B, X(15), S33, &H1FA27CF8)
- Call HH(B, c, d, a, X(2), S34, &HC4AC5665)
-
-
- Call ii(a, B, c, d, X(0), S41, &HF4292244)
- Call ii(d, a, B, c, X(7), S42, &H432AFF97)
- Call ii(c, d, a, B, X(14), S43, &HAB9423A7)
- Call ii(B, c, d, a, X(5), S44, &HFC93A039)
- Call ii(a, B, c, d, X(12), S41, &H655B59C3)
- Call ii(d, a, B, c, X(3), S42, &H8F0CCC92)
- Call ii(c, d, a, B, X(10), S43, &HFFEFF47D)
- Call ii(B, c, d, a, X(1), S44, &H85845DD1)
- Call ii(a, B, c, d, X(8), S41, &H6FA87E4F)
- Call ii(d, a, B, c, X(15), S42, &HFE2CE6E0)
- Call ii(c, d, a, B, X(6), S43, &HA3014314)
- Call ii(B, c, d, a, X(13), S44, &H4E0811A1)
- Call ii(a, B, c, d, X(4), S41, &HF7537E82)
- Call ii(d, a, B, c, X(11), S42, &HBD3AF235)
- Call ii(c, d, a, B, X(2), S43, &H2AD7D2BB)
- Call ii(B, c, d, a, X(9), S44, &HEB86D391)
-
- State(0) = LongCycleAdd(State(0), a)
- State(1) = LongCycleAdd(State(1), B)
- State(2) = LongCycleAdd(State(2), c)
- State(3) = LongCycleAdd(State(3), d)
- End Sub
-
-
- Private Sub Encode(InputArr() As Long, OutputArr() As Byte, Length As Long)
- Call CopyMemory(OutputArr(0), InputArr(0), 64)
- End Sub
-
-
- Private Sub Decode(InputArr() As Byte, OutputArr() As Long, Length As Long)
- Call CopyMemory(OutputArr(0), InputArr(0), 64)
- End Sub
-
- Private Function LongCycleAdd(ByVal a As Long, ByVal B As Long, Optional ByVal c As Long = 0, Optional ByVal d As Long = 0) As Long
- Dim t As Double
- t = 0# + a + B + c + d
- Do While t < 0
- t = t + 4294967296#
- Loop
- Do While t >= 4294967296#
- t = t - 4294967296#
- Loop
- If t > 2147483647 Then t = t - 4294967296#
- LongCycleAdd = t
- End Function
-
- Private Function LongToString(ByVal Value As Long) As String
- Dim Arr(0 To 3) As Byte, t As Byte
- Call CopyMemory(Arr(0), Value, 4)
- t = Arr(0)
- Arr(0) = Arr(3)
- Arr(3) = t
- t = Arr(1)
- Arr(1) = Arr(2)
- Arr(2) = t
- Call CopyMemory(Value, Arr(0), 4)
- LongToString = Hex$(Value)
- If Len(LongToString) < 8 Then LongToString = String$(8 - Len(LongToString), "0") & LongToString
- End Function
-
-
- Private Sub Class_Initialize()
- Dim i As Long
- LongBits(0) = 1
- For i = 1 To 30
- LongBits(i) = LongBits(i - 1) * 2
- Next
- LongBits(31) = &H80000000
- End Sub
|