VB6 MD5 存在的问题
(创建时间:2009年12月05日 23:31:00)
Jangogo : 

十年前,在开发财务软件的时候在网上找到一个 作者是: Robert Hubley.   的 VB6 的MD5算法,经过十年的使用,没有发现问题,因为我们使用MD5算法都只是用于密码加密,当近日做Dotnet应用的时候,居然发现这个算法有Bug! 当需要计算的字符串的长度为120-127之间的时候,或者是120的整数倍的到127的整数倍之间的MD5的结果和C#出来的结果不对,又在网上找了很多VB的MD5实现,发现当字符串长度为64*N+55 时候,计算结果和C#的结果也对不上。也就是说这两种实现都存在问题,网上基本上没有能够出来结果和C#完全一致的MD5 算法的VB实现。
费尽努力才找到一个:
经过测试,字符串长度1到1000都没有发现问题:

 
  1. Option Explicit   
  2.   
  3. Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)   
  4. Private Declare Sub ZeroMemory Lib "KERNEL32" Alias "RtlZeroMemory" (dest As Any, ByVal numBytes As Long)   
  5.   
  6. '/* Constants for MD5Transform routine. */   
  7. Private Const S11 As Long = 7   
  8. Private Const S12 As Long = 12   
  9. Private Const S13 As Long = 17   
  10. Private Const S14 As Long = 22   
  11. Private Const S21 As Long = 5   
  12. Private Const S22 As Long = 9   
  13. Private Const S23 As Long = 14   
  14. Private Const S24 As Long = 20   
  15. Private Const S31 As Long = 4   
  16. Private Const S32 As Long = 11   
  17. Private Const S33 As Long = 16   
  18. Private Const S34 As Long = 23   
  19. Private Const S41 As Long = 6   
  20. Private Const S42 As Long = 10   
  21. Private Const S43 As Long = 15   
  22. Private Const S44 As Long = 21   
  23.   
  24. Private LongBits(0 To 31) As Long  
  25.   
  26. Private padding(0 To 63) As Byte  
  27. Private Buffer(0 To 63) As Byte  
  28. Private State(0 To 3) As Long  
  29. Private Count As Long  
  30.   
  31. '/* ROTATE_LEFT rotates x left n bits.*/   
  32. Private Function ROTATE_LEFT(ByVal X As LongByVal n As LongAs Long  
  33.     Dim Aftern As Long, Beforen As Long  
  34.     Aftern = X And (LongBits(31 - n) - 1)   
  35.     Beforen = (X And &H7FFFFFFF) \ LongBits(32 - n)   
  36.     ROTATE_LEFT = Aftern * LongBits(n) Or Beforen   
  37.     If X And LongBits(31 - n) Then ROTATE_LEFT = ROTATE_LEFT Or &H80000000   
  38.     If X And &H80000000 Then ROTATE_LEFT = ROTATE_LEFT Or LongBits(n - 1)   
  39. End Function  
  40.   
  41. '/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.   
  42. 'Rotation is separate from addition to prevent recomputation.*/   
  43. Private Sub FF(ByRef a As Long, _   
  44.                ByVal B As Long, _   
  45.                ByVal c As Long, _   
  46.                ByVal d As Long, _   
  47.                ByVal X As Long, _   
  48.                ByVal s As Long, _   
  49.                ByVal ac As Long)   
  50.     a = LongCycleAdd(a, B And c Or Not B And d, X, ac)   
  51.     a = ROTATE_LEFT(a, s)   
  52.     a = LongCycleAdd(a, B)   
  53. End Sub  
  54.   
  55. Private Sub GG(ByRef a As Long, _   
  56.                ByVal B As Long, _   
  57.                ByVal c As Long, _   
  58.                ByVal d As Long, _   
  59.                ByVal X As Long, _   
  60.                ByVal s As Long, _   
  61.                ByVal ac As Long)   
  62.     a = LongCycleAdd(a, B And d Or c And Not d, X, ac)   
  63.     a = ROTATE_LEFT(a, s)   
  64.     a = LongCycleAdd(a, B)   
  65. End Sub  
  66.   
  67. Private Sub HH(ByRef a As Long, _   
  68.                ByVal B As Long, _   
  69.                ByVal c As Long, _   
  70.                ByVal d As Long, _   
  71.                ByVal X As Long, _   
  72.                ByVal s As Long, _   
  73.                ByVal ac As Long)   
  74.     a = LongCycleAdd(a, B Xor c Xor d, X, ac)   
  75.     a = ROTATE_LEFT(a, s)   
  76.     a = LongCycleAdd(a, B)   
  77. End Sub  
  78.   
  79. Private Sub ii(ByRef a As Long, _   
  80.                ByVal B As Long, _   
  81.                ByVal c As Long, _   
  82.                ByVal d As Long, _   
  83.                ByVal X As Long, _   
  84.                ByVal s As Long, _   
  85.                ByVal ac As Long)   
  86.     a = LongCycleAdd(a, c Xor B Or Not d, X, ac)   
  87.     a = ROTATE_LEFT(a, s)   
  88.     a = LongCycleAdd(a, B)   
  89. End Sub  
  90.   
  91.   
  92.   
  93. '/* Construct a MD5 object with a input buffer. */   
  94. Public Function DigestByteToHexStr(SourceByte() As ByteAs String  
  95.     Call ReSet   
  96.     Call Update(SourceByte, UBound(SourceByte) + 1)   
  97.     Call Final   
  98.     DigestByteToHexStr = LongToString(State(0)) & LongToString(State(1)) & LongToString(State(2)) & LongToString(State(3))   
  99. End Function  
  100.   
  101. '/* Construct a MD5 object with a string. */   
  102. Public Function DigestStrToHexStr(SourceString As StringAs String  
  103.     DigestStrToHexStr = DigestByteToHexStr(StrConv(SourceString, vbFromUnicode))   
  104. End Function  
  105.   
  106. '/* Construct a MD5 object with a file. */   
  107. Public Function DigestFileToHexStr(FilePath As StringAs String  
  108.     If Len(Dir$(FilePath)) Then  
  109.         Dim F1 As Long, FileBuffer(0 To 65535) As Byte, i As Long, j As Long  
  110.         F1 = FreeFile   
  111.         Open FilePath For Binary Access Read As #F1   
  112.         Call ReSet   
  113.        
  114.         For i = 1 To LOF(F1) \ 65536   
  115.             Get #F1, , FileBuffer   
  116.             Call Update(FileBuffer, UBound(FileBuffer) + 1)   
  117.         Next  
  118.         i = LOF(F1) And &HFFFF&   
  119.         If i Then  
  120.             Get #F1, , FileBuffer   
  121.             Call Update(FileBuffer, i)   
  122.         End If  
  123.        
  124.         Count = LOF(F1)   
  125.         Close #F1   
  126.         Call Final   
  127.         DigestFileToHexStr = LongToString(State(0)) & LongToString(State(1)) & LongToString(State(2)) & LongToString(State(3))   
  128.     End If  
  129. End Function  
  130.   
  131. '/* Reset the calculate state */   
  132. Private Sub ReSet()   
  133.     '/* reset number of bits. */   
  134.     Count = 0   
  135.     '/* Load magic initialization constants. */   
  136.     State(0) = &H67452301   
  137.     State(1) = &HEFCDAB89   
  138.     State(2) = &H98BADCFE   
  139.     State(3) = &H10325476   
  140. End Sub  
  141.   
  142. '/* MD5 block update operation. Continues an MD5 message-digest   
  143. 'operation, processing another message block, and updating thecontext.*/   
  144. Private Sub Update(InputArr() As Byte, Length As Long)   
  145.     Dim i As Long, Index As Long, PartLen As Long  
  146.     '/* Compute number of bytes mod 64 */   
  147.     Index = Count And &H3F   
  148.     '/* update number of bits */   
  149.     Count = Count + Length   
  150.     PartLen = 64 - Index   
  151.     '/* transform as many times as possible. */   
  152.     If Length >= PartLen Then  
  153.         Call CopyMemory(Buffer(Index), InputArr(0), PartLen)   
  154.         Call Transform(Buffer)   
  155.         For i = PartLen To Length - 64 Step 64   
  156.             Call CopyMemory(Buffer(Index), InputArr(i), 64)   
  157.             Call Transform(Buffer)   
  158.         Next  
  159.         Index = 0   
  160.     Else  
  161.         i = 0   
  162.     End If  
  163.     '/* Buffer remaining input */   
  164.     If Length - i > 0 Then Call CopyMemory(Buffer(Index), InputArr(i), Length - i)   
  165. End Sub  
  166.   
  167.   
  168. '/* MD5 finalization. Ends an MD5 message-_digest operation, writing the   
  169. 'the message _digest and zeroizing the context.*/   
  170. Private Sub Final()   
  171.     'byte bits[8];   
  172.     'uint32 oldState[4];   
  173.     'uint32 oldCount[2];   
  174.     Dim Index As Long, PadLen As Long  
  175.     Dim TempCount As Long  
  176.     TempCount = Count   
  177.     '/* Save current state and count. */   
  178.     'memcpy(oldState, _state, 16);   
  179.     'memcpy(oldCount, _count, 8);   
  180.   
  181.     '/* Save number of bits */   
  182.     'encode(_count, bits, 8);   
  183.     Call ZeroMemory(padding(1), 7)   
  184.     padding(0) = &H80   
  185.     '/* Pad out to 56 mod 64. */   
  186.     Index = Count And &H3F   
  187.     PadLen = IIf(Index < 56, 56 - Index, 120 - Index)   
  188.     Call Update(padding, PadLen)   
  189.   
  190.     '/* Append length (before padding) */   
  191.     Call CopyMemory(padding(0), TempCount * 8, 4)   
  192.     Call Update(padding, 8)   
  193.   
  194.     '/* Store state in digest */   
  195.     'encode(_state, _digest, 16);   
  196.   
  197.     '/* Restore current state and count. */   
  198.     'memcpy(_state, oldState, 16);   
  199.     'memcpy(_count, oldCount, 8);   
  200. End Sub  
  201.   
  202. '/* MD5 basic transformation. Transforms _state based on block. */   
  203. Private Sub Transform(Block() As Byte)   
  204.   
  205.     Dim a As Long, B As Long, c As Long, d As Long  
  206.     a = State(0)   
  207.     B = State(1)   
  208.     c = State(2)   
  209.     d = State(3)   
  210.     Dim X(0 To 15) As Long  
  211.     Call Decode(Block, X, 64)   
  212.   
  213.     '/* Round 1 */   
  214.     Call FF(a, B, c, d, X(0), S11, &HD76AA478)  ' /* 1 */   
  215.     Call FF(d, a, B, c, X(1), S12, &HE8C7B756)  ' /* 2 */   
  216.     Call FF(c, d, a, B, X(2), S13, &H242070DB)  ' /* 3 */   
  217.     Call FF(B, c, d, a, X(3), S14, &HC1BDCEEE)  ' /* 4 */   
  218.     Call FF(a, B, c, d, X(4), S11, &HF57C0FAF)  ' /* 5 */   
  219.     Call FF(d, a, B, c, X(5), S12, &H4787C62A)  ' /* 6 */   
  220.     Call FF(c, d, a, B, X(6), S13, &HA8304613)  ' /* 7 */   
  221.     Call FF(B, c, d, a, X(7), S14, &HFD469501)  ' /* 8 */   
  222.     Call FF(a, B, c, d, X(8), S11, &H698098D8)  ' /* 9 */   
  223.     Call FF(d, a, B, c, X(9), S12, &H8B44F7AF)  ' /* 10 */   
  224.     Call FF(c, d, a, B, X(10), S13, &HFFFF5BB1) ' /* 11 */   
  225.     Call FF(B, c, d, a, X(11), S14, &H895CD7BE) ' /* 12 */   
  226.     Call FF(a, B, c, d, X(12), S11, &H6B901122) ' /* 13 */   
  227.     Call FF(d, a, B, c, X(13), S12, &HFD987193) ' /* 14 */   
  228.     Call FF(c, d, a, B, X(14), S13, &HA679438E) ' /* 15 */   
  229.     Call FF(B, c, d, a, X(15), S14, &H49B40821) ' /* 16 */   
  230.   
  231.     '/* Round 2 */   
  232.     Call GG(a, B, c, d, X(1), S21, &HF61E2562)  ' /* 17 */   
  233.     Call GG(d, a, B, c, X(6), S22, &HC040B340)  ' /* 18 */   
  234.     Call GG(c, d, a, B, X(11), S23, &H265E5A51) ' /* 19 */   
  235.     Call GG(B, c, d, a, X(0), S24, &HE9B6C7AA)  ' /* 20 */   
  236.     Call GG(a, B, c, d, X(5), S21, &HD62F105D)  ' /* 21 */   
  237.     Call GG(d, a, B, c, X(10), S22, &H2441453)  ' /* 22 */   
  238.     Call GG(c, d, a, B, X(15), S23, &HD8A1E681) ' /* 23 */   
  239.     Call GG(B, c, d, a, X(4), S24, &HE7D3FBC8)  ' /* 24 */   
  240.     Call GG(a, B, c, d, X(9), S21, &H21E1CDE6)  ' /* 25 */   
  241.     Call GG(d, a, B, c, X(14), S22, &HC33707D6) ' /* 26 */   
  242.     Call GG(c, d, a, B, X(3), S23, &HF4D50D87)  ' /* 27 */   
  243.     Call GG(B, c, d, a, X(8), S24, &H455A14ED)  ' /* 28 */   
  244.     Call GG(a, B, c, d, X(13), S21, &HA9E3E905) ' /* 29 */   
  245.     Call GG(d, a, B, c, X(2), S22, &HFCEFA3F8)  ' /* 30 */   
  246.     Call GG(c, d, a, B, X(7), S23, &H676F02D9)  ' /* 31 */   
  247.     Call GG(B, c, d, a, X(12), S24, &H8D2A4C8A) ' /* 32 */   
  248.   
  249.     '/* Round 3 */   
  250.     Call HH(a, B, c, d, X(5), S31, &HFFFA3942)  ' /* 33 */   
  251.     Call HH(d, a, B, c, X(8), S32, &H8771F681)  ' /* 34 */   
  252.     Call HH(c, d, a, B, X(11), S33, &H6D9D6122) ' /* 35 */   
  253.     Call HH(B, c, d, a, X(14), S34, &HFDE5380C) ' /* 36 */   
  254.     Call HH(a, B, c, d, X(1), S31, &HA4BEEA44)  ' /* 37 */   
  255.     Call HH(d, a, B, c, X(4), S32, &H4BDECFA9)  ' /* 38 */   
  256.     Call HH(c, d, a, B, X(7), S33, &HF6BB4B60)  ' /* 39 */   
  257.     Call HH(B, c, d, a, X(10), S34, &HBEBFBC70) ' /* 40 */   
  258.     Call HH(a, B, c, d, X(13), S31, &H289B7EC6) ' /* 41 */   
  259.     Call HH(d, a, B, c, X(0), S32, &HEAA127FA)  ' /* 42 */   
  260.     Call HH(c, d, a, B, X(3), S33, &HD4EF3085)  ' /* 43 */   
  261.     Call HH(B, c, d, a, X(6), S34, &H4881D05)   ' /* 44 */   
  262.     Call HH(a, B, c, d, X(9), S31, &HD9D4D039)  ' /* 45 */   
  263.     Call HH(d, a, B, c, X(12), S32, &HE6DB99E5) ' /* 46 */   
  264.     Call HH(c, d, a, B, X(15), S33, &H1FA27CF8) ' /* 47 */   
  265.     Call HH(B, c, d, a, X(2), S34, &HC4AC5665)  ' /* 48 */   
  266.   
  267.     '/* Round 4 */   
  268.     Call ii(a, B, c, d, X(0), S41, &HF4292244)  ' /* 49 */   
  269.     Call ii(d, a, B, c, X(7), S42, &H432AFF97)  ' /* 50 */   
  270.     Call ii(c, d, a, B, X(14), S43, &HAB9423A7) ' /* 51 */   
  271.     Call ii(B, c, d, a, X(5), S44, &HFC93A039)  ' /* 52 */   
  272.     Call ii(a, B, c, d, X(12), S41, &H655B59C3) ' /* 53 */   
  273.     Call ii(d, a, B, c, X(3), S42, &H8F0CCC92)  ' /* 54 */   
  274.     Call ii(c, d, a, B, X(10), S43, &HFFEFF47D) ' /* 55 */   
  275.     Call ii(B, c, d, a, X(1), S44, &H85845DD1)  ' /* 56 */   
  276.     Call ii(a, B, c, d, X(8), S41, &H6FA87E4F)  ' /* 57 */   
  277.     Call ii(d, a, B, c, X(15), S42, &HFE2CE6E0) ' /* 58 */   
  278.     Call ii(c, d, a, B, X(6), S43, &HA3014314)  ' /* 59 */   
  279.     Call ii(B, c, d, a, X(13), S44, &H4E0811A1) ' /* 60 */   
  280.     Call ii(a, B, c, d, X(4), S41, &HF7537E82)  ' /* 61 */   
  281.     Call ii(d, a, B, c, X(11), S42, &HBD3AF235) ' /* 62 */   
  282.     Call ii(c, d, a, B, X(2), S43, &H2AD7D2BB)  ' /* 63 */   
  283.     Call ii(B, c, d, a, X(9), S44, &HEB86D391)  ' /* 64 */   
  284.   
  285.     State(0) = LongCycleAdd(State(0), a)   
  286.     State(1) = LongCycleAdd(State(1), B)   
  287.     State(2) = LongCycleAdd(State(2), c)   
  288.     State(3) = LongCycleAdd(State(3), d)   
  289. End Sub  
  290.   
  291. '/* Encodes input (ulong) into output (byte). Assumes length is a multiple of 4.*/   
  292. Private Sub Encode(InputArr() As Long, OutputArr() As Byte, Length As Long)   
  293.     Call CopyMemory(OutputArr(0), InputArr(0), 64)   
  294. End Sub  
  295.   
  296. '/* Decodes input (byte) into output (ulong). Assumes length is a multiple of 4.*/   
  297. Private Sub Decode(InputArr() As Byte, OutputArr() As Long, Length As Long)   
  298.     Call CopyMemory(OutputArr(0), InputArr(0), 64)   
  299. End Sub  
  300.   
  301. Private Function LongCycleAdd(ByVal a As LongByVal B As LongOptional ByVal c As Long = 0, Optional ByVal d As Long = 0) As Long  
  302.     Dim t As Double  
  303.     t = 0# + a + B + c + d   
  304.     Do While t < 0   
  305.         t = t + 4294967296#   
  306.     Loop  
  307.     Do While t >= 4294967296#   
  308.         t = t - 4294967296#   
  309.     Loop  
  310.     If t > 2147483647 Then t = t - 4294967296#   
  311.     LongCycleAdd = t   
  312. End Function  
  313.   
  314. Private Function LongToString(ByVal Value As LongAs String  
  315.     Dim Arr(0 To 3) As Byte, t As Byte  
  316.     Call CopyMemory(Arr(0), Value, 4)   
  317.     t = Arr(0)   
  318.     Arr(0) = Arr(3)   
  319.     Arr(3) = t   
  320.     t = Arr(1)   
  321.     Arr(1) = Arr(2)   
  322.     Arr(2) = t   
  323.     Call CopyMemory(Value, Arr(0), 4)   
  324.     LongToString = Hex$(Value)   
  325.     If Len(LongToString) < 8 Then LongToString = String$(8 - Len(LongToString), "0") & LongToString   
  326. End Function  
  327.   
  328.   
  329. Private Sub Class_Initialize()   
  330.     Dim i As Long  
  331.     LongBits(0) = 1   
  332.     For i = 1 To 30   
  333.         LongBits(i) = LongBits(i - 1) * 2   
  334.     Next  
  335.     LongBits(31) = &H80000000   
  336. End Sub  
文档中心