一直都是用的这个MD5模块,没发现什么问题,可是在做taobaoapi时,问题来了,其它的参数都对,只是换个字串,taobao就返回Invalid Signature,即签名错误,之前是可以正确提交的,根本就没往MD5上去考虑,郁闷半天,才想到把生成的MD5去在线检验下,结果发现这个MD5模块是有BUG的,有些能校验对,有些却是错的
有错误的MD5模块:
PS:baidu上很多这上,这作者太不负责啦
Option Explicit Private Const OFFSET_4 = 4294967296# Private Const MAXINT_4 = 2147483647 Private State(4) As Long Private ByteCounter As Long Private ByteBuffer(63) As Byte Private Const S11 = 7 Private Const S12 = 12 Private Const S13 = 17 Private Const S14 = 22 Private Const S21 = 5 Private Const S22 = 9 Private Const S23 = 14 Private Const S24 = 20 Private Const S31 = 4 Private Const S32 = 11 Private Const S33 = 16 Private Const S34 = 23 Private Const S41 = 6 Private Const S42 = 10 Private Const S43 = 15 Private Const S44 = 21 Property Get RegisterA() As String RegisterA = State(1) End Property Property Get RegisterB() As String RegisterB = State(2) End Property Property Get RegisterC() As String RegisterC = State(3) End Property Property Get RegisterD() As String RegisterD = State(4) End Property Public Function Md5_String_Calc(SourceString As String) As String MD5Init MD5Update LenB(StrConv(SourceString,vbFromUnicode)),StringToArray(SourceString) MD5Final Md5_String_Calc = GetValues End Function Public Function Md5_File_Calc(InFile As String) As String On Error GoTo errorhandler GoSub begin errorhandler: Md5_File_Calc = "" Exit Function begin: Dim FileO As Integer FileO = FreeFile Call FileLen(InFile) Open InFile For Binary Access Read As #FileO MD5Init Do While Not EOF(FileO) Get #FileO,ByteBuffer If Loc(FileO) < LOF(FileO) Then ByteCounter = ByteCounter + 64 MD5Transform ByteBuffer End If Loop ByteCounter = ByteCounter + (LOF(FileO) Mod 64) Close #FileO MD5Final Md5_File_Calc = GetValues End Function Private Function StringToArray(InString As String) As Byte() Dim I As Integer,bytBuffer() As Byte ReDim bytBuffer(LenB(StrConv(InString,vbFromUnicode))) bytBuffer = StrConv(InString,vbFromUnicode) StringToArray = bytBuffer End Function Public Function GetValues() As String GetValues = LongToString(State(1)) & LongToString(State(2)) & LongToString(State(3)) & LongToString(State(4)) End Function Private Function LongToString(Num As Long) As String Dim A As Byte,B As Byte,C As Byte,d As Byte A = Num And &HFF& If A < 16 Then LongToString = "0" & Hex(A) Else LongToString = Hex(A) B = (Num And &HFF00&) \ 256 If B < 16 Then LongToString = LongToString & "0" & Hex(B) Else LongToString = LongToString & Hex(B) C = (Num And &HFF0000) \ 65536 If C < 16 Then LongToString = LongToString & "0" & Hex(C) Else LongToString = LongToString & Hex(C) If Num < 0 Then d = ((Num And &H7F000000) \ 16777216) Or &H80& Else d = (Num And &HFF000000) \ 16777216 If d < 16 Then LongToString = LongToString & "0" & Hex(d) Else LongToString = LongToString & Hex(d) End Function Public Sub MD5Init() ByteCounter = 0 State(1) = UnsignedToLong(1732584193#) State(2) = UnsignedToLong(4023233417#) State(3) = UnsignedToLong(2562383102#) State(4) = UnsignedToLong(271733878#) End Sub Public Sub MD5Final() Dim dblBits As Double,padding(72) As Byte,lngBytesBuffered As Long padding(0) = &H80 dblBits = ByteCounter * 8 lngBytesBuffered = ByteCounter Mod 64 If lngBytesBuffered <= 56 Then MD5Update 56 - lngBytesBuffered,padding Else MD5Update 120 - ByteCounter,padding padding(0) = UnsignedToLong(dblBits) And &HFF& padding(1) = UnsignedToLong(dblBits) \ 256 And &HFF& padding(2) = UnsignedToLong(dblBits) \ 65536 And &HFF& padding(3) = UnsignedToLong(dblBits) \ 16777216 And &HFF& padding(4) = 0 padding(5) = 0 padding(6) = 0 padding(7) = 0 MD5Update 8,padding End Sub Public Sub MD5Update(InputLen As Long,InputBuffer() As Byte) Dim II As Integer,I As Integer,J As Integer,K As Integer,lngBufferedBytes As Long,lngBufferRemaining As Long,lngRem As Long lngBufferedBytes = ByteCounter Mod 64 lngBufferRemaining = 64 - lngBufferedBytes ByteCounter = ByteCounter + InputLen If InputLen >= lngBufferRemaining Then For II = 0 To lngBufferRemaining - 1 ByteBuffer(lngBufferedBytes + II) = InputBuffer(II) Next II MD5Transform ByteBuffer lngRem = (InputLen) Mod 64 For I = lngBufferRemaining To InputLen - II - lngRem Step 64 For J = 0 To 63 ByteBuffer(J) = InputBuffer(I + J) Next J MD5Transform ByteBuffer Next I lngBufferedBytes = 0 Else I = 0 End If For K = 0 To InputLen - I - 1 ByteBuffer(lngBufferedBytes + K) = InputBuffer(I + K) Next K End Sub Private Sub MD5Transform(Buffer() As Byte) Dim X(16) As Long,A As Long,B As Long,C As Long,d As Long A = State(1) B = State(2) C = State(3) d = State(4) Decode 64,X,Buffer FF A,B,C,d,X(0),S11,-680876936 FF d,A,X(1),S12,-389564586 FF C,X(2),S13,606105819 FF B,X(3),S14,-1044525330 FF A,X(4),-176418897 FF d,X(5),1200080426 FF C,X(6),-1473231341 FF B,X(7),-45705983 FF A,X(8),1770035416 FF d,X(9),-1958414417 FF C,X(10),-42063 FF B,X(11),-1990404162 FF A,X(12),1804603682 FF d,X(13),-40341101 FF C,X(14),-1502002290 FF B,X(15),1236535329 GG A,S21,-165796510 GG d,S22,-1069501632 GG C,S23,643717713 GG B,S24,-373897302 GG A,-701558691 GG d,38016083 GG C,-660478335 GG B,-405537848 GG A,568446438 GG d,-1019803690 GG C,-187363961 GG B,1163531501 GG A,-1444681467 GG d,-51403784 GG C,1735328473 GG B,-1926607734 HH A,S31,-378558 HH d,S32,-2022574463 HH C,S33,1839030562 HH B,S34,-35309556 HH A,-1530992060 HH d,1272893353 HH C,-155497632 HH B,-1094730640 HH A,681279174 HH d,-358537222 HH C,-722521979 HH B,76029189 HH A,-640364487 HH d,-421815835 HH C,530742520 HH B,-995338651 II A,S41,-198630844 II d,S42,1126891415 II C,S43,-1416354905 II B,S44,-57434055 II A,1700485571 II d,-1894986606 II C,-1051523 II B,-2054922799 II A,1873313359 II d,-30611744 II C,-1560198380 II B,1309151649 II A,-145523070 II d,-1120210379 II C,718787259 II B,-343485551 State(1) = LongOverflowAdd(State(1),A) State(2) = LongOverflowAdd(State(2),B) State(3) = LongOverflowAdd(State(3),C) State(4) = LongOverflowAdd(State(4),d) End Sub Private Sub Decode(Length As Integer,OutputBuffer() As Long,InputBuffer() As Byte) Dim intDblIndex As Integer,intByteIndex As Integer,dblSum As Double For intByteIndex = 0 To Length - 1 Step 4 dblSum = InputBuffer(intByteIndex) + InputBuffer(intByteIndex + 1) * 256# + InputBuffer(intByteIndex + 2) * 65536# + InputBuffer(intByteIndex + 3) * 16777216# OutputBuffer(intDblIndex) = UnsignedToLong(dblSum) intDblIndex = intDblIndex + 1 Next intByteIndex End Sub Private Function FF(A As Long,d As Long,X As Long,S As Long,ac As Long) As Long A = LongOverflowAdd4(A,(B And C) Or (Not (B) And d),ac) A = LongLeftRotate(A,S) A = LongOverflowAdd(A,B) End Function Private Function GG(A As Long,(B And d) Or (C And Not (d)),B) End Function Private Function HH(A As Long,B Xor C Xor d,B) End Function Private Function II(A As Long,C Xor (B Or Not (d)),B) End Function Function LongLeftRotate(value As Long,Bits As Long) As Long Dim lngSign As Long,lngI As Long Bits = Bits Mod 32 If Bits = 0 Then LongLeftRotate = value: Exit Function For lngI = 1 To Bits lngSign = value And &HC0000000 value = (value And &H3FFFFFFF) * 2 value = value Or ((lngSign < 0) And 1) Or (CBool(lngSign And &H40000000) And &H80000000) Next LongLeftRotate = value End Function Private Function LongOverflowAdd(Val1 As Long,Val2 As Long) As Long Dim lngHighWord As Long,lngLowWord As Long,lngOverflow As Long lngLowWord = (Val1 And &HFFFF&) + (Val2 And &HFFFF&) lngOverflow = lngLowWord \ 65536 lngHighWord = (((Val1 And &HFFFF0000) \ 65536) + ((Val2 And &HFFFF0000) \ 65536) + lngOverflow) And &HFFFF& LongOverflowAdd = UnsignedToLong((lngHighWord * 65536#) + (lngLowWord And &HFFFF&)) End Function Private Function LongOverflowAdd4(Val1 As Long,Val2 As Long,val3 As Long,val4 As Long) As Long Dim lngHighWord As Long,lngOverflow As Long lngLowWord = (Val1 And &HFFFF&) + (Val2 And &HFFFF&) + (val3 And &HFFFF&) + (val4 And &HFFFF&) lngOverflow = lngLowWord \ 65536 lngHighWord = (((Val1 And &HFFFF0000) \ 65536) + ((Val2 And &HFFFF0000) \ 65536) + ((val3 And &HFFFF0000) \ 65536) + ((val4 And &HFFFF0000) \ 65536) + lngOverflow) And &HFFFF& LongOverflowAdd4 = UnsignedToLong((lngHighWord * 65536#) + (lngLowWord And &HFFFF&)) End Function Private Function UnsignedToLong(value As Double) As Long If value < 0 Or value >= OFFSET_4 Then Error 6 If value <= MAXINT_4 Then UnsignedToLong = value Else UnsignedToLong = value - OFFSET_4 End Function Private Function LongToUnsigned(value As Long) As Double If value < 0 Then LongToUnsigned = value + OFFSET_4 Else LongToUnsigned = value End Function
附一个正确的MD5模块:
Private Const BITS_TO_A_BYTE = 8 Private Const BYTES_TO_A_WORD = 4 Private Const BITS_TO_A_WORD = 32 Private m_lOnBits(30) Private m_l2Power(30) Private Function LShift(lValue,iShiftBits) If iShiftBits = 0 Then LShift = lValue Exit Function ElseIf iShiftBits = 31 Then If lValue And 1 Then LShift = &H80000000 Else LShift = 0 End If Exit Function ElseIf iShiftBits < 0 Or iShiftBits > 31 Then Err.Raise 6 End If If (lValue And m_l2Power(31 - iShiftBits)) Then LShift = ((lValue And m_lOnBits(31 - (iShiftBits + 1))) * m_l2Power(iShiftBits)) Or &H80000000 Else LShift = ((lValue And m_lOnBits(31 - iShiftBits)) * m_l2Power(iShiftBits)) End If End Function Private Function RShift(lValue,iShiftBits) If iShiftBits = 0 Then RShift = lValue Exit Function ElseIf iShiftBits = 31 Then If lValue And &H80000000 Then RShift = 1 Else RShift = 0 End If Exit Function ElseIf iShiftBits < 0 Or iShiftBits > 31 Then Err.Raise 6 End If RShift = (lValue And &H7FFFFFFE) \ m_l2Power(iShiftBits) If (lValue And &H80000000) Then RShift = (RShift Or (&H40000000 \ m_l2Power(iShiftBits - 1))) End If End Function Private Function RotateLeft(lValue,iShiftBits) RotateLeft = LShift(lValue,iShiftBits) Or RShift(lValue,(32 - iShiftBits)) End Function Private Function AddUnsigned(lX,lY) Dim lX4 Dim lY4 Dim lX8 Dim lY8 Dim lResult lX8 = lX And &H80000000 lY8 = lY And &H80000000 lX4 = lX And &H40000000 lY4 = lY And &H40000000 lResult = (lX And &H3FFFFFFF) + (lY And &H3FFFFFFF) If lX4 And lY4 Then lResult = lResult Xor &H80000000 Xor lX8 Xor lY8 ElseIf lX4 Or lY4 Then If lResult And &H40000000 Then lResult = lResult Xor &HC0000000 Xor lX8 Xor lY8 Else lResult = lResult Xor &H40000000 Xor lX8 Xor lY8 End If Else lResult = lResult Xor lX8 Xor lY8 End If AddUnsigned = lResult End Function Private Function md5_F(x,y,z) md5_F = (x And y) Or ((Not x) And z) End Function Private Function md5_G(x,z) md5_G = (x And z) Or (y And (Not z)) End Function Private Function md5_H(x,z) md5_H = (x Xor y Xor z) End Function Private Function md5_I(x,z) md5_I = (y Xor (x Or (Not z))) End Function Private Sub md5_FF(a,b,c,x,s,ac) a = AddUnsigned(a,AddUnsigned(AddUnsigned(md5_F(b,d),x),ac)) a = RotateLeft(a,s) a = AddUnsigned(a,b) End Sub Private Sub md5_GG(a,AddUnsigned(AddUnsigned(md5_G(b,b) End Sub Private Sub md5_HH(a,AddUnsigned(AddUnsigned(md5_H(b,b) End Sub Private Sub md5_II(a,AddUnsigned(AddUnsigned(md5_I(b,b) End Sub Private Function ConvertToWordArray(sMessage) Dim lMessageLength Dim lNumberOfWords Dim lWordArray() Dim lBytePosition Dim lByteCount Dim lWordCount Const MODULUS_BITS = 512 Const CONGRUENT_BITS = 448 lMessageLength = Len(sMessage) lNumberOfWords = (((lMessageLength + ((MODULUS_BITS - CONGRUENT_BITS) \ BITS_TO_A_BYTE)) \ (MODULUS_BITS \ BITS_TO_A_BYTE)) + 1) * (MODULUS_BITS \ BITS_TO_A_WORD) ReDim lWordArray(lNumberOfWords - 1) lBytePosition = 0 lByteCount = 0 Do Until lByteCount >= lMessageLength lWordCount = lByteCount \ BYTES_TO_A_WORD lBytePosition = (lByteCount Mod BYTES_TO_A_WORD) * BITS_TO_A_BYTE lWordArray(lWordCount) = lWordArray(lWordCount) Or LShift(Asc(Mid(sMessage,lByteCount + 1,1)),lBytePosition) lByteCount = lByteCount + 1 Loop lWordCount = lByteCount \ BYTES_TO_A_WORD lBytePosition = (lByteCount Mod BYTES_TO_A_WORD) * BITS_TO_A_BYTE lWordArray(lWordCount) = lWordArray(lWordCount) Or LShift(&H80,lBytePosition) lWordArray(lNumberOfWords - 2) = LShift(lMessageLength,3) lWordArray(lNumberOfWords - 1) = RShift(lMessageLength,29) ConvertToWordArray = lWordArray End Function Private Function WordToHex(lValue) Dim lByte Dim lCount For lCount = 0 To 3 lByte = RShift(lValue,lCount * BITS_TO_A_BYTE) And m_lOnBits(BITS_TO_A_BYTE - 1) WordToHex = WordToHex & Right("0" & Hex(lByte),2) Next End Function Public Function MD5(sMessage) As String m_lOnBits(0) = CLng(1) m_lOnBits(1) = CLng(3) m_lOnBits(2) = CLng(7) m_lOnBits(3) = CLng(15) m_lOnBits(4) = CLng(31) m_lOnBits(5) = CLng(63) m_lOnBits(6) = CLng(127) m_lOnBits(7) = CLng(255) m_lOnBits(8) = CLng(511) m_lOnBits(9) = CLng(1023) m_lOnBits(10) = CLng(2047) m_lOnBits(11) = CLng(4095) m_lOnBits(12) = CLng(8191) m_lOnBits(13) = CLng(16383) m_lOnBits(14) = CLng(32767) m_lOnBits(15) = CLng(65535) m_lOnBits(16) = CLng(131071) m_lOnBits(17) = CLng(262143) m_lOnBits(18) = CLng(524287) m_lOnBits(19) = CLng(1048575) m_lOnBits(20) = CLng(2097151) m_lOnBits(21) = CLng(4194303) m_lOnBits(22) = CLng(8388607) m_lOnBits(23) = CLng(16777215) m_lOnBits(24) = CLng(33554431) m_lOnBits(25) = CLng(67108863) m_lOnBits(26) = CLng(134217727) m_lOnBits(27) = CLng(268435455) m_lOnBits(28) = CLng(536870911) m_lOnBits(29) = CLng(1073741823) m_lOnBits(30) = CLng(2147483647) m_l2Power(0) = CLng(1) m_l2Power(1) = CLng(2) m_l2Power(2) = CLng(4) m_l2Power(3) = CLng(8) m_l2Power(4) = CLng(16) m_l2Power(5) = CLng(32) m_l2Power(6) = CLng(64) m_l2Power(7) = CLng(128) m_l2Power(8) = CLng(256) m_l2Power(9) = CLng(512) m_l2Power(10) = CLng(1024) m_l2Power(11) = CLng(2048) m_l2Power(12) = CLng(4096) m_l2Power(13) = CLng(8192) m_l2Power(14) = CLng(16384) m_l2Power(15) = CLng(32768) m_l2Power(16) = CLng(65536) m_l2Power(17) = CLng(131072) m_l2Power(18) = CLng(262144) m_l2Power(19) = CLng(524288) m_l2Power(20) = CLng(1048576) m_l2Power(21) = CLng(2097152) m_l2Power(22) = CLng(4194304) m_l2Power(23) = CLng(8388608) m_l2Power(24) = CLng(16777216) m_l2Power(25) = CLng(33554432) m_l2Power(26) = CLng(67108864) m_l2Power(27) = CLng(134217728) m_l2Power(28) = CLng(268435456) m_l2Power(29) = CLng(536870912) m_l2Power(30) = CLng(1073741824) Dim x Dim k Dim AA Dim BB Dim CC Dim DD Dim a Dim b Dim c Dim d Const S11 = 7 Const S12 = 12 Const S13 = 17 Const S14 = 22 Const S21 = 5 Const S22 = 9 Const S23 = 14 Const S24 = 20 Const S31 = 4 Const S32 = 11 Const S33 = 16 Const S34 = 23 Const S41 = 6 Const S42 = 10 Const S43 = 15 Const S44 = 21 x = ConvertToWordArray(sMessage) a = &H67452301 b = &HEFCDAB89 c = &H98BADCFE d = &H10325476 For k = 0 To UBound(x) Step 16 AA = a BB = b CC = c DD = d md5_FF a,x(k + 0),&HD76AA478 md5_FF d,a,x(k + 1),&HE8C7B756 md5_FF c,x(k + 2),&H242070DB md5_FF b,x(k + 3),&HC1BDCEEE md5_FF a,x(k + 4),&HF57C0FAF md5_FF d,x(k + 5),&H4787C62A md5_FF c,x(k + 6),&HA8304613 md5_FF b,x(k + 7),&HFD469501 md5_FF a,x(k + 8),&H698098D8 md5_FF d,x(k + 9),&H8B44F7AF md5_FF c,x(k + 10),&HFFFF5BB1 md5_FF b,x(k + 11),&H895CD7BE md5_FF a,x(k + 12),&H6B901122 md5_FF d,x(k + 13),&HFD987193 md5_FF c,x(k + 14),&HA679438E md5_FF b,x(k + 15),&H49B40821 md5_GG a,&HF61E2562 md5_GG d,&HC040B340 md5_GG c,&H265E5A51 md5_GG b,&HE9B6C7AA md5_GG a,&HD62F105D md5_GG d,&H2441453 md5_GG c,&HD8A1E681 md5_GG b,&HE7D3FBC8 md5_GG a,&H21E1CDE6 md5_GG d,&HC33707D6 md5_GG c,&HF4D50D87 md5_GG b,&H455A14ED md5_GG a,&HA9E3E905 md5_GG d,&HFCEFA3F8 md5_GG c,&H676F02D9 md5_GG b,&H8D2A4C8A md5_HH a,&HFFFA3942 md5_HH d,&H8771F681 md5_HH c,&H6D9D6122 md5_HH b,&HFDE5380C md5_HH a,&HA4BEEA44 md5_HH d,&H4BDECFA9 md5_HH c,&HF6BB4B60 md5_HH b,&HBEBFBC70 md5_HH a,&H289B7EC6 md5_HH d,&HEAA127FA md5_HH c,&HD4EF3085 md5_HH b,&H4881D05 md5_HH a,&HD9D4D039 md5_HH d,&HE6DB99E5 md5_HH c,&H1FA27CF8 md5_HH b,&HC4AC5665 md5_II a,&HF4292244 md5_II d,&H432AFF97 md5_II c,&HAB9423A7 md5_II b,&HFC93A039 md5_II a,&H655B59C3 md5_II d,&H8F0CCC92 md5_II c,&HFFEFF47D md5_II b,&H85845DD1 md5_II a,&H6FA87E4F md5_II d,&HFE2CE6E0 md5_II c,&HA3014314 md5_II b,&H4E0811A1 md5_II a,&HF7537E82 md5_II d,&HBD3AF235 md5_II c,&H2AD7D2BB md5_II b,&HEB86D391 a = AddUnsigned(a,AA) b = AddUnsigned(b,BB) c = AddUnsigned(c,CC) d = AddUnsigned(d,DD) Next MD5 = WordToHex(a) & WordToHex(b) & WordToHex(c) & WordToHex(d) 'MD5 = LCase(WordToHex(b) & WordToHex(c)) 'I crop this to fit 16byte database password End Function