Code:
' RC6 Speed = 550 m/s per Megabyte Encrypt, 530 m/s Decrypt ' In cryptography, RC6 is a symmetric key block cipher derived from RC5. ' It was designed by Ron Rivest, Matt Robshaw, Ray Sidney, and Yiqun Lisa Yin ' to meet the requirements of the Advanced Encryption Standard (AES) competition. ' ' The algorithm was one of the five finalists, and was also submitted to the NESSIE ' and CRYPTREC projects. It is a proprietary algorithm, patented by RSA Security. ' ' RC6 proper has a block size of 128 bits and supports key sizes of 128, 192 and 256 bits, ' but, like RC5, it can be parameterised to support a wide variety of word-lengths, ' key sizes and number of rounds. RC6 is very similar to RC5 in structure, ' using data-dependent rotations, modular addition and XOR operations; in fact, ' RC6 could be viewed as interweaving two parallel RC5 encryption processes. ' ' However, RC6 does use an extra multiplication operation not present in RC5 in ' order to make the rotation dependent on every bit in a word, and not just the ' least significant few bits. ' ' ' As RC6 has not been selected for the AES, it is not guaranteed that RC6 ' is royalty-free. As of January 2007, a web page on the official web site ' of the designers of RC6, RSA Laboratories, states the following: ' "We emphasize that if RC6 is selected for the AES, RSA Security will ' not require any licensing or royalty payments for products using the algorithm". ' The emphasis on the word "if" suggests that RSA Security Inc. may now require ' licensing and royalty payments for any products using the RC6 algorithm. ' RC6 is a patented encryption algorithm ' RC6, an encryption algorithm designed by Ron Rivest (RSA Labs) and submitted as a candidate algorithm for the ' Advanced Encryption Standard programme of the US National Institute of Standards and Technology." ' Ported to PB from "C" by Aleksandr Dobrev - Thanks to wonsky Lu for provide source on C ' Ver. 0.0.1 December 03, 2006 ' Padding and testbed Mike Trader 2007 #COMPILE EXE #DIM ALL #INCLUDE "win32api.inc" %LITTLE_ENDIAN = 1 ' For Little Endian Machines ' Utility macros MACRO zbs(xx) = STRING$(xx, 0) MACRO FUNCTION rotr(x,n) MACROTEMP s DIM s AS DWORD s = (x) ROTATE RIGHT s,n END MACRO = s '#define rotl(x,n) (((x) << ((INT)((n) & 0x1f))) | ((x) >> ((INT)((32 - ((n) & 0x1f)))))) MACRO FUNCTION rotl(x,n) MACROTEMP s DIM s AS DWORD s = (x) ROTATE LEFT s,n END MACRO = s ' PUT OR GET a 32 BIT WORD (v) IN machine order FROM a BYTE address IN (x) #IF %DEF(%LITTLE_ENDIAN) '#define u4byte_in(x) (*(u4byte*)(x)) MACRO FUNCTION u4byte_in(x) MACROTEMP pdwZmacro DIM pdwZmacro AS DWORD PTR pdwZmacro = (x) END MACRO = @pdwZmacro '#define u4byte_out(x,v) (*(u4byte*)(x) = (v)) MACRO u4byte_out(x,v) MACROTEMP pdwZmacro DIM pdwZmacro AS DWORD PTR pdwZmacro = (x) @pdwZmacro = v END MACRO #ELSE '#define u4byte_in(x) bswap(*(u4byte)(x)) MACRO u4byte_in(x) MACROTEMP dwZmacro DIM pdwZmacro AS DWORD PTR pdwZmacro = (x) @pdwZmacro = bswap(@z) END MACRO '#define u4byte_out(x, v) (*(u4byte*)(x) = bswap(v)) MACRO u4byte_out(x, v) MACROTEMP pdwZmacro DIM pdwZmacro AS DWORD PTR pdwZmacro = (x) @pdwZmacro = bswap(v) END MACRO #ENDIF MACRO f_rnd(i,a,b,c,d) MACROTEMP u,t DIM u AS DWORD,t AS DWORD u = rotl(d * (d + d + 1), 5) t = rotl(b * (b + b + 1), 5) a = rotl(a XOR t, u) + RC6Key(i) c = rotl(c XOR u, t) + RC6Key(i + 1) END MACRO MACRO i_rnd(i,a,b,c,d) MACROTEMP u,t DIM u AS DWORD,t AS DWORD u = rotl(d * (d + d + 1), 5) t = rotl(b * (b + b + 1), 5) c = rotr(c - RC6Key(i + 1), t) XOR u a = rotr(a - RC6Key(i), u) XOR t END MACRO UNION ConvertTwoByteTYPE ' Converts a Two Byte Value str AS STRING * 02 igr AS INTEGER wrd AS WORD byt(1 TO 2) AS BYTE END UNION GLOBAL CvtTwoByte AS ConvertTwoByteTYPE '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤' SUB time_stamp_count(tick AS QUAD) ' CPU Clock count Charles E V Pegge '---------------------------' ' ' approx because it is not a serialised instruction ' ' it may execute before or after other instructions ' ' in the pipeline. ! mov ebx,tick ' var address where count is to be stored. ! db &h0f,&h31 ' RDTSC read time-stamp counter into edx:eax hi lo. ! mov [ebx],eax ' save low order 4 bytes. ! mov [ebx+4],edx ' save high order 4 bytes. '---------------------------' END SUB '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION StrToHex( sBin AS STRING ) AS STRING REGISTER i AS LONG, j AS LONG LOCAL a, b AS BYTE PTR LOCAL sHex AS STRING sHex = STRING$( LEN(sBin)*2, " " ) ' make a string the right size a = STRPTR(sHex) b = STRPTR(sBin) j = 0 FOR i = 0 TO LEN(sBin)-1 CvtTwoByte.str = HEX$(@b[i],2) ' NO String concatenation @a[j] = CvtTwoByte.byt(1) INCR j @a[j] = CvtTwoByte.byt(2) INCR j NEXT i FUNCTION = sHex ' return string END FUNCTION '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤' ' Invert BYTE order IN a 32 BIT variable '#define bswap(x) (rotl(x, 8) & 0x00ff00ff | rotr(x, 8) & 0xff00ff00) FUNCTION bswap( BYVAL dwX AS DWORD ) AS DWORD LOCAL XXdwl,XXdwr AS DWORD XXdwl = dwX : XXdwr = dwX ROTATE RIGHT XXdwr,8 : XXdwr = XXdwr AND &Hff00ff00??? ROTATE LEFT XXdwl,8 : XXdwl = XXdwl AND &H00ff00ff??? FUNCTION = XXdwl OR XXdwr END FUNCTION '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤' ' initialise the key schedule FROM the USER supplied key SUB RC6_set_key( UserKey() AS BYTE, BYVAL key_len AS DWORD, RC6Key() AS DWORD ) LOCAL i, j, k, a, b, t AS DWORD DIM l(7) AS DWORD REDIM RC6Key(43) ' STATIC u4byte RC6(l_key[44]); RC6Key(0) = &Hb7e15163??? LOCAL pdwUserKey AS DWORD PTR pdwUserKey = VARPTR(UserKey(0)) k = 1 WHILE k < 44 RC6Key(k) = RC6Key(k - 1) + &H9e3779b9??? INCR k WEND k = 0 WHILE k < key_len / 32 l(k) = u4byte_in(pdwUserKey + (4 * k)) INCR k WEND t = (key_len / 32) - 1 ' t = (key_len / 32); a = 0: b = 0: i = 0: j = 0 k = 0 WHILE k < 132 a = rotl(RC6Key(i) + a + b, 3): b = b+a b = rotl(l(j) + b, b) RC6Key(i) = a : l(j) = b i = IIF(i = 43, 0, i + 1) ' i = (i + 1) % 44; j = IIF(j = t , 0, j + 1) ' j = (j + 1) % t; INCR k WEND END SUB '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤' SUB RC6_EnCrypt( BYVAL pdw_InBlk AS DWORD PTR, BYVAL pdw_OutBlk AS DWORD PTR, RC6Key() AS DWORD ) ' encrypt a 16byte block OF TEXT LOCAL a,b,c,d,t,u AS DWORD a = u4byte_in(pdw_InBlk ): b = u4byte_in(pdw_InBlk + 4) + RC6Key(0) c = u4byte_in(pdw_InBlk + 8): d = u4byte_in(pdw_InBlk + 12) + RC6Key(1) f_rnd( 2,a,b,c,d): f_rnd( 4,b,c,d,a) f_rnd( 6,c,d,a,b): f_rnd( 8,d,a,b,c) f_rnd(10,a,b,c,d): f_rnd(12,b,c,d,a) f_rnd(14,c,d,a,b): f_rnd(16,d,a,b,c) f_rnd(18,a,b,c,d): f_rnd(20,b,c,d,a) f_rnd(22,c,d,a,b): f_rnd(24,d,a,b,c) f_rnd(26,a,b,c,d): f_rnd(28,b,c,d,a) f_rnd(30,c,d,a,b): f_rnd(32,d,a,b,c) f_rnd(34,a,b,c,d): f_rnd(36,b,c,d,a) f_rnd(38,c,d,a,b): f_rnd(40,d,a,b,c) u4byte_out(pdw_OutBlk, a + RC6Key(42)) : u4byte_out(pdw_OutBlk + 4, b) u4byte_out(pdw_OutBlk + 8, c + RC6Key(43)) : u4byte_out(pdw_OutBlk + 12, d) END SUB '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤' SUB RC6_DeCrypt( BYVAL pdw_InBlk AS DWORD PTR, BYVAL pdw_OutBlk AS DWORD PTR, RC6Key() AS DWORD ) ' decrypt a 16byte block OF TEXT LOCAL a,b,c,d,t,u AS DWORD d = u4byte_in(pdw_InBlk + 12): c = u4byte_in(pdw_InBlk + 8) - RC6Key(43) b = u4byte_in(pdw_InBlk + 4): a = u4byte_in(pdw_InBlk ) - RC6Key(42) i_rnd(40,d,a,b,c): i_rnd(38,c,d,a,b) i_rnd(36,b,c,d,a): i_rnd(34,a,b,c,d) i_rnd(32,d,a,b,c): i_rnd(30,c,d,a,b) i_rnd(28,b,c,d,a): i_rnd(26,a,b,c,d) i_rnd(24,d,a,b,c): i_rnd(22,c,d,a,b) i_rnd(20,b,c,d,a): i_rnd(18,a,b,c,d) i_rnd(16,d,a,b,c): i_rnd(14,c,d,a,b) i_rnd(12,b,c,d,a): i_rnd(10,a,b,c,d) i_rnd( 8,d,a,b,c): i_rnd( 6,c,d,a,b) i_rnd( 4,b,c,d,a): i_rnd( 2,a,b,c,d) u4byte_out(pdw_OutBlk + 12, d - RC6Key(1)) : u4byte_out(pdw_OutBlk + 8, c) u4byte_out(pdw_OutBlk + 4, b - RC6Key(0)) : u4byte_out(pdw_OutBlk, a) END SUB '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤' FUNCTION PBMAIN() AS LONG DIM RC6Key(0) AS STATIC DWORD LOCAL KeyLen, SrcLen AS LONG LOCAL sKey, sFile, sCipher, t, sFileName AS STRING LOCAL FileLen, i, k, hFile, PadLen, RetVal, nLoops, nBlocks AS LONG LOCAL PerfFreq, t1, t2 AS QUAD LOCAL cBeg, cEnd AS QUAD LOCAL Elapsed AS SINGLE LOCAL pIn, pOut AS BYTE PTR RetVal = QueryPerformanceFrequency(PerfFreq) ' Checkhardware supports High Resolution Timer sFile = "Low voltage cutoff should not be of great concern to the average user." ' Default sFileName = "1MBBinary.exe" ' <+++++++++++++++++++++++++++++++++++----------------------- ** CHANGE THIS ** hFile = FREEFILE ' Save the Declarations OPEN sFileName FOR BINARY SHARED AS hFile IF ERR THEN MSGBOX "Problem opening file to be encrypted",48,"File Error"+STR$(ERRCLEAR) GET$ #hFile, LOF(hFile), sFile CLOSE hFile ' ' t = t + LEFT$(sFile,80) + $CRLF + $CRLF ' COMMENT OUT FOR BINARY FILE ************** SrcLen = LEN(sFile) t = t + "Input File length :" + STR$(SrcLen) + $CRLF ' "12345678901234567890123456789012" sKey = "RC6SixteenByteKe" nLoops = 1 ' 999 for short string KeyLen = LEN(sKey) t = t + "Key length:" + STR$(KeyLen) + " (max=32)" + $CRLF DIM UserKey(KeyLen) AS STATIC BYTE POKE$ VARPTR(UserKey(0)), sKey ' string to byte array RC6_set_key( UserKey(), KeyLen, RC6Key() ) ' Create password based key for crypt and decrypt t = t + sKey + $CRLF + $CRLF t = t + "Input File: '"+sFileName+"', length=" + STR$(LEN(sFile)) + $CRLF PadLen = 16 - (SrcLen MOD 16) t = t + "PadLen :" + STR$(PadLen) + $CRLF nBlocks = (SrcLen+PadLen) / 16 t = t + "nBlocks :" + STR$(nBlocks) + $CRLF sFile = sFile + zbs(LEN(PadLen)) sCipher = zbs(SrcLen+PadLen) ' t = t + "Cipher length :" + STR$(LEN(sCipher)) + $CRLF pIn = STRPTR(sFile) pOut = STRPTR(sCipher) ' ---------------------------------------------------------- Encoding sCipher QueryPerformanceCounter t1 time_stamp_count(cBeg) ' measuring cpu clock cycles. The overhead just for making this call is about 25 clocks FOR i = 1 TO nLoops FOR k = 0 TO (nBlocks-1)*16 STEP 16 RC6_EnCrypt( pIn+k, pOut+k, RC6Key() ) NEXT NEXT time_stamp_count(cEnd) ' measuring cpu clock cycles. The overhead just for making this call is about 25 clocks t = t + "Encrypt Clock Cycles="+STR$( (cEnd-cBeg)\nLoops ) + $CRLF sCipher = sCipher + CHR$(PadLen) ' byte array to string QueryPerformanceCounter t2 : Elapsed = (t2-t1)/PerfFreq*1000 ' m/s sFile = "" ' Burn the Input. t = t + "Encrypted in:"+STR$(Elapsed)+" m/s" + $CRLF + $CRLF t = t + "Cipher length :" + STR$(LEN(sCipher)) + $CRLF ' t = t + StrToHex(LEFT$(sCipher, 30)) + $CRLF + $CRLF + $CRLF ' ---------------------------------------------------------- Decoding sCipher QueryPerformanceCounter t1 PadLen = ASC(RIGHT$(sCipher, 1)) t = t + "Recovered PadLen :" + STR$(PadLen) + $CRLF SrcLen = LEN(sCipher) - 1 nBlocks = SrcLen / 16 t = t + "Recovered nBlocks :" + STR$(nBlocks) + $CRLF sFile = zbs(SrcLen) pIn = STRPTR(sCipher) pOut = STRPTR(sFile) time_stamp_count(cBeg) ' measuring cpu clock cycles. The overhead just for making this call is about 25 clocks FOR i = 1 TO nLoops FOR k = 0 TO (nBlocks-1)*16 STEP 16 RC6_DeCrypt( pIn+k, pOut+k, RC6Key() ) NEXT NEXT time_stamp_count(cEnd) ' measuring cpu clock cycles. The overhead just for making this call is about 25 clocks t = t + "Decrypt Clock Cycles="+STR$( (cEnd-cBeg)\nLoops ) + $CRLF sFile = LEFT$(sFile, SrcLen-PadLen) ' convert byte array to string IF sFile = "" THEN MSGBOX "Decryption Operation Failed",64,"RC6" : EXIT FUNCTION QueryPerformanceCounter t2 : Elapsed = (t2-t1)/PerfFreq*1000 ' m/s sCipher = "" ' Burn the Cipher t = t + "Decrypted File length :" + STR$(LEN(sFile)) + $CRLF t = t + "Decrypt Completed in:"+STR$(Elapsed)+" m/s" + $CRLF + $CRLF ' t = t + LEFT$(sFile,80) + $CRLF ' COMMENT OUT FOR BINARY FILE ************** MSGBOX t,64,"RC6 Encryption" END FUNCTION '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
Comment