zoukankan      html  css  js  c++  java
  • MD5 Message Digest Algorithm in Visual Basic 6

    Attribute VB_Name = "basMD5"
    Option Explicit
    Option Base 0
    
    ' A VB6/VBA procedure for the MD5 message-digest algorithm
    ' as described in RFC 1321 by R. Rivest, April 1992
    
    ' First published 16 September 2005.
    ' Updated 2010-10-20 to fix ">" vs ">=" issue in uwAdd.
    '  --Thanks to Loek for this.
    '************************* COPYRIGHT NOTICE*************************
    ' This code was originally written in Visual Basic by David Ireland
    ' and is copyright (c) 2005-10 D.I. Management Services Pty Limited,
    ' all rights reserved.
    
    ' You are free to use this code as part of your own applications
    ' provided you keep this copyright notice intact and acknowledge
    ' its authorship with the words:
    
    '   "Contains cryptography software by David Ireland of
    '   DI Management Services Pty Ltd <www.di-mgt.com.au>."
    
    ' If you use it as part of a web site, please include a link
    ' to our site in the form
    ' <A HREF="http://www.di-mgt.com.au/crypto.html">Cryptography
    ' Software Code</a>
    
    ' This code may only be used as part of an application. It may
    ' not be reproduced or distributed separately by any means without
    ' the express written permission of the author.
    
    ' David Ireland and DI Management Services Pty Limited make no
    ' representations concerning either the merchantability of this
    ' software or the suitability of this software for any particular
    ' purpose. It is provided "as is" without express or implied
    ' warranty of any kind.
    
    ' The latest version of this source code can be downloaded from
    ' www.di-mgt.com.au/crypto.html.
    ' Comments and bug reports to http://www.di-mgt.com.au/contact.html
    '****************** END OF COPYRIGHT NOTICE*************************
    
    ' POSSIBLE SPEED-UPS
    ' 1. Use memory copy functions from Win32 API to copy bytes into
    '    32-bit words directly.
    ' 2. Write 16 x specific Rotate_Left_By_n functions with hardcoded
    '    multiplicands for each possible shift S11..S44;
    '    i.e. for n = 4-7, 9-12, 14-17, 20-23.
    
    Private Const MD5_BLK_LEN As Long = 64
    ' Constants for MD5Transform routine
    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
    ' Constants for unsigned word addition
    Private Const OFFSET_4 = 4294967296#
    Private Const MAXINT_4 = 2147483647
    
    ' TEST FUNCTIONS...
    ' MD5 test suite:
    ' MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
    ' MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
    ' MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
    ' MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
    ' MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
    ' MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
    ' d174ab98d277d9f5a5611c2c9f419d9f
    ' MD5 ("123456789012345678901234567890123456789012345678901234567890123456
    ' 78901234567890") = 57edf4a22be3c955ac49da2e2107b67a
    
    ' MD5 (1 million x 'a') = 7707d6ae4e027c70eea2a935c2296f21
    
    Public Function Test_md5_abc()
        Debug.Print MD5_string("abc")
    End Function
    
    Public Function md5_test_suite()
        Debug.Print MD5_string("")
        Debug.Print MD5_string("a")
        Debug.Print MD5_string("abc")
        Debug.Print MD5_string("message digest")
        Debug.Print MD5_string("abcdefghijklmnopqrstuvwxyz")
        Debug.Print MD5_string("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
        Debug.Print MD5_string("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
    End Function
    
    Public Function test_md5_empty()
        Debug.Print MD5_string("")
    End Function
    
    Public Function test_md5_around64()
        Dim strMessage As String
        strMessage = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
        Debug.Print MD5_string(strMessage)
        Debug.Print MD5_string(Left(strMessage, 65))
        Debug.Print MD5_string(Left(strMessage, 64))
        Debug.Print MD5_string(Left(strMessage, 63))
        Debug.Print MD5_string(Left(strMessage, 62))
        Debug.Print MD5_string(Left(strMessage, 57))
        Debug.Print MD5_string(Left(strMessage, 56))
        Debug.Print MD5_string(Left(strMessage, 55))
    End Function
    
    Public Function test_md5_million_a()
    ' This may take some time...
        Dim abMessage() As Byte
        Dim mLen As Long
        Dim i As Long
        mLen = 1000000
        ReDim abMessage(mLen - 1)
        For i = 0 To mLen - 1
            abMessage(i) = &H61     ' 0x61 = 'a'
        Next
        Debug.Print MD5_bytes(abMessage, mLen)
        
    End Function
    
    ' MAIN EXPORTED MD5 FUNCTIONS...
    
    Public Function MD5_string(strMessage As String) As String
    ' Returns 32-char hex string representation of message digest
    ' Input as a string (max length 2^29-1 bytes)
        Dim abMessage() As Byte
        Dim mLen As Long
        ' Cope with the empty string
        If Len(strMessage) > 0 Then
            abMessage = StrConv(strMessage, vbFromUnicode)
            ' Compute length of message in bytes
            mLen = UBound(abMessage) - LBound(abMessage) + 1
        End If
        MD5_string = MD5_bytes(abMessage, mLen)
    End Function
    
    Public Function MD5_bytes(abMessage() As Byte, mLen As Long) As String
    ' Returns 32-char hex string representation of message digest
    ' Input as an array of bytes of length mLen bytes
    
        Dim nBlks As Long
        Dim nBits As Long
        Dim block(MD5_BLK_LEN - 1) As Byte
        Dim state(3) As Long
        Dim wb(3) As Byte
        Dim sHex As String
        Dim index As Long
        Dim partLen As Long
        Dim i As Long
        Dim j As Long
        
        ' Catch length too big for VB arithmetic (268 million!)
        If mLen >= &HFFFFFFF Then Error 6     ' overflow
        
        ' Initialise
        ' Number of complete 512-bit/64-byte blocks to process
        nBlks = mLen \ MD5_BLK_LEN
        
        ' Load magic initialization constants
        state(0) = &H67452301
        state(1) = &HEFCDAB89
        state(2) = &H98BADCFE
        state(3) = &H10325476
        
        ' Main loop for each complete input block of 64 bytes
        index = 0
        For i = 0 To nBlks - 1
            Call md5_transform(state, abMessage, index)
            index = index + MD5_BLK_LEN
        Next
        
        ' Construct final block(s) with padding
        partLen = mLen Mod MD5_BLK_LEN
        index = nBlks * MD5_BLK_LEN
        For i = 0 To partLen - 1
            block(i) = abMessage(index + i)
        Next
        block(partLen) = &H80
        ' Make sure padding (and bit-length) set to zero
        For i = partLen + 1 To MD5_BLK_LEN - 1
            block(i) = 0
        Next
        ' Two cases: partLen is < or >= 56
        If partLen >= MD5_BLK_LEN - 8 Then
            ' Need two blocks
            Call md5_transform(state, block, 0)
            For i = 0 To MD5_BLK_LEN - 1
                block(i) = 0
            Next
        End If
        ' Append number of bits in little-endian order
        nBits = mLen * 8
        block(MD5_BLK_LEN - 8) = nBits And &HFF
        block(MD5_BLK_LEN - 7) = nBits \ &H100 And &HFF
        block(MD5_BLK_LEN - 6) = nBits \ &H10000 And &HFF
        block(MD5_BLK_LEN - 5) = nBits \ &H1000000 And &HFF
        ' (NB we don't try to cope with number greater than 2^31)
        
        ' Final padded block with bit length
        Call md5_transform(state, block, 0)
        
        ' Decode 4 x 32-bit words into 16 bytes with LSB first each time
        ' and return result as a hex string
        MD5_bytes = ""
        For i = 0 To 3
            Call uwSplit(state(i), wb(3), wb(2), wb(1), wb(0))
            For j = 0 To 3
                If wb(j) < 16 Then
                    sHex = "0" & Hex(wb(j))
                Else
                    sHex = Hex(wb(j))
                End If
                MD5_bytes = MD5_bytes & sHex
            Next
        Next
        
    End Function
    
    ' INTERNAL FUNCTIONS...
    
    Private Sub md5_transform(state() As Long, buf() As Byte, ByVal index As Long)
    ' Updates 4 x 32-bit values in state
    ' Input: the next 64 bytes in buf starting at offset index
    ' Assumes at least 64 bytes are present after offset index
        Dim a As Long
        Dim b As Long
        Dim c As Long
        Dim d As Long
        Dim j As Integer
        Dim x(15) As Long
        
        a = state(0)
        b = state(1)
        c = state(2)
        d = state(3)
        
        ' Decode the next 64 bytes into 16 words with LSB first
        For j = 0 To 15
            x(j) = uwJoin(buf(index + 3), buf(index + 2), buf(index + 1), buf(index))
            index = index + 4
        Next
        
        ' Round 1
        a = FF(a, b, c, d, x(0), S11, &HD76AA478)   ' 1
        d = FF(d, a, b, c, x(1), S12, &HE8C7B756)   ' 2
        c = FF(c, d, a, b, x(2), S13, &H242070DB)   ' 3
        b = FF(b, c, d, a, x(3), S14, &HC1BDCEEE)   ' 4
        a = FF(a, b, c, d, x(4), S11, &HF57C0FAF)   ' 5
        d = FF(d, a, b, c, x(5), S12, &H4787C62A)   ' 6
        c = FF(c, d, a, b, x(6), S13, &HA8304613)   ' 7
        b = FF(b, c, d, a, x(7), S14, &HFD469501)   ' 8
        a = FF(a, b, c, d, x(8), S11, &H698098D8)   ' 9
        d = FF(d, a, b, c, x(9), S12, &H8B44F7AF)   ' 10
        c = FF(c, d, a, b, x(10), S13, &HFFFF5BB1)  ' 11
        b = FF(b, c, d, a, x(11), S14, &H895CD7BE)  ' 12
        a = FF(a, b, c, d, x(12), S11, &H6B901122)  ' 13
        d = FF(d, a, b, c, x(13), S12, &HFD987193)  ' 14
        c = FF(c, d, a, b, x(14), S13, &HA679438E)  ' 15
        b = FF(b, c, d, a, x(15), S14, &H49B40821)  ' 16
        
        ' Round 2
        a = GG(a, b, c, d, x(1), S21, &HF61E2562)   ' 17
        d = GG(d, a, b, c, x(6), S22, &HC040B340)   ' 18
        c = GG(c, d, a, b, x(11), S23, &H265E5A51)  ' 19
        b = GG(b, c, d, a, x(0), S24, &HE9B6C7AA)   ' 20
        a = GG(a, b, c, d, x(5), S21, &HD62F105D)   ' 21
        d = GG(d, a, b, c, x(10), S22, &H2441453)   ' 22
        c = GG(c, d, a, b, x(15), S23, &HD8A1E681)  ' 23
        b = GG(b, c, d, a, x(4), S24, &HE7D3FBC8)   ' 24
        a = GG(a, b, c, d, x(9), S21, &H21E1CDE6)   ' 25
        d = GG(d, a, b, c, x(14), S22, &HC33707D6)  ' 26
        c = GG(c, d, a, b, x(3), S23, &HF4D50D87)   ' 27
        b = GG(b, c, d, a, x(8), S24, &H455A14ED)   ' 28
        a = GG(a, b, c, d, x(13), S21, &HA9E3E905)  ' 29
        d = GG(d, a, b, c, x(2), S22, &HFCEFA3F8)   ' 30
        c = GG(c, d, a, b, x(7), S23, &H676F02D9)   ' 31
        b = GG(b, c, d, a, x(12), S24, &H8D2A4C8A)  ' 32
        
        ' Round 3
        a = HH(a, b, c, d, x(5), S31, &HFFFA3942)   ' 33
        d = HH(d, a, b, c, x(8), S32, &H8771F681)   ' 34
        c = HH(c, d, a, b, x(11), S33, &H6D9D6122)  ' 35
        b = HH(b, c, d, a, x(14), S34, &HFDE5380C)  ' 36
        a = HH(a, b, c, d, x(1), S31, &HA4BEEA44)   ' 37
        d = HH(d, a, b, c, x(4), S32, &H4BDECFA9)   ' 38
        c = HH(c, d, a, b, x(7), S33, &HF6BB4B60)   ' 39
        b = HH(b, c, d, a, x(10), S34, &HBEBFBC70)  ' 40
        a = HH(a, b, c, d, x(13), S31, &H289B7EC6)  ' 41
        d = HH(d, a, b, c, x(0), S32, &HEAA127FA)   ' 42
        c = HH(c, d, a, b, x(3), S33, &HD4EF3085)   ' 43
        b = HH(b, c, d, a, x(6), S34, &H4881D05)    ' 44
        a = HH(a, b, c, d, x(9), S31, &HD9D4D039)   ' 45
        d = HH(d, a, b, c, x(12), S32, &HE6DB99E5)  ' 46
        c = HH(c, d, a, b, x(15), S33, &H1FA27CF8)  ' 47
        b = HH(b, c, d, a, x(2), S34, &HC4AC5665)   ' 48
        
        ' Round 4
        a = II(a, b, c, d, x(0), S41, &HF4292244)   ' 49
        d = II(d, a, b, c, x(7), S42, &H432AFF97)   ' 50
        c = II(c, d, a, b, x(14), S43, &HAB9423A7)  ' 51
        b = II(b, c, d, a, x(5), S44, &HFC93A039)   ' 52
        a = II(a, b, c, d, x(12), S41, &H655B59C3)  ' 53
        d = II(d, a, b, c, x(3), S42, &H8F0CCC92)   ' 54
        c = II(c, d, a, b, x(10), S43, &HFFEFF47D)  ' 55
        b = II(b, c, d, a, x(1), S44, &H85845DD1)   ' 56
        a = II(a, b, c, d, x(8), S41, &H6FA87E4F)   ' 57
        d = II(d, a, b, c, x(15), S42, &HFE2CE6E0)  ' 58
        c = II(c, d, a, b, x(6), S43, &HA3014314)   ' 59
        b = II(b, c, d, a, x(13), S44, &H4E0811A1)  ' 60
        a = II(a, b, c, d, x(4), S41, &HF7537E82)   ' 61
        d = II(d, a, b, c, x(11), S42, &HBD3AF235)  ' 62
        c = II(c, d, a, b, x(2), S43, &H2AD7D2BB)   ' 63
        b = II(b, c, d, a, x(9), S44, &HEB86D391)   ' 64
        
        state(0) = uwAdd(state(0), a)
        state(1) = uwAdd(state(1), b)
        state(2) = uwAdd(state(2), c)
        state(3) = uwAdd(state(3), d)
    
    End Sub
    
    ' FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4
    
    Private Function AddRotAdd(f As Long, a As Long, b As Long, x As Long, s As Integer, ac As Long) As Long
    ' Common routine for FF, GG, HH and II
    ' #define AddRotAdd(f, a, b, c, d, x, s, ac) { \
    '  (a) += f + (x) + (UINT4)(ac); \
    '  (a) = ROTATE_LEFT ((a), (s)); \
    '  (a) += (b); \
    '  }
        Dim temp As Long
        temp = uwAdd(a, f)
        temp = uwAdd(temp, x)
        temp = uwAdd(temp, ac)
        temp = uwRol(temp, s)
        AddRotAdd = uwAdd(temp, b)
    End Function
    
    Private Function FF(a As Long, b As Long, c As Long, d As Long, x As Long, s As Integer, ac As Long) As Long
    ' Returns new value of a
    ' #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
    ' #define FF(a, b, c, d, x, s, ac) { \
    '  (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
    '  (a) = ROTATE_LEFT ((a), (s)); \
    '  (a) += (b); \
    '  }
        Dim t As Long
        Dim t2 As Long
        ' F ((b), (c), (d)) = (((b) & (c)) | ((~b) & (d)))
        t = b And c
        t2 = (Not b) And d
        t = t Or t2
        FF = AddRotAdd(t, a, b, x, s, ac)
    End Function
    
    Private Function GG(a As Long, b As Long, c As Long, d As Long, x As Long, s As Integer, ac As Long) As Long
    ' #define G(b, c, d) (((b) & (d)) | ((c) & (~d)))
        Dim t As Long
        Dim t2 As Long
        t = b And d
        t2 = c And (Not d)
        t = t Or t2
        GG = AddRotAdd(t, a, b, x, s, ac)
    End Function
    
    Private Function HH(a As Long, b As Long, c As Long, d As Long, x As Long, s As Integer, ac As Long) As Long
    ' #define H(b, c, d) ((b) ^ (c) ^ (d))
        Dim t As Long
        t = b Xor c Xor d
        HH = AddRotAdd(t, a, b, x, s, ac)
    End Function
    
    Private Function II(a As Long, b As Long, c As Long, d As Long, x As Long, s As Integer, ac As Long) As Long
    ' #define I(b, c, d) ((c) ^ ((b) | (~d)))
        Dim t As Long
        t = b Or (Not d)
        t = c Xor t
        II = AddRotAdd(t, a, b, x, s, ac)
    End Function
    
    ' Unsigned 32-bit word functions suitable for VB/VBA
    
    Private Function uwRol(w As Long, s As Integer) As Long
    ' Return 32-bit word w rotated left by s bits
    ' avoiding problem with VB sign bit
        Dim i As Integer
        Dim t As Long
        
        uwRol = w
        For i = 1 To s
            t = uwRol And &H3FFFFFFF
            t = t * 2
            If (uwRol And &H40000000) <> 0 Then
                t = t Or &H80000000
            End If
            If (uwRol And &H80000000) <> 0 Then
                t = t Or &H1
            End If
            uwRol = t
        Next
    End Function
    
    Private Function uwJoin(a As Byte, b As Byte, c As Byte, d As Byte) As Long
    ' Join 4 x 8-bit bytes into one 32-bit word a.b.c.d
        uwJoin = ((a And &H7F) * &H1000000) Or (b * &H10000) Or (CLng(c) * &H100) Or d
        If a And &H80 Then
            uwJoin = uwJoin Or &H80000000
        End If
    End Function
    
    Private Sub uwSplit(ByVal w As Long, a As Byte, b As Byte, c As Byte, d As Byte)
    ' Split 32-bit word w into 4 x 8-bit bytes
        a = CByte(((w And &HFF000000) \ &H1000000) And &HFF)
        b = CByte(((w And &HFF0000) \ &H10000) And &HFF)
        c = CByte(((w And &HFF00) \ &H100) And &HFF)
        d = CByte((w And &HFF) And &HFF)
    End Sub
    
    Public Function uwAdd(wordA As Long, wordB As Long) As Long
    ' Adds words A and B avoiding overflow
        Dim myUnsigned As Double
        
        myUnsigned = LongToUnsigned(wordA) + LongToUnsigned(wordB)
        ' Cope with overflow
        '[2010-10-20] Changed from ">" to ">=". Thanks Loek.
        If myUnsigned >= OFFSET_4 Then
            myUnsigned = myUnsigned - OFFSET_4
        End If
        uwAdd = UnsignedToLong(myUnsigned)
        
    End Function
    
    '****************************************************
    ' These two functions from Microsoft Article Q189323
    ' "HOWTO: convert between Signed and Unsigned Numbers"
    
    Private Function UnsignedToLong(value As Double) As Long
        If value < 0 Or value >= OFFSET_4 Then Error 6 ' Overflow
        If value <= MAXINT_4 Then
            UnsignedToLong = value
        Else
            UnsignedToLong = value - OFFSET_4
        End If
    End Function
    
    Private Function LongToUnsigned(value As Long) As Double
        If value < 0 Then
            LongToUnsigned = value + OFFSET_4
        Else
            LongToUnsigned = value
        End If
    End Function
    
    ' End of Microsoft-article functions
    '****************************************************
    

      

    以下是我调用vb.net实现,需要引用一下.net类库:

    Public Function GetMD5Hash(ByVal StrToHash As String) As String
        Dim BytestoHash() As Byte
        Dim b As Variant
        Dim StrResult As String
        Dim Text As Object
        Dim SHA512 As Object
        Set Text = CreateObject("System.Text.UTF8Encoding")
        Set MD5 = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
        BytestoHash = Text.GetBytes_4(StrToHash)
        BytestoHash = MD5.ComputeHash_2(BytestoHash)
        For i = LBound(BytestoHash) To UBound(BytestoHash)
            StrResult = StrResult & Format(Hex(BytestoHash(i)), "00")
        Next
        GetMD5Hash = StrResult
    End Function
    

      

    refer to:http://www.di-mgt.com.au/crypto.html

  • 相关阅读:
    LeetCode 139. Word Break
    Amazon behavior question
    学习笔记之100 TOP Ikm C++ Online Test Questions
    学习笔记之IKM C++ 11
    学习笔记之C/C++指针使用常见的坑
    LeetCode 208. Implement Trie (Prefix Tree)
    队列 & 栈//岛屿的个数
    队列 & 栈//设计循环队列
    队列 & 栈//设计循环队列
    查找表类算法//存在重复元素 III
  • 原文地址:https://www.cnblogs.com/tewuapple/p/2914199.html
Copyright © 2011-2022 走看看