Hi,
This is the encapsulation of the MD5 algorithm in an easy to use class.
Updated with memory copy and memory fill powerbasic functions
Cheers
This is the encapsulation of the MD5 algorithm in an easy to use class.
Updated with memory copy and memory fill powerbasic functions
Cheers
Code:
#compile exe "md5.exe" #dim all ' ===================================================== #Include "win32api.inc" ' ===================================================== %S11 = 7 %S12 = 12 %S13 = 17 %S14 = 22 %S21 = 5 %S22 = 9 %S23 = 14 %S24 = 20 %S31 = 4 %S32 = 11 %S33 = 16 %S34 = 23 %S41 = 6 %S42 = 10 %S43 = 15 %S44 = 21 class MD5 instance lState() as Long 'state (ABCD) instance lCount() as Long 'number of bits modulo 2^64 (lsp first) instance Buf as Asciiz * 64 'input buffer class method create() Redim lState(4) as instance Long Redim lCount(1) as instance Long me.init() end method class method shiftRight(BYVAL lThis AS LONG, BYVAL lBits AS LONG) AS LONG SHIFT RIGHT lThis, lBits method = lThis end method class method shiftLeft(BYVAL lThis AS LONG, BYVAL lBits AS LONG) AS LONG SHIFT LEFT lThis, lBits method = lThis end method class method init() 'MD5 initialization. Begins an MD5 operation, writing a new context lCount(0) = 0 lCount(1) = 0 ' Load magic initialization constants. lState(0) = &H67452301 lState(1) = &HEFCDAB89 lState(2) = &H98BADCFE lState(3) = &H10325476 end method class method Transform (ByVal bBuf as Long Ptr) LOCAL a AS LONG LOCAL b AS LONG LOCAL c AS LONG LOCAL d AS LONG a = lState(0) b = lState(1) c = lState(2) d = lState(3) 'ROUND 1 a = a + ((((b)) AND ((c))) OR ((NOT (b)) AND ((d)))) + (@bBuf[ 0]) +&Hd76aa478 ROTATE LEFT a, %S11: a = a + b d = d + ((((a)) AND ((b))) OR ((NOT (a)) AND ((c)))) + (@bBuf[ 1]) +&He8c7b756 ROTATE LEFT d, %S12: d = d + a c = c + ((((d)) AND ((a))) OR ((NOT (d)) AND ((b)))) + (@bBuf[ 2]) +&H242070db ROTATE LEFT c, %S13: c = c + d b = b + ((((c)) AND ((d))) OR ((NOT (c)) AND ((a)))) + (@bBuf[ 3]) +&Hc1bdceee ROTATE LEFT b, %S14: b = b + c ' a = a + ((((b)) AND ((c))) OR ((NOT (b)) AND ((d)))) + (@bBuf[ 4]) +&Hf57c0faf ROTATE LEFT a, %S11: a = a + b d = d + ((((a)) AND ((b))) OR ((NOT (a)) AND ((c)))) + (@bBuf[ 5]) +&H4787c62a ROTATE LEFT d, %S12: d = d + a c = c + ((((d)) AND ((a))) OR ((NOT (d)) AND ((b)))) + (@bBuf[ 6]) +&Ha8304613 ROTATE LEFT c, %S13: c = c + d b = b + ((((c)) AND ((d))) OR ((NOT (c)) AND ((a)))) + (@bBuf[ 7]) +&Hfd469501 ROTATE LEFT b, %S14: b = b + c ' a = a + ((((b)) AND ((c))) OR ((NOT (b)) AND ((d)))) + (@bBuf[ 8]) +&H698098d8 ROTATE LEFT a, %S11: a = a + b d = d + ((((a)) AND ((b))) OR ((NOT (a)) AND ((c)))) + (@bBuf[ 9]) +&H8b44f7af ROTATE LEFT d, %S12: d = d + a c = c + ((((d)) AND ((a))) OR ((NOT (d)) AND ((b)))) + (@bBuf[10]) +&Hffff5bb1 ROTATE LEFT c, %S13: c = c + d b = b + ((((c)) AND ((d))) OR ((NOT (c)) AND ((a)))) + (@bBuf[11]) +&H895cd7be ROTATE LEFT b, %S14: b = b + c ' a = a + ((((b)) AND ((c))) OR ((NOT (b)) AND ((d)))) + (@bBuf[12]) +&H6b901122 ROTATE LEFT a, %S11: a = a + b d = d + ((((a)) AND ((b))) OR ((NOT (a)) AND ((c)))) + (@bBuf[13]) +&Hfd987193 ROTATE LEFT d, %S12: d = d + a c = c + ((((d)) AND ((a))) OR ((NOT (d)) AND ((b)))) + (@bBuf[14]) +&Ha679438e ROTATE LEFT c, %S13: c = c + d b = b + ((((c)) AND ((d))) OR ((NOT (c)) AND ((a)))) + (@bBuf[15]) +&H49b40821 ROTATE LEFT b, %S14: b = b + c 'ROUND 2 a = a + ((((b)) AND ((d))) OR (((c)) AND (NOT (d)))) + (@bBuf[ 1]) +&Hf61e2562 ROTATE LEFT a, %S21: a = a + b d = d + ((((a)) AND ((c))) OR (((b)) AND (NOT (c)))) + (@bBuf[ 6]) +&Hc040b340 ROTATE LEFT d, %S22: d = d + a c = c + ((((d)) AND ((b))) OR (((a)) AND (NOT (b)))) + (@bBuf[11]) +&H265e5a51 ROTATE LEFT c, %S23: c = c + d b = b + ((((c)) AND ((a))) OR (((d)) AND (NOT (a)))) + (@bBuf[ 0]) +&He9b6c7aa ROTATE LEFT b, %S24: b = b + c ' a = a + ((((b)) AND ((d))) OR (((c)) AND (NOT (d)))) + (@bBuf[ 5]) +&Hd62f105d ROTATE LEFT a, %S21: a = a + b d = d + ((((a)) AND ((c))) OR (((b)) AND (NOT (c)))) + (@bBuf[10]) +&H2441453 ROTATE LEFT d, %S22: d = d + a c = c + ((((d)) AND ((b))) OR (((a)) AND (NOT (b)))) + (@bBuf[15]) +&Hd8a1e681 ROTATE LEFT c, %S23: c = c + d b = b + ((((c)) AND ((a))) OR (((d)) AND (NOT (a)))) + (@bBuf[ 4]) +&He7d3fbc8 ROTATE LEFT b, %S24: b = b + c ' a = a + ((((b)) AND ((d))) OR (((c)) AND (NOT (d)))) + (@bBuf[ 9]) +&H21e1cde6 ROTATE LEFT a, %S21: a = a + b d = d + ((((a)) AND ((c))) OR (((b)) AND (NOT (c)))) + (@bBuf[14]) +&Hc33707d6 ROTATE LEFT d, %S22: d = d + a c = c + ((((d)) AND ((b))) OR (((a)) AND (NOT (b)))) + (@bBuf[ 3]) +&Hf4d50d87 ROTATE LEFT c, %S23: c = c + d b = b + ((((c)) AND ((a))) OR (((d)) AND (NOT (a)))) + (@bBuf[ 8]) +&H455a14ed ROTATE LEFT b, %S24: b = b + c ' a = a + ((((b)) AND ((d))) OR (((c)) AND (NOT (d)))) + (@bBuf[13]) +&Ha9e3e905 ROTATE LEFT a, %S21: a = a + b d = d + ((((a)) AND ((c))) OR (((b)) AND (NOT (c)))) + (@bBuf[ 2]) +&Hfcefa3f8 ROTATE LEFT d, %S22: d = d + a c = c + ((((d)) AND ((b))) OR (((a)) AND (NOT (b)))) + (@bBuf[ 7]) +&H676f02d9 ROTATE LEFT c, %S23: c = c + d b = b + ((((c)) AND ((a))) OR (((d)) AND (NOT (a)))) + (@bBuf[12]) +&H8d2a4c8a ROTATE LEFT b, %S24: b = b + c 'ROUND 3 a = a + (((b)) XOR ((c)) XOR ((d))) + (@bBuf[ 5]) +&Hfffa3942 ROTATE LEFT a, %S31: a = a + b d = d + (((a)) XOR ((b)) XOR ((c))) + (@bBuf[ 8]) +&H8771f681 ROTATE LEFT d, %S32: d = d + a c = c + (((d)) XOR ((a)) XOR ((b))) + (@bBuf[11]) +&H6d9d6122 ROTATE LEFT c, %S33: c = c + d b = b + (((c)) XOR ((d)) XOR ((a))) + (@bBuf[14]) +&Hfde5380c ROTATE LEFT b, %S34: b = b + c ' a = a + (((b)) XOR ((c)) XOR ((d))) + (@bBuf[ 1]) +&Ha4beea44 ROTATE LEFT a, %S31: a = a + b d = d + (((a)) XOR ((b)) XOR ((c))) + (@bBuf[ 4]) +&H4bdecfa9 ROTATE LEFT d, %S32: d = d + a c = c + (((d)) XOR ((a)) XOR ((b))) + (@bBuf[ 7]) +&Hf6bb4b60 ROTATE LEFT c, %S33: c = c + d b = b + (((c)) XOR ((d)) XOR ((a))) + (@bBuf[10]) +&Hbebfbc70 ROTATE LEFT b, %S34: b = b + c ' a = a + (((b)) XOR ((c)) XOR ((d))) + (@bBuf[13]) +&H289b7ec6 ROTATE LEFT a, %S31: a = a + b d = d + (((a)) XOR ((b)) XOR ((c))) + (@bBuf[ 0]) +&Heaa127fa ROTATE LEFT d, %S32: d = d + a c = c + (((d)) XOR ((a)) XOR ((b))) + (@bBuf[ 3]) +&Hd4ef3085 ROTATE LEFT c, %S33: c = c + d b = b + (((c)) XOR ((d)) XOR ((a))) + (@bBuf[ 6]) +&H4881d05 ROTATE LEFT b, %S34: b = b + c ' a = a + (((b)) XOR ((c)) XOR ((d))) + (@bBuf[ 9]) +&Hd9d4d039 ROTATE LEFT a, %S31: a = a + b d = d + (((a)) XOR ((b)) XOR ((c))) + (@bBuf[12]) +&He6db99e5 ROTATE LEFT d, %S32: d = d + a c = c + (((d)) XOR ((a)) XOR ((b))) + (@bBuf[15]) +&H1fa27cf8 ROTATE LEFT c, %S33: c = c + d b = b + (((c)) XOR ((d)) XOR ((a))) + (@bBuf[ 2]) +&Hc4ac5665 ROTATE LEFT b, %S34: b = b + c 'ROUND 4 a = a + (((c)) XOR (((b)) OR (NOT (d)))) + (@bBuf[ 0]) +&Hf4292244 ROTATE LEFT a, %S41: a = a + b d = d + (((b)) XOR (((a)) OR (NOT (c)))) + (@bBuf[ 7]) +&H432aff97 ROTATE LEFT d, %S42: d = d + a c = c + (((a)) XOR (((d)) OR (NOT (b)))) + (@bBuf[14]) +&Hab9423a7 ROTATE LEFT c, %S43: c = c + d b = b + (((d)) XOR (((c)) OR (NOT (a)))) + (@bBuf[ 5]) +&Hfc93a039 ROTATE LEFT b, %S44: b = b + c ' a = a + (((c)) XOR (((b)) OR (NOT (d)))) + (@bBuf[12]) +&H655b59c3 ROTATE LEFT a, %S41: a = a + b d = d + (((b)) XOR (((a)) OR (NOT (c)))) + (@bBuf[ 3]) +&H8f0ccc92 ROTATE LEFT d, %S42: d = d + a c = c + (((a)) XOR (((d)) OR (NOT (b)))) + (@bBuf[10]) +&Hffeff47d ROTATE LEFT c, %S43: c = c + d b = b + (((d)) XOR (((c)) OR (NOT (a)))) + (@bBuf[ 1]) +&H85845dd1 ROTATE LEFT b, %S44: b = b + c ' a = a + (((c)) XOR (((b)) OR (NOT (d)))) + (@bBuf[ 8]) +&H6fa87e4f ROTATE LEFT a, %S41: a = a + b d = d + (((b)) XOR (((a)) OR (NOT (c)))) + (@bBuf[15]) +&Hfe2ce6e0 ROTATE LEFT d, %S42: d = d + a c = c + (((a)) XOR (((d)) OR (NOT (b)))) + (@bBuf[ 6]) +&Ha3014314 ROTATE LEFT c, %S43: c = c + d b = b + (((d)) XOR (((c)) OR (NOT (a)))) + (@bBuf[13]) +&H4e0811a1 ROTATE LEFT b, %S44: b = b + c ' a = a + (((c)) XOR (((b)) OR (NOT (d)))) + (@bBuf[ 4]) +&Hf7537e82 ROTATE LEFT a, %S41: a = a + b d = d + (((b)) XOR (((a)) OR (NOT (c)))) + (@bBuf[11]) +&Hbd3af235 ROTATE LEFT d, %S42: d = d + a c = c + (((a)) XOR (((d)) OR (NOT (b)))) + (@bBuf[ 2]) +&H2ad7d2bb ROTATE LEFT c, %S43: c = c + d b = b + (((d)) XOR (((c)) OR (NOT (a)))) + (@bBuf[ 9]) +&Heb86d391 ROTATE LEFT b, %S44: b = b + c lState(0) = lState(0) + a lState(1) = lState(1) + b lState(2) = lState(2) + c lState(3) = lState(3) + d end method ' Update context TO reflect the concatenation of another buffer full ' of bytes. class method Update(BYVAL bBuf AS BYTE PTR, BYVAL dwLen AS DWORD ) Local t AS DWORD Local p AS BYTE PTR ' Update bitcount t = lCount(0) lCount(0) = t + me.shiftLeft( dwLen, 3 ) IF lCount(0) < t THEN INCR lCount(1) 'carry from low to high END IF lCount(1) = lCount(1) + me.shiftRight( dwLen, 29 ) t = ( me.shiftRight( t, 3) AND &H3F ) 'Bytes already IN shsInfo->DATA 'handle any leading odd-sized chunks IF ISTRUE(t) THEN p = VARPTR(buf) p = p + t t = 64 - t IF dwLen < t THEN 'CALL MoveMemory( BYVAL p, BYVAL bBuf, dwLen ) memory copy bBuf, p, dwlen exit method END IF 'CALL MoveMemory( BYVAL p, BYVAL bBuf, t ) MEMORY COPY bBuf, p, t me.Transform(VARPTR(buf)) bBuf = bBuf + t dwLen = dwLen - t END IF 'Process DATA IN 64-BYTE chunks DO WHILE (dwLen >= 64) 'CALL MoveMemory( BYVAL VARPTR(Buf), BYVAL bBuf, 64) memory copy bBuf, VarPtr(buf), 64 CALL me.Transform(VARPTR(Buf) ) bBuf = bBuf + 64 dwLen = dwLen - 64 LOOP 'handle any remaining bytes of data 'CALL MoveMemory( BYVAL VARPTR(buf), BYVAL bBuf, dwLen ) memory copy bBuf, VarPtr(buf), dwLen end method ' Final wrapup - pad TO 64-BYTE boundary WITH the BIT pattern ' 1 0* (64-BIT count of bits processed, MSB-first) class method Final( BYVAL bDigest AS BYTE PTR) LOCAL dwCount AS DWORD LOCAL p AS BYTE PTR LOCAL bBuffer AS BYTE PTR bBuffer = VARPTR(Buf) 'Compute number of bytes MOD 64 dwCount = (me.shiftRight(lCount(0), 3) AND &H3F ) 'set the first char of padding to &H80. This is safe since there is 'always AT least one BYTE free p = VARPTR(Buf) p = p + dwCount @p = &H80 INCR p ' Bytes of padding needed TO make 64 bytes dwCount = 64 - 1 - dwCount ' Pad out TO 56 MOD 64 if dwCount < 8 THEN 'two lots of padding: pad the first block to 64 bytes 'CALL FillMemory( p, dwCount, 0 ) memory fill p, dwCount, DWORD 0 CALL me.Transform(VARPTR(Buf) ) 'CALL FillMemory( byval VARPTR(Buf), 56, 0 ) memory fill varPtr(Buf), dwCount, DWORD 0 ELSE 'pad block to 56 bytes 'CALL FillMemory( byval p, (dwCount - 8), 0) memory fill p, dwCount - 8, DWORD 0 END IF 'append length IN bits and transform 'CALL MoveMemory( BYVAL VARPTR(@bBuffer[14 * SIZEOF(dwCount)]), BYVAL VARPTR(lCount(0)), SIZEOF(dwCount)) memory copy VarPtr(lCount(0)), VARPTR(@bBuffer[14 * SIZEOF(dwCount)]), sizeOf(dwCount) 'CALL MoveMemory( BYVAL VARPTR(@bBuffer[15 * SIZEOF(dwCount)]), BYVAL VARPTR(lCount(1)), SIZEOF(dwCount)) memory copy VarPtr(lCount(1)), VARPTR(@bBuffer[15 * SIZEOF(dwCount)]), sizeOf(dwCount) CALL me.Transform(VARPTR(Buf) ) 'CALL MoveMemory( BYVAL bDigest, BYVAL VARPTR(lState(0)), 16) memory copy varPtr(lState(0)), bDigest, 16 'Zeroise sensitive information ' CALL FillMemory( byval varptr(ctx), SIZEOF(ctx), 0) end method class method digest() AS STRING 'returns the MD5 digest as a hex string DIM sHex AS STRING DIM szDigest AS ASCIIZ * 16 DIM bDigest AS BYTE PTR DIM sCheck AS STRING DIM i AS LONG bDigest = VARPTR(szDigest) CALL me.Final( bDigest) IF bDigest <> %NULL THEN FOR i = 0 TO 15 sHex = sHex + HEX$(@bDigest[i],2) NEXT END IF method = sHex end method interface iMD5 inherit iDispatch method readFile(szFile AS ASCIIZ ) 'reads a file and calls md5_Update on the buffer 'md5_Init() MUST have been called prior to calling 'this function - call md5_Digest() afterwards to 'get the fingerprint LOCAL hFile AS Dword LOCAL szBuffer AS ASCIIZ * 1024 LOCAL lBufLen AS LONG LOCAL lLen AS LONG LOCAL lResult AS LONG LOCAL lToRead AS LONG LOCAL lToReadHigh AS LONG LOCAL lpBuffer AS LONG lBufLen = SIZEOF(szBuffer) lpBuffer = VARPTR(szBuffer) hFile = CreateFile( szFile, %GENERIC_READ, %FILE_SHARE_READ, _ BYVAL %NULL, %OPEN_EXISTING, %FILE_ATTRIBUTE_NORMAL, 0& ) IF hFile <> %INVALID_HANDLE_VALUE THEN lToRead = GetFileSize(hFile, lToReadHigh) md5_readFile_loop: Do lResult = ReadFile( hFile, BYVAL lpBuffer, lBufLen, lLen , BYVAL %NULL ) IF lResult = 0 THEN Exit Do End if me.Update(lpBuffer, lLen) lToRead = lToRead - lLen Loop until lResult = 0 or lToRead = 0 Call CloseHandle(hFile) END IF end method method Calc(ByVal sText as String) as String Local szText As ASCIIZ * 512 szText = sText me.init() me.update(VarPtr(szText), len(szText)) method = me.digest() end method end interface end class ' ===================================================== function pbmain() as long local oMD5 as iMD5 oMD5 = class "MD5" print oMD5.calc("hello") print oMD5.calc("hello") end function
Comment