home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 5_2007-2008.ISO / data / Zips / TestRegist206899632007.psc / CMD5.cls < prev    next >
Text File  |  2001-05-27  |  31KB  |  765 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "CMD5"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. '*******************************************************************************
  15. ' MODULE:       CMD5
  16. ' FILENAME:     C:\My Code\vb\md5\CMD5.cls
  17. ' AUTHOR:       Phil Fresle
  18. ' CREATED:      16-Feb-2001
  19. ' COPYRIGHT:    Copyright 2001 Frez Systems Limited. All Rights Reserved.
  20. '
  21. ' DESCRIPTION:
  22. ' Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm,
  23. ' as set out in the memo RFC1321.
  24. '
  25. ' This class is used to generate an MD5 'digest' or 'signature' of a string. The
  26. ' MD5 algorithm is one of the industry standard methods for generating digital
  27. ' signatures. It is generically known as a digest, digital signature, one-way
  28. ' encryption, hash or checksum algorithm. A common use for MD5 is for password
  29. ' encryption as it is one-way in nature, that does not mean that your passwords
  30. ' are not free from a dictionary attack. If you are using the
  31. ' routine for passwords, you can make it a little more secure by concatenating
  32. ' some known random characters to the password before you generate the signature
  33. ' and on subsequent tests, so even if a hacker knows you are using MD5 for
  34. ' your passwords, the random characters will make it harder to dictionary attack.
  35. '
  36. ' *** CAUTION ***
  37. ' See the comment attached to the MD5 method below regarding use on systems
  38. ' with different character sets.
  39. '
  40. ' This is 'free' software with the following restrictions:
  41. '
  42. ' You may not redistribute this code as a 'sample' or 'demo'. However, you are free
  43. ' to use the source code in your own code, but you may not claim that you created
  44. ' the sample code. It is expressly forbidden to sell or profit from this source code
  45. ' other than by the knowledge gained or the enhanced value added by your own code.
  46. '
  47. ' Use of this software is also done so at your own risk. The code is supplied as
  48. ' is without warranty or guarantee of any kind.
  49. '
  50. ' Should you wish to commission some derivative work based on this code provided
  51. ' here, or any consultancy work, please do not hesitate to contact us.
  52. '
  53. ' Web Site:  http://www.frez.co.uk
  54. ' E-mail:    sales@frez.co.uk
  55. '
  56. ' MODIFICATION HISTORY:
  57. ' 1.0       16-Feb-2001
  58. '           Phil Fresle
  59. '           Initial Version
  60. '*******************************************************************************
  61. Option Explicit
  62.  
  63. Private Const BITS_TO_A_BYTE  As Long = 8
  64. Private Const BYTES_TO_A_WORD As Long = 4
  65. Private Const BITS_TO_A_WORD  As Long = BYTES_TO_A_WORD * BITS_TO_A_BYTE
  66.  
  67. Private m_lOnBits(0 To 30) As Long
  68. Private m_l2Power(0 To 30) As Long
  69.  
  70. '*******************************************************************************
  71. ' Class_Initialize (SUB)
  72. '
  73. ' DESCRIPTION:
  74. ' We will usually get quicker results by preparing arrays of bit patterns and
  75. ' powers of 2 ahead of time instead of calculating them every time, unless of
  76. ' course the methods are only ever getting called once per instantiation of the
  77. ' class.
  78. '*******************************************************************************
  79. Private Sub Class_Initialize()
  80.     ' Could have done this with a loop calculating each value, but simply
  81.     ' assigning the values is quicker - BITS SET FROM RIGHT
  82.     m_lOnBits(0) = 1            ' 00000000000000000000000000000001
  83.     m_lOnBits(1) = 3            ' 00000000000000000000000000000011
  84.     m_lOnBits(2) = 7            ' 00000000000000000000000000000111
  85.     m_lOnBits(3) = 15           ' 00000000000000000000000000001111
  86.     m_lOnBits(4) = 31           ' 00000000000000000000000000011111
  87.     m_lOnBits(5) = 63           ' 00000000000000000000000000111111
  88.     m_lOnBits(6) = 127          ' 00000000000000000000000001111111
  89.     m_lOnBits(7) = 255          ' 00000000000000000000000011111111
  90.     m_lOnBits(8) = 511          ' 00000000000000000000000111111111
  91.     m_lOnBits(9) = 1023         ' 00000000000000000000001111111111
  92.     m_lOnBits(10) = 2047        ' 00000000000000000000011111111111
  93.     m_lOnBits(11) = 4095        ' 00000000000000000000111111111111
  94.     m_lOnBits(12) = 8191        ' 00000000000000000001111111111111
  95.     m_lOnBits(13) = 16383       ' 00000000000000000011111111111111
  96.     m_lOnBits(14) = 32767       ' 00000000000000000111111111111111
  97.     m_lOnBits(15) = 65535       ' 00000000000000001111111111111111
  98.     m_lOnBits(16) = 131071      ' 00000000000000011111111111111111
  99.     m_lOnBits(17) = 262143      ' 00000000000000111111111111111111
  100.     m_lOnBits(18) = 524287      ' 00000000000001111111111111111111
  101.     m_lOnBits(19) = 1048575     ' 00000000000011111111111111111111
  102.     m_lOnBits(20) = 2097151     ' 00000000000111111111111111111111
  103.     m_lOnBits(21) = 4194303     ' 00000000001111111111111111111111
  104.     m_lOnBits(22) = 8388607     ' 00000000011111111111111111111111
  105.     m_lOnBits(23) = 16777215    ' 00000000111111111111111111111111
  106.     m_lOnBits(24) = 33554431    ' 00000001111111111111111111111111
  107.     m_lOnBits(25) = 67108863    ' 00000011111111111111111111111111
  108.     m_lOnBits(26) = 134217727   ' 00000111111111111111111111111111
  109.     m_lOnBits(27) = 268435455   ' 00001111111111111111111111111111
  110.     m_lOnBits(28) = 536870911   ' 00011111111111111111111111111111
  111.     m_lOnBits(29) = 1073741823  ' 00111111111111111111111111111111
  112.     m_lOnBits(30) = 2147483647  ' 01111111111111111111111111111111
  113.     
  114.     ' Could have done this with a loop calculating each value, but simply
  115.     ' assigning the values is quicker - POWERS OF 2
  116.     m_l2Power(0) = 1            ' 00000000000000000000000000000001
  117.     m_l2Power(1) = 2            ' 00000000000000000000000000000010
  118.     m_l2Power(2) = 4            ' 00000000000000000000000000000100
  119.     m_l2Power(3) = 8            ' 00000000000000000000000000001000
  120.     m_l2Power(4) = 16           ' 00000000000000000000000000010000
  121.     m_l2Power(5) = 32           ' 00000000000000000000000000100000
  122.     m_l2Power(6) = 64           ' 00000000000000000000000001000000
  123.     m_l2Power(7) = 128          ' 00000000000000000000000010000000
  124.     m_l2Power(8) = 256          ' 00000000000000000000000100000000
  125.     m_l2Power(9) = 512          ' 00000000000000000000001000000000
  126.     m_l2Power(10) = 1024        ' 00000000000000000000010000000000
  127.     m_l2Power(11) = 2048        ' 00000000000000000000100000000000
  128.     m_l2Power(12) = 4096        ' 00000000000000000001000000000000
  129.     m_l2Power(13) = 8192        ' 00000000000000000010000000000000
  130.     m_l2Power(14) = 16384       ' 00000000000000000100000000000000
  131.     m_l2Power(15) = 32768       ' 00000000000000001000000000000000
  132.     m_l2Power(16) = 65536       ' 00000000000000010000000000000000
  133.     m_l2Power(17) = 131072      ' 00000000000000100000000000000000
  134.     m_l2Power(18) = 262144      ' 00000000000001000000000000000000
  135.     m_l2Power(19) = 524288      ' 00000000000010000000000000000000
  136.     m_l2Power(20) = 1048576     ' 00000000000100000000000000000000
  137.     m_l2Power(21) = 2097152     ' 00000000001000000000000000000000
  138.     m_l2Power(22) = 4194304     ' 00000000010000000000000000000000
  139.     m_l2Power(23) = 8388608     ' 00000000100000000000000000000000
  140.     m_l2Power(24) = 16777216    ' 00000001000000000000000000000000
  141.     m_l2Power(25) = 33554432    ' 00000010000000000000000000000000
  142.     m_l2Power(26) = 67108864    ' 00000100000000000000000000000000
  143.     m_l2Power(27) = 134217728   ' 00001000000000000000000000000000
  144.     m_l2Power(28) = 268435456   ' 00010000000000000000000000000000
  145.     m_l2Power(29) = 536870912   ' 00100000000000000000000000000000
  146.     m_l2Power(30) = 1073741824  ' 01000000000000000000000000000000
  147. End Sub
  148.  
  149. '*******************************************************************************
  150. ' LShift (FUNCTION)
  151. '
  152. ' PARAMETERS:
  153. ' (In) - lValue     - Long    - The value to be shifted
  154. ' (In) - iShiftBits - Integer - The number of bits to shift the value by
  155. '
  156. ' RETURN VALUE:
  157. ' Long - The shifted long integer
  158. '
  159. ' DESCRIPTION:
  160. ' A left shift takes all the set binary bits and moves them left, in-filling
  161. ' with zeros in the vacated bits on the right. This function is equivalent to
  162. ' the << operator in Java and C++
  163. '*******************************************************************************
  164. Private Function LShift(ByVal lValue As Long, _
  165.                         ByVal iShiftBits As Integer) As Long
  166.     ' NOTE: If you can guarantee that the Shift parameter will be in the
  167.     ' range 1 to 30 you can safely strip of this first nested if structure for
  168.     ' speed.
  169.     '
  170.     ' A shift of zero is no shift at all.
  171.     If iShiftBits = 0 Then
  172.         LShift = lValue
  173.         Exit Function
  174.         
  175.     ' A shift of 31 will result in the right most bit becoming the left most
  176.     ' bit and all other bits being cleared
  177.     ElseIf iShiftBits = 31 Then
  178.         If lValue And 1 Then
  179.             LShift = &H80000000
  180.         Else
  181.             LShift = 0
  182.         End If
  183.         Exit Function
  184.         
  185.     ' A shift of less than zero or more than 31 is undefined
  186.     ElseIf iShiftBits < 0 Or iShiftBits > 31 Then
  187.         Err.Raise 6
  188.     End If
  189.     
  190.     ' If the left most bit that remains will end up in the negative bit
  191.     ' position (&H80000000) we would end up with an overflow if we took the
  192.     ' standard route. We need to strip the left most bit and add it back
  193.     ' afterwards.
  194.     If (lValue And m_l2Power(31 - iShiftBits)) Then
  195.     
  196.         ' (Value And OnBits(31 - (Shift + 1))) chops off the left most bits that
  197.         ' we are shifting into, but also the left most bit we still want as this
  198.         ' is going to end up in the negative bit marker position (&H80000000).
  199.         ' After the multiplication/shift we Or the result with &H80000000 to
  200.         ' turn the negative bit on.
  201.         LShift = ((lValue And m_lOnBits(31 - (iShiftBits + 1))) * _
  202.             m_l2Power(iShiftBits)) Or &H80000000
  203.     
  204.     Else
  205.     
  206.         ' (Value And OnBits(31-Shift)) chops off the left most bits that we are
  207.         ' shifting into so we do not get an overflow error when we do the
  208.         ' multiplication/shift
  209.         LShift = ((lValue And m_lOnBits(31 - iShiftBits)) * _
  210.             m_l2Power(iShiftBits))
  211.         
  212.     End If
  213. End Function
  214.  
  215. '*******************************************************************************
  216. ' RShift (FUNCTION)
  217. '
  218. ' PARAMETERS:
  219. ' (In) - lValue     - Long    - The value to be shifted
  220. ' (In) - iShiftBits - Integer - The number of bits to shift the value by
  221. '
  222. ' RETURN VALUE:
  223. ' Long - The shifted long integer
  224. '
  225. ' DESCRIPTION:
  226. ' The right shift of an unsigned long integer involves shifting all the set bits
  227. ' to the right and in-filling on the left with zeros. This function is
  228. ' equivalent to the >>> operator in Java or the >> operator in C++ when used on
  229. ' an unsigned long.
  230. '*******************************************************************************
  231. Private Function RShift(ByVal lValue As Long, _
  232.                         ByVal iShiftBits As Integer) As Long
  233.     
  234.     ' NOTE: If you can guarantee that the Shift parameter will be in the
  235.     ' range 1 to 30 you can safely strip of this first nested if structure for
  236.     ' speed.
  237.     '
  238.     ' A shift of zero is no shift at all
  239.     If iShiftBits = 0 Then
  240.         RShift = lValue
  241.         Exit Function
  242.         
  243.     ' A shift of 31 will clear all bits and move the left most bit to the right
  244.     ' most bit position
  245.     ElseIf iShiftBits = 31 Then
  246.         If lValue And &H80000000 Then
  247.             RShift = 1
  248.         Else
  249.             RShift = 0
  250.         End If
  251.         Exit Function
  252.         
  253.     ' A shift of less than zero or more than 31 is undefined
  254.     ElseIf iShiftBits < 0 Or iShiftBits > 31 Then
  255.         Err.Raise 6
  256.     End If
  257.     
  258.     ' We do not care about the top most bit or the final bit, the top most bit
  259.     ' will be taken into account in the next stage, the final bit (whether it
  260.     ' is an odd number or not) is being shifted into, so we do not give a jot
  261.     ' about it
  262.     RShift = (lValue And &H7FFFFFFE) \ m_l2Power(iShiftBits)
  263.     
  264.     ' If the top most bit (&H80000000) was set we need to do things differently
  265.     ' as in a normal VB signed long integer the top most bit is used to indicate
  266.     ' the sign of the number, when it is set it is a negative number, so just
  267.     ' deviding by a factor of 2 as above would not work.
  268.     ' NOTE: (lValue And  &H80000000) is equivalent to (lValue < 0), you could
  269.     ' get a very marginal speed improvement by changing the test to (lValue < 0)
  270.     If (lValue And &H80000000) Then
  271.         ' We take the value computed so far, and then add the left most negative
  272.         ' bit after it has been shifted to the right the appropriate number of
  273.         ' places
  274.         RShift = (RShift Or (&H40000000 \ m_l2Power(iShiftBits - 1)))
  275.     End If
  276. End Function
  277.  
  278. '*******************************************************************************
  279. ' RShiftSigned (FUNCTION)
  280. '
  281. ' PARAMETERS:
  282. ' (In) - lValue     - Long    -
  283. ' (In) - iShiftBits - Integer -
  284. '
  285. ' RETURN VALUE:
  286. ' Long -
  287. '
  288. ' DESCRIPTION:
  289. ' The right shift of a signed long integer involves shifting all the set bits to
  290. ' the right and in-filling on the left with the sign bit (0 if positive, 1 if
  291. ' negative. This function is equivalent to the >> operator in Java or the >>
  292. ' operator in C++ when used on a signed long integer. Not used in this class,
  293. ' but included for completeness.
  294. '*******************************************************************************
  295. Private Function RShiftSigned(ByVal lValue As Long, _
  296.                               ByVal iShiftBits As Integer) As Long
  297.     
  298.     ' NOTE: If you can guarantee that the Shift parameter will be in the
  299.     ' range 1 to 30 you can safely strip of this first nested if structure for
  300.     ' speed.
  301.     '
  302.     ' A shift of zero is no shift at all
  303.     If iShiftBits = 0 Then
  304.         RShiftSigned = lValue
  305.         Exit Function
  306.     
  307.     ' A shift of 31 will clear all bits if the left most bit was zero, and will
  308.     ' set all bits if the left most bit was 1 (a negative indicator)
  309.     ElseIf iShiftBits = 31 Then
  310.         
  311.         ' NOTE: (lValue And  &H80000000) is equivalent to (lValue < 0), you
  312.         ' could get a very marginal speed improvement by changing the test to
  313.         ' (lValue < 0)
  314.         If (lValue And &H80000000) Then
  315.             RShiftSigned = -1
  316.         Else
  317.             RShiftSigned = 0
  318.         End If
  319.         Exit Function
  320.     
  321.     ' A shift of less than zero or more than 31 is undefined
  322.     ElseIf iShiftBits < 0 Or iShiftBits > 31 Then
  323.         Err.Raise 6
  324.     End If
  325.     
  326.     ' We get the same result by dividing by the appropriate power of 2 and
  327.     ' rounding in the negative direction
  328.     RShiftSigned = Int(lValue / m_l2Power(iShiftBits))
  329. End Function
  330.  
  331. '*******************************************************************************
  332. ' RotateLeft (FUNCTION)
  333. '
  334. ' PARAMETERS:
  335. ' (In) - lValue     - Long    - Value to act on
  336. ' (In) - iShiftBits - Integer - Bits to move by
  337. '
  338. ' RETURN VALUE:
  339. ' Long - Result
  340. '
  341. ' DESCRIPTION:
  342. ' Rotates the bits in a long integer to the left, those bits falling off the
  343. ' left edge are put back on the right edge
  344. '*******************************************************************************
  345. Private Function RotateLeft(ByVal lValue As Long, _
  346.                             ByVal iShiftBits As Integer) As Long
  347.     RotateLeft = LShift(lValue, iShiftBits) Or RShift(lValue, (32 - iShiftBits))
  348. End Function
  349.  
  350. '*******************************************************************************
  351. ' AddUnsigned (FUNCTION)
  352. '
  353. ' PARAMETERS:
  354. ' (In) - lX - Long - First value
  355. ' (In) - lY - Long - Second value
  356. '
  357. ' RETURN VALUE:
  358. ' Long - Result
  359. '
  360. ' DESCRIPTION:
  361. ' Adds two potentially large unsigned numbers without overflowing
  362. '*******************************************************************************
  363. Private Function AddUnsigned(ByVal lX As Long, _
  364.                              ByVal lY As Long) As Long
  365.     Dim lX4     As Long
  366.     Dim lY4     As Long
  367.     Dim lX8     As Long
  368.     Dim lY8     As Long
  369.     Dim lResult As Long
  370.  
  371.     lX8 = lX And &H80000000
  372.     lY8 = lY And &H80000000
  373.     lX4 = lX And &H40000000
  374.     lY4 = lY And &H40000000
  375.  
  376.     lResult = (lX And &H3FFFFFFF) + (lY And &H3FFFFFFF)
  377.  
  378.     If lX4 And lY4 Then
  379.         lResult = lResult Xor &H80000000 Xor lX8 Xor lY8
  380.     ElseIf lX4 Or lY4 Then
  381.         If lResult And &H40000000 Then
  382.             lResult = lResult Xor &HC0000000 Xor lX8 Xor lY8
  383.         Else
  384.             lResult = lResult Xor &H40000000 Xor lX8 Xor lY8
  385.         End If
  386.     Else
  387.         lResult = lResult Xor lX8 Xor lY8
  388.     End If
  389.  
  390.     AddUnsigned = lResult
  391. End Function
  392.  
  393. '*******************************************************************************
  394. ' F (FUNCTION)
  395. '
  396. ' DESCRIPTION:
  397. ' MD5's F function
  398. '*******************************************************************************
  399. Private Function F(ByVal x As Long, _
  400.                    ByVal y As Long, _
  401.                    ByVal z As Long) As Long
  402.     F = (x And y) Or ((Not x) And z)
  403. End Function
  404.  
  405. '*******************************************************************************
  406. ' G (FUNCTION)
  407. '
  408. ' DESCRIPTION:
  409. ' MD5's G function
  410. '*******************************************************************************
  411. Private Function G(ByVal x As Long, _
  412.                    ByVal y As Long, _
  413.                    ByVal z As Long) As Long
  414.     G = (x And z) Or (y And (Not z))
  415. End Function
  416.  
  417. '*******************************************************************************
  418. ' H (FUNCTION)
  419. '
  420. ' DESCRIPTION:
  421. ' MD5's H function
  422. '*******************************************************************************
  423. Private Function H(ByVal x As Long, _
  424.                    ByVal y As Long, _
  425.                    ByVal z As Long) As Long
  426.     H = (x Xor y Xor z)
  427. End Function
  428.  
  429. '*******************************************************************************
  430. ' I (FUNCTION)
  431. '
  432. ' DESCRIPTION:
  433. ' MD5's I function
  434. '*******************************************************************************
  435. Private Function I(ByVal x As Long, _
  436.                    ByVal y As Long, _
  437.                    ByVal z As Long) As Long
  438.     I = (y Xor (x Or (Not z)))
  439. End Function
  440.  
  441. '*******************************************************************************
  442. ' FF (SUB)
  443. '
  444. ' DESCRIPTION:
  445. ' MD5's FF procedure
  446. '*******************************************************************************
  447. Private Sub FF(a As Long, _
  448.                ByVal b As Long, _
  449.                ByVal c As Long, _
  450.                ByVal d As Long, _
  451.                ByVal x As Long, _
  452.                ByVal s As Long, _
  453.                ByVal ac As Long)
  454.     a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac))
  455.     a = RotateLeft(a, s)
  456.     a = AddUnsigned(a, b)
  457. End Sub
  458.  
  459. '*******************************************************************************
  460. ' GG (SUB)
  461. '
  462. ' DESCRIPTION:
  463. ' MD5's GG procedure
  464. '*******************************************************************************
  465. Private Sub GG(a As Long, _
  466.                ByVal b As Long, _
  467.                ByVal c As Long, _
  468.                ByVal d As Long, _
  469.                ByVal x As Long, _
  470.                ByVal s As Long, _
  471.                ByVal ac As Long)
  472.     a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac))
  473.     a = RotateLeft(a, s)
  474.     a = AddUnsigned(a, b)
  475. End Sub
  476.  
  477. '*******************************************************************************
  478. ' HH (SUB)
  479. '
  480. ' DESCRIPTION:
  481. ' MD5's HH procedure
  482. '*******************************************************************************
  483. Private Sub HH(a As Long, _
  484.                ByVal b As Long, _
  485.                ByVal c As Long, _
  486.                ByVal d As Long, _
  487.                ByVal x As Long, _
  488.                ByVal s As Long, _
  489.                ByVal ac As Long)
  490.     a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac))
  491.     a = RotateLeft(a, s)
  492.     a = AddUnsigned(a, b)
  493. End Sub
  494.  
  495. '*******************************************************************************
  496. ' II (SUB)
  497. '
  498. ' DESCRIPTION:
  499. ' MD5's II procedure
  500. '*******************************************************************************
  501. Private Sub II(a As Long, _
  502.                ByVal b As Long, _
  503.                ByVal c As Long, _
  504.                ByVal d As Long, _
  505.                ByVal x As Long, _
  506.                ByVal s As Long, _
  507.                ByVal ac As Long)
  508.     a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac))
  509.     a = RotateLeft(a, s)
  510.     a = AddUnsigned(a, b)
  511. End Sub
  512.  
  513. '*******************************************************************************
  514. ' ConvertToWordArray (FUNCTION)
  515. '
  516. ' PARAMETERS:
  517. ' (In/Out) - sMessage - String - String message
  518. '
  519. ' RETURN VALUE:
  520. ' Long() - Converted message as long array
  521. '
  522. ' DESCRIPTION:
  523. ' Takes the string message and puts it in a long array with padding according to
  524. ' the MD5 rules. Note we are using only the first byte of each character with
  525. ' the AscB function, this may well mess up in unicode/dbcs situations where you
  526. ' are comparing what was generated on two different PCs with different
  527. ' character sets.
  528. '*******************************************************************************
  529. Private Function ConvertToWordArray(sMessage As String) As Long()
  530.     Dim lMessageLength  As Long
  531.     Dim lNumberOfWords  As Long
  532.     Dim lWordArray()    As Long
  533.     Dim lBytePosition   As Long
  534.     Dim lByteCount      As Long
  535.     Dim lWordCount      As Long
  536.     Dim lChar           As Long
  537.     
  538.     Const MODULUS_BITS      As Long = 512
  539.     Const CONGRUENT_BITS    As Long = 448
  540.     
  541.     lMessageLength = Len(sMessage)
  542.     
  543.     ' Get padded number of words. Message needs to be congruent to 448 bits,
  544.     ' modulo 512 bits. If it is exactly congruent to 448 bits, modulo 512 bits
  545.     ' it must still have another 512 bits added. 512 bits = 64 bytes
  546.     ' (or 16 * 4 byte words), 448 bits = 56 bytes. This means lMessageSize must
  547.     ' be a multiple of 16 (i.e. 16 * 4 (bytes) * 8 (bits))
  548.     lNumberOfWords = (((lMessageLength + _
  549.         ((MODULUS_BITS - CONGRUENT_BITS) \ BITS_TO_A_BYTE)) \ _
  550.         (MODULUS_BITS \ BITS_TO_A_BYTE)) + 1) * _
  551.         (MODULUS_BITS \ BITS_TO_A_WORD)
  552.     ReDim lWordArray(lNumberOfWords - 1)
  553.     
  554.     ' Combine each block of 4 bytes (ascii code of character) into one long
  555.     ' value and store in the message. The high-order (most significant) bit of
  556.     ' each byte is listed first. However, the low-order (least significant) byte
  557.     ' is given first in each word.
  558.     lBytePosition = 0
  559.     lByteCount = 0
  560.     Do Until lByteCount >= lMessageLength
  561.         ' Each word is 4 bytes
  562.         lWordCount = lByteCount \ BYTES_TO_A_WORD
  563.                 
  564.         ' The bytes are put in the word from the right most edge
  565.         lBytePosition = (lByteCount Mod BYTES_TO_A_WORD) * BITS_TO_A_BYTE
  566.         lChar = AscB(Mid(sMessage, lByteCount + 1, 1))
  567.         lWordArray(lWordCount) = lWordArray(lWordCount) Or LShift(lChar, lBytePosition)
  568.         lByteCount = lByteCount + 1
  569.     Loop
  570.  
  571.     ' Terminate according to MD5 rules with a 1 bit, zeros and the length in
  572.     ' bits stored in the last two words
  573.     lWordCount = lByteCount \ BYTES_TO_A_WORD
  574.     lBytePosition = (lByteCount Mod BYTES_TO_A_WORD) * BITS_TO_A_BYTE
  575.  
  576.     ' Add a terminating 1 bit, all the rest of the bits to the end of the
  577.     ' word array will default to zero
  578.     lWordArray(lWordCount) = lWordArray(lWordCount) Or LShift(&H80, lBytePosition)
  579.  
  580.     ' We put the length of the message in bits into the last two words, to get
  581.     ' the length in bits we need to multiply by 8 (or left shift 3). This left
  582.     ' shifted value is put in the first word. Any bits shifted off the left edge
  583.     ' need to be put in the second word, we can work out which bits by shifting
  584.     ' right the length by 29 bits.
  585.     lWordArray(lNumberOfWords - 2) = LShift(lMessageLength, 3)
  586.     lWordArray(lNumberOfWords - 1) = RShift(lMessageLength, 29)
  587.     
  588.     ConvertToWordArray = lWordArray
  589. End Function
  590.  
  591. '*******************************************************************************
  592. ' WordToHex (FUNCTION)
  593. '
  594. ' PARAMETERS:
  595. ' (In) - lValue - Long - Long value to convert
  596. '
  597. ' RETURN VALUE:
  598. ' String - Hex value to return
  599. '
  600. ' DESCRIPTION:
  601. ' Takes a long integer and due to the bytes reverse order it extracts the
  602. ' individual bytes and converts them to hex appending them for an overall hex
  603. ' value
  604. '*******************************************************************************
  605. Private Function WordToHex(ByVal lValue As Long) As String
  606.     Dim lByte As Long
  607.     Dim lCount As Long
  608.     
  609.     For lCount = 0 To 3
  610.         lByte = RShift(lValue, lCount * BITS_TO_A_BYTE) And _
  611.             m_lOnBits(BITS_TO_A_BYTE - 1)
  612.         WordToHex = WordToHex & Right("0" & Hex(lByte), 2)
  613.     Next
  614. End Function
  615.  
  616. '*******************************************************************************
  617. ' MD5 (FUNCTION)
  618. '
  619. ' PARAMETERS:
  620. ' (In/Out) - sMessage - String - String to be digested
  621. '
  622. ' RETURN VALUE:
  623. ' String - The MD5 digest
  624. '
  625. ' DESCRIPTION:
  626. ' This function takes a string message and generates an MD5 digest for it.
  627. ' sMessage can be up to the VB string length limit of 2^31 (approx. 2 billion)
  628. ' characters.
  629. '
  630. ' NOTE: Due to the way in which the string is processed the routine assumes a
  631. ' single byte character set. VB passes unicode (2-byte) character strings, the
  632. ' ConvertToWordArray function uses on the first byte for each character. This
  633. ' has been done this way for ease of use, to make the routine truely portable
  634. ' you could accept a byte array instead, it would then be up to the calling
  635. ' routine to make sure that the byte array is generated from their string in
  636. ' a manner consistent with the string type.
  637. '*******************************************************************************
  638. Public Function MD5(sMessage As String) As String
  639.     Dim x() As Long
  640.     Dim k   As Long
  641.     Dim AA  As Long
  642.     Dim BB  As Long
  643.     Dim CC  As Long
  644.     Dim DD  As Long
  645.     Dim a   As Long
  646.     Dim b   As Long
  647.     Dim c   As Long
  648.     Dim d   As Long
  649.     
  650.     Const S11 As Long = 7
  651.     Const S12 As Long = 12
  652.     Const S13 As Long = 17
  653.     Const S14 As Long = 22
  654.     Const S21 As Long = 5
  655.     Const S22 As Long = 9
  656.     Const S23 As Long = 14
  657.     Const S24 As Long = 20
  658.     Const S31 As Long = 4
  659.     Const S32 As Long = 11
  660.     Const S33 As Long = 16
  661.     Const S34 As Long = 23
  662.     Const S41 As Long = 6
  663.     Const S42 As Long = 10
  664.     Const S43 As Long = 15
  665.     Const S44 As Long = 21
  666.  
  667.     ' Steps 1 and 2.  Append padding bits and length and convert to words
  668.     x = ConvertToWordArray(sMessage)
  669.     
  670.     ' Step 3.  Initialise
  671.     a = &H67452301
  672.     b = &HEFCDAB89
  673.     c = &H98BADCFE
  674.     d = &H10325476
  675.  
  676.     ' Step 4.  Process the message in 16-word blocks
  677.     For k = 0 To UBound(x) Step 16
  678.         AA = a
  679.         BB = b
  680.         CC = c
  681.         DD = d
  682.     
  683.         ' The hex number on the end of each of the following procedure calls is
  684.         ' an element from the 64 element table constructed with
  685.         ' T(i) = Int(4294967296 * Abs(Sin(i))) where i is 1 to 64.
  686.         '
  687.         ' However, for speed we don't want to calculate the value every time.
  688.         FF a, b, c, d, x(k + 0), S11, &HD76AA478
  689.         FF d, a, b, c, x(k + 1), S12, &HE8C7B756
  690.         FF c, d, a, b, x(k + 2), S13, &H242070DB
  691.         FF b, c, d, a, x(k + 3), S14, &HC1BDCEEE
  692.         FF a, b, c, d, x(k + 4), S11, &HF57C0FAF
  693.         FF d, a, b, c, x(k + 5), S12, &H4787C62A
  694.         FF c, d, a, b, x(k + 6), S13, &HA8304613
  695.         FF b, c, d, a, x(k + 7), S14, &HFD469501
  696.         FF a, b, c, d, x(k + 8), S11, &H698098D8
  697.         FF d, a, b, c, x(k + 9), S12, &H8B44F7AF
  698.         FF c, d, a, b, x(k + 10), S13, &HFFFF5BB1
  699.         FF b, c, d, a, x(k + 11), S14, &H895CD7BE
  700.         FF a, b, c, d, x(k + 12), S11, &H6B901122
  701.         FF d, a, b, c, x(k + 13), S12, &HFD987193
  702.         FF c, d, a, b, x(k + 14), S13, &HA679438E
  703.         FF b, c, d, a, x(k + 15), S14, &H49B40821
  704.     
  705.         GG a, b, c, d, x(k + 1), S21, &HF61E2562
  706.         GG d, a, b, c, x(k + 6), S22, &HC040B340
  707.         GG c, d, a, b, x(k + 11), S23, &H265E5A51
  708.         GG b, c, d, a, x(k + 0), S24, &HE9B6C7AA
  709.         GG a, b, c, d, x(k + 5), S21, &HD62F105D
  710.         GG d, a, b, c, x(k + 10), S22, &H2441453
  711.         GG c, d, a, b, x(k + 15), S23, &HD8A1E681
  712.         GG b, c, d, a, x(k + 4), S24, &HE7D3FBC8
  713.         GG a, b, c, d, x(k + 9), S21, &H21E1CDE6
  714.         GG d, a, b, c, x(k + 14), S22, &HC33707D6
  715.         GG c, d, a, b, x(k + 3), S23, &HF4D50D87
  716.         GG b, c, d, a, x(k + 8), S24, &H455A14ED
  717.         GG a, b, c, d, x(k + 13), S21, &HA9E3E905
  718.         GG d, a, b, c, x(k + 2), S22, &HFCEFA3F8
  719.         GG c, d, a, b, x(k + 7), S23, &H676F02D9
  720.         GG b, c, d, a, x(k + 12), S24, &H8D2A4C8A
  721.             
  722.         HH a, b, c, d, x(k + 5), S31, &HFFFA3942
  723.         HH d, a, b, c, x(k + 8), S32, &H8771F681
  724.         HH c, d, a, b, x(k + 11), S33, &H6D9D6122
  725.         HH b, c, d, a, x(k + 14), S34, &HFDE5380C
  726.         HH a, b, c, d, x(k + 1), S31, &HA4BEEA44
  727.         HH d, a, b, c, x(k + 4), S32, &H4BDECFA9
  728.         HH c, d, a, b, x(k + 7), S33, &HF6BB4B60
  729.         HH b, c, d, a, x(k + 10), S34, &HBEBFBC70
  730.         HH a, b, c, d, x(k + 13), S31, &H289B7EC6
  731.         HH d, a, b, c, x(k + 0), S32, &HEAA127FA
  732.         HH c, d, a, b, x(k + 3), S33, &HD4EF3085
  733.         HH b, c, d, a, x(k + 6), S34, &H4881D05
  734.         HH a, b, c, d, x(k + 9), S31, &HD9D4D039
  735.         HH d, a, b, c, x(k + 12), S32, &HE6DB99E5
  736.         HH c, d, a, b, x(k + 15), S33, &H1FA27CF8
  737.         HH b, c, d, a, x(k + 2), S34, &HC4AC5665
  738.     
  739.         II a, b, c, d, x(k + 0), S41, &HF4292244
  740.         II d, a, b, c, x(k + 7), S42, &H432AFF97
  741.         II c, d, a, b, x(k + 14), S43, &HAB9423A7
  742.         II b, c, d, a, x(k + 5), S44, &HFC93A039
  743.         II a, b, c, d, x(k + 12), S41, &H655B59C3
  744.         II d, a, b, c, x(k + 3), S42, &H8F0CCC92
  745.         II c, d, a, b, x(k + 10), S43, &HFFEFF47D
  746.         II b, c, d, a, x(k + 1), S44, &H85845DD1
  747.         II a, b, c, d, x(k + 8), S41, &H6FA87E4F
  748.         II d, a, b, c, x(k + 15), S42, &HFE2CE6E0
  749.         II c, d, a, b, x(k + 6), S43, &HA3014314
  750.         II b, c, d, a, x(k + 13), S44, &H4E0811A1
  751.         II a, b, c, d, x(k + 4), S41, &HF7537E82
  752.         II d, a, b, c, x(k + 11), S42, &HBD3AF235
  753.         II c, d, a, b, x(k + 2), S43, &H2AD7D2BB
  754.         II b, c, d, a, x(k + 9), S44, &HEB86D391
  755.     
  756.         a = AddUnsigned(a, AA)
  757.         b = AddUnsigned(b, BB)
  758.         c = AddUnsigned(c, CC)
  759.         d = AddUnsigned(d, DD)
  760.     Next
  761.     
  762.     ' Step 5.  Output the 128 bit digest
  763.     MD5 = LCase(WordToHex(a) & WordToHex(b) & WordToHex(c) & WordToHex(d))
  764. End Function
  765.