` MD5 algorithm (Dan Gorrell) - Icetips Article
Icetips - Templates, Tools & Utilities for Clarion Developers

Templates, Tools and Utilities
for Clarion Developers

Icetips Article

Back to article list   Search Articles     Add Comment     Printer friendly     Direct link  

Windows API: MD5 algorithm
2004-03-17 -- Dan Gorrell
 
Newsgroups: softvelocity.public.clarion6 Here is a piece of a cyptography library that I'm working on. It's going to be a while before I am able to release the whole thing, so I thought I'd just toss this out there for free. This procedure takes a string and computes an RFC compliant MD5 hash. ! MD5FromString -- part of the DanCrypto Clarion Cryptography Library ! Copyright 2004 (C) by Daniel J. Gorrell ! You may use this code freely for personal, commercial, or other purposes so long as this ! copyright notice is maintained within the code. This code may not be redistributed as ! part of a programming library or template without written consent of the author. MD5FromString PROCEDURE(STRING myString) InputLen LONG TargetLen LONG ResultA CSTRING(9) ResultB CSTRING(9) ResultC CSTRING(9) ResultD CSTRING(9) Extras LONG DivTimes LONG ABuf LONG BBuf LONG CBuf LONG DBuf LONG AA LONG BB LONG CC LONG DD LONG myTempLong LONG myTempBytes GROUP,OVER(myTempLong) Byte1 BYTE Byte2 BYTE Byte3 BYTE Byte4 BYTE END ProcessingString &CSTRING my64BitLength GROUP myActualLong ULONG myPaddingLong ULONG END my64BitChars STRING(8),OVER(my64BitLength) myXBytes STRING(64) myXLongs ULONG,DIM(16),OVER(myXBytes) retval STRING(32) CODE !STEP 1 - Append padding bits !Get original string size InputLen = LEN(myString) !Determine the size of the target string IF InputLen > 55 THEN IF InputLen > 64 THEN DivTimes = ABS(InputLen/64) Extras = (InputLen - (DivTimes * 64)) IF Extras > 55 THEN TargetLen = InputLen + (120 - Extras) ELSE TargetLen = InputLen + (56 - Extras) END ELSE TargetLen = InputLen + (120 - InputLen) END ELSE TargetLen = InputLen + (56 - InputLen) END !Create CString that is TargetLen + 8 Bytes (for length) ProcessingString &= NEW(CSTRING(TargetLen + 8)) !Null out entire string (to add 0-bit padding) memset(ADDRESS(ProcessingString),00000000b,SIZE(ProcessingString)) !Copy original string into CString for processing ProcessingString[1:InputLen] = myString[1:InputLen] !Add one-bit padding byte to CString ProcessingString[InputLen+1] = CHR(128) !128 is base10 for 10000000b !STEP 2 - Append 64 bit representation of original message length to end my64BitLength.myPaddingLong = 00000000h my64BitLength.myActualLong = (InputLen * 8) ProcessingString[TargetLen+1:TargetLen+8] = my64BitChars[1:8] !STEP 3 - Initialize MD Buffers ABuf = 1732584193 BBuf = -271733879 CBuf = -1732584194 DBuf = 271733878 !STEP 4 - Process Message in 16-Word (LONG) Blocks LOOP i# = 64 TO SIZE(ProcessingString) BY 64 !Clear our processing buffer memset(ADDRESS(myXBytes),00000000b,64) !Load in 16 LONGS / 64 CHARS myXBytes[1:64] = ProcessingString[(i#-63):i#] LOOP j# = 1 TO 16 BY 1 myTempLong = 0000h myTempLong = BOR(myTempLong, BSHIFT(VAL( | ProcessingString[((i#-63)+(((J#-1)*4)+0))]),0)) myTempLong = BOR(myTempLong, BSHIFT(VAL( | ProcessingString[((i#-63)+(((J#-1)*4)+1))]),8)) myTempLong = BOR(myTempLong, BSHIFT(VAL( | ProcessingString[((i#-63)+(((J#-1)*4)+2))]),16)) myTempLong = BOR(myTempLong, BSHIFT(VAL( | ProcessingString[((i#-63)+(((J#-1)*4)+3))]),24)) myXLongs[j#] = myTempLong END AA = ABuf BB = BBuf CC = CBuf DD = DBuf SELF.MD5_FF(ABuf, BBuf, CBuf, DBuf, myXLongs[1], 7, -680876936) SELF.MD5_FF(DBuf, ABuf, BBuf, CBuf, myXLongs[2], 12, -389564586) SELF.MD5_FF(CBuf, DBuf, ABuf, BBuf, myXLongs[3], 17, 606105819) SELF.MD5_FF(BBuf, CBuf, DBuf, ABuf, myXLongs[4], 22, -1044525330) SELF.MD5_FF(ABuf, BBuf, CBuf, DBuf, myXLongs[5], 7, -176418897) SELF.MD5_FF(DBuf, ABuf, BBuf, CBuf, myXLongs[6], 12, 1200080426) SELF.MD5_FF(CBuf, DBuf, ABuf, BBuf, myXLongs[7], 17, -1473231341) SELF.MD5_FF(BBuf, CBuf, DBuf, ABuf, myXLongs[8], 22, -45705983) SELF.MD5_FF(ABuf, BBuf, CBuf, DBuf, myXLongs[9], 7, 1770035416) SELF.MD5_FF(DBuf, ABuf, BBuf, CBuf, myXLongs[10], 12, -1958414417) SELF.MD5_FF(CBuf, DBuf, ABuf, BBuf, myXLongs[11], 17, -42063) SELF.MD5_FF(BBuf, CBuf, DBuf, ABuf, myXLongs[12], 22, -1990404162) SELF.MD5_FF(ABuf, BBuf, CBuf, DBuf, myXLongs[13], 7, 1804603682) SELF.MD5_FF(DBuf, ABuf, BBuf, CBuf, myXLongs[14], 12, -40341101) SELF.MD5_FF(CBuf, DBuf, ABuf, BBuf, myXLongs[15], 17, -1502002290) SELF.MD5_FF(BBuf, CBuf, DBuf, ABuf, myXLongs[16], 22, 1236535329) SELF.MD5_GG(ABuf, BBuf, CBuf, DBuf, myXLongs[2], 5, -165796510) SELF.MD5_GG(DBuf, ABuf, BBuf, CBuf, myXLongs[7], 9, -1069501632) SELF.MD5_GG(CBuf, DBuf, ABuf, BBuf, myXLongs[12], 14, 643717713) SELF.MD5_GG(BBuf, CBuf, DBuf, ABuf, myXLongs[1], 20, -373897302) SELF.MD5_GG(ABuf, BBuf, CBuf, DBuf, myXLongs[6], 5, -701558691) SELF.MD5_GG(DBuf, ABuf, BBuf, CBuf, myXLongs[11], 9, 38016083) SELF.MD5_GG(CBuf, DBuf, ABuf, BBuf, myXLongs[16], 14, -660478335) SELF.MD5_GG(BBuf, CBuf, DBuf, ABuf, myXLongs[5], 20, -405537848) SELF.MD5_GG(ABuf, BBuf, CBuf, DBuf, myXLongs[10], 5, 568446438) SELF.MD5_GG(DBuf, ABuf, BBuf, CBuf, myXLongs[15], 9, -1019803690) SELF.MD5_GG(CBuf, DBuf, ABuf, BBuf, myXLongs[4], 14, -187363961) SELF.MD5_GG(BBuf, CBuf, DBuf, ABuf, myXLongs[9], 20, 1163531501) SELF.MD5_GG(ABuf, BBuf, CBuf, DBuf, myXLongs[14], 5, -1444681467) SELF.MD5_GG(DBuf, ABuf, BBuf, CBuf, myXLongs[3], 9, -51403784) SELF.MD5_GG(CBuf, DBuf, ABuf, BBuf, myXLongs[8], 14, 1735328473) SELF.MD5_GG(BBuf, CBuf, DBuf, ABuf, myXLongs[13], 20, -1926607734) SELF.MD5_HH(ABuf, BBuf, CBuf, DBuf, myXLongs[6], 4, -378558) SELF.MD5_HH(DBuf, ABuf, BBuf, CBuf, myXLongs[9], 11, -2022574463) SELF.MD5_HH(CBuf, DBuf, ABuf, BBuf, myXLongs[12], 16, 1839030562) SELF.MD5_HH(BBuf, CBuf, DBuf, ABuf, myXLongs[15], 23, -35309556) SELF.MD5_HH(ABuf, BBuf, CBuf, DBuf, myXLongs[2], 4, -1530992060) SELF.MD5_HH(DBuf, ABuf, BBuf, CBuf, myXLongs[5], 11, 1272893353) SELF.MD5_HH(CBuf, DBuf, ABuf, BBuf, myXLongs[8], 16, -155497632) SELF.MD5_HH(BBuf, CBuf, DBuf, ABuf, myXLongs[11], 23, -1094730640) SELF.MD5_HH(ABuf, BBuf, CBuf, DBuf, myXLongs[14], 4, 681279174) SELF.MD5_HH(DBuf, ABuf, BBuf, CBuf, myXLongs[1], 11, -358537222) SELF.MD5_HH(CBuf, DBuf, ABuf, BBuf, myXLongs[4], 16, -722521979) SELF.MD5_HH(BBuf, CBuf, DBuf, ABuf, myXLongs[7], 23, 76029189) SELF.MD5_HH(ABuf, BBuf, CBuf, DBuf, myXLongs[10], 4, -640364487) SELF.MD5_HH(DBuf, ABuf, BBuf, CBuf, myXLongs[13], 11, -421815835) SELF.MD5_HH(CBuf, DBuf, ABuf, BBuf, myXLongs[16], 16, 530742520) SELF.MD5_HH(BBuf, CBuf, DBuf, ABuf, myXLongs[3], 23, -995338651) SELF.MD5_II(ABuf, BBuf, CBuf, DBuf, myXLongs[1], 6, -198630844) SELF.MD5_II(DBuf, ABuf, BBuf, CBuf, myXLongs[8], 10, 1126891415) SELF.MD5_II(CBuf, DBuf, ABuf, BBuf, myXLongs[15], 15, -1416354905) SELF.MD5_II(BBuf, CBuf, DBuf, ABuf, myXLongs[6], 21, -57434055) SELF.MD5_II(ABuf, BBuf, CBuf, DBuf, myXLongs[13], 6, 1700485571) SELF.MD5_II(DBuf, ABuf, BBuf, CBuf, myXLongs[4], 10, -1894986606) SELF.MD5_II(CBuf, DBuf, ABuf, BBuf, myXLongs[11], 15, -1051523) SELF.MD5_II(BBuf, CBuf, DBuf, ABuf, myXLongs[2], 21, -2054922799) SELF.MD5_II(ABuf, BBuf, CBuf, DBuf, myXLongs[9], 6, 1873313359) SELF.MD5_II(DBuf, ABuf, BBuf, CBuf, myXLongs[16], 10, -30611744) SELF.MD5_II(CBuf, DBuf, ABuf, BBuf, myXLongs[7], 15, -1560198380) SELF.MD5_II(BBuf, CBuf, DBuf, ABuf, myXLongs[14], 21, 1309151649) SELF.MD5_II(ABuf, BBuf, CBuf, DBuf, myXLongs[5], 6, -145523070) SELF.MD5_II(DBuf, ABuf, BBuf, CBuf, myXLongs[12], 10, -1120210379) SELF.MD5_II(CBuf, DBuf, ABuf, BBuf, myXLongs[3], 15, 718787259) SELF.MD5_II(BBuf, CBuf, DBuf, ABuf, myXLongs[10], 21, -343485551) ABuf += AA BBuf += BB CBuf += CC DBuf += DD END LtoA(ABuf,ResultA,16) LtoA(BBuf,ResultB,16) LtoA(CBuf,ResultC,16) LtoA(DBuf,ResultD,16) IF LEN(ResultA) < 8 THEN LOOP i# = 1 TO (8 - LEN(ResultA)) BY 1 ResultA = '0' & ResultA END END IF LEN(ResultB) < 8 THEN LOOP i# = 1 TO (8 - LEN(ResultB)) BY 1 ResultB = '0' & ResultB END END IF LEN(ResultC) < 8 THEN LOOP i# = 1 TO (8 - LEN(ResultC)) BY 1 ResultC = '0' & ResultC END END IF LEN(ResultD) < 8 THEN LOOP i# = 1 TO (8 - LEN(ResultD)) BY 1 ResultD = '0' & ResultD END END retval = ResultA[7:8] & ResultA[5:6] & ResultA[3:4] & ResultA[1:2] & | ResultB[7:8] & ResultB[5:6] & ResultB[3:4] & ResultB[1:2] & | ResultC[7:8] & ResultC[5:6] & ResultC[3:4] & ResultC[1:2] & | ResultD[7:8] & ResultD[5:6] & ResultD[3:4] & ResultD[1:2] DISPOSE(ProcessingString) ProcessingString &= NULL RETURN(retval) You'll need the following in your map. MODULE('runtime library') LtoA(LONG,*CSTRING,SIGNED),ULONG,RAW,NAME('_ltoa'),PROC memcpy(LONG,LONG,UNSIGNED),NAME('_memcpy') memset(LONG,LONG,UNSIGNED),NAME('_memset') END You'll need to rename them to procedures instead of methods, and change the calls in the main procedure so they don't reference SELF. DanCrypt.MD5_FF PROCEDURE(*LONG mya, LONG myb, LONG myc, LONG myd, LONG myx, LONG mys, LONG myac) CODE mya = myb + SELF.MD5_RotateLeft((mya + BOR((BAND(myb,myc)),| (BAND(BXOR(myb,-1),myd))) + | myx + myac),mys) RETURN DanCrypt.MD5_GG PROCEDURE(*LONG mya, LONG myb, LONG myc, | LONG myd, LONG myx, LONG mys, | LONG myac) CODE mya = myb + SELF.MD5_RotateLeft((mya + BOR((BAND(myb,myd)),| (BAND(myc,(BXOR(myd,-1))))) + | myx + myac),mys) RETURN DanCrypt.MD5_HH PROCEDURE(*LONG mya, LONG myb, LONG myc, | LONG myd, LONG myx, LONG mys, | LONG myac) CODE mya = myb + SELF.MD5_RotateLeft((mya + BXOR((BXOR(myb,myc)),myd) + | myx + myac),mys) RETURN DanCrypt.MD5_II PROCEDURE(*LONG mya, LONG myb, LONG myc, | LONG myd, LONG myx, LONG mys, | LONG myac) CODE mya = myb + SELF.MD5_RotateLeft((mya + BXOR(myc,(BOR(myb,| (BXOR(myd,-1))))) + | myx + myac),mys) RETURN DanCrypt.MD5_RotateLeft PROCEDURE(LONG lValue, LONG iShiftBits) retval LONG CODE retval = (BOR(BSHIFT(lValue,iShiftBits),| BSHIFT(lValue, (-1 * (32 - iShiftBits))))) RETURN(retval)


Today is April 25, 2024, 8:28 pm
This article has been viewed 35108 times.
Google search has resulted in 280 hits on this article since January 25, 2004.



Back to article list   Search Articles   Add Comment   Printer friendly

Login

User Name:

Password: