Code:
'  RC6 algorithm, AES finalist.
'  I corrected f_rnd and i_rnd macro multiply overflows and significantly optimized
'  this RC6 algorithm that was ported to PB from "C" by Aleksandr Dobrev, with testbed
'  My laptop averages 33 ticks/byte encoding, 53 ticks/byte decoding.
'  This demo will encode, decode and verify all files included on a list of files
'  stored in c:\fListCrypt.txt--one file per record--and display statistics after
'  each file. Individual files can be tested also.
'  John Gleason, Oct. 22, 07.
'  Addendum Nov. 7, 2007. Added a big RC6 monotonic timer secure random # generator & test vector code,
'  fixed bugs so test vectors match, optimized encoding further, and wrote easier to use demo code.
'  I did see Aleksandr posted his similar code he'd worked on for a couple hours, but since this code I
'  worked on for TWO WEEKS, and I did promise I'd post it, I figured it's time to deliver even if the thunder has died.
' ====================================================================================

'  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

#COMPILE EXE
#DIM ALL
#REGISTER NONE

#INCLUDE "win32api.inc"

%ROUNDS        = 20

' Utility macros
MACRO zbs(xx) = STRING\$(xx, 0)

MACRO FUNCTION rotr(x,n)
MACROTEMP s
LOCAL 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
LOCAL s AS DWORD
s = (x)
ROTATE LEFT s,n
END MACRO = s

MACRO rotr2(x,n)
MACROTEMP s
LOCAL s AS DWORD
s = x
!mov eax, s
!mov ecx, n
!ror eax, cl
END MACRO

MACRO rotl2(x,n)
!mov ecx, n
!mov eax, x
!rol eax, cl
END MACRO

'  GET a 32 BIT WORD (v) IN machine order FROM a BYTE address IN (x)
MACRO FUNCTION u4byte_in(x)
MACROTEMP pdwZmacro
DIM pdwZmacro AS DWORD PTR
pdwZmacro = (x)
END MACRO = @pdwZmacro

MACRO f_rnd(i,a,b,c,d)           'changed 2 macros------------------------
MACROTEMP u,t
LOCAL u, t AS LONG
!mov ecx, d
!lea eax, [ecx+ecx+1]
!mul ecx
!rol eax, 5
!mov u, eax

!mov ecx, b
!lea eax, [ecx+ecx+1]
!mul ecx
!rol eax, 5
!mov t, eax

!xor eax, a
!mov ecx, u
!rol eax, cl
!mov edx, keyPtr
!mov ecx, i
!mov a, eax         ;a = a + RC6Key(i)

!mov eax, c
!xor eax, u
!mov ecx, t
!rol eax, cl
!mov ecx, i
!mov c, eax         ;c = c + RC6Key(i + 1)
END MACRO

MACRO i_rnd(i,a,b,c,d)
MACROTEMP u,t,d2,b2
LOCAL u, t, d2, b2 AS DWORD
!mov eax, d
!mov ecx, d
!mul ecx
!mov d2,  eax
rotl2(d2, 5)       'rotl2(d * (d + d + 1), 5)
!mov u, eax

!mov eax, b
!mov ecx, b
!mul ecx
!mov b2,  eax
rotl2(b2, 5)       'rotl2(b * (b + b + 1), 5)
!mov t, eax

rotr2(c - RC6Key(i + 1), t)
!xor eax, u
!mov c, eax
rotr2(a - RC6Key(i), u)
!xor eax, t
!mov a, eax
END MACRO                        'end change------------------------------

'MACRO f_rnd(i,a,b,c,d)          'this is what the above asm does... (but correctly with no undefined overflow)
'  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

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
' 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

IF key_len > 32 THEN key_len = 32
IF (key_len AND 3) <> 0 THEN
key_len = key_len - (key_len AND 3) + 4
END IF
k = 0
WHILE k < key_len \ 4
l(k) = u4byte_in(pdwUserKey + (4 * k))
INCR k
WEND

t = (key_len \ 4) - 1

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

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'

MACRO mRC6_monotonicEncrypt(pdw_OutBlk)'RC6 encrypt a ~60 yr "monotonic" counter--won't ever repeat for 60 years. And even
'after 60 years, the odds of a 16-byte sequence repeating are > 10^18. This assumes
'your clock speed = 5GHz. If your computer is 2.5GHz, the counter won't ever repeat
'for 120 years, 1.25GHz doesn't risk repeating for 240 years and so on. What about
'Moore's law tho, if clock speeds increase to 5 PetaHz? By then the time stamp counter
'will be 128 or 256 bits AT LEAST, making the monotonic counter good for way longer
'(at 5 PHz) than even the most optimistic estimate of the lifespan of the UNIVERSE.
'Be sure to make the equate %CLOCKSPEED a little larger than your actual processor
'speed to be sure there will never be any possible overlap. Realistically tho,
'even if you ignored this directive and got non-monotonic timer overlap, you'd still
'have over a billion billion to one chance of getting a duplicate round. What is
'the 60 yr. limitation workaround? Well, every 60 years or so, reset the password.
'See ya around 2068, maybe on Europa! :D
MACROTEMP a,b,c,d,initComplete
LOCAL  a,b,c,d     AS DWORD
'----------------------------------------------------------------------------------
!cmp a,   0              ;this little section does the following:
!ja short initComplete   ;IF a, b, c, and d are not initialized--that is, all are zero--THEN
!cmp b,   0              ;initialize them with initVector by direct copy.
!ja short initComplete
!cmp c,   0
!ja short initComplete
!cmp d,   0
!ja short initComplete
!lea esi, initVector
!mov eax, [esi+00]
!mov ebx, [esi+04]
!mov ecx, [esi+08]
!mov edx, [esi+12]
!mov a,   eax
!mov b,   ebx
!mov c,   ecx
!mov d,   edx
'----------------------------------------------------------------------------------

initComplete:
!db  &h0f,&h31                     ;read time stamp ctr
!xor esi, esi
!mov edi, keyPtr
!mov ebx, ticksSinceJan1st2007     ;low dword of sys time
!mov ecx, ticksSinceJan1st2007[4]  ; hi      "       "
!add eax, ebx                      ;add total since Jan. 1, 2007 to current day clock ticks
!adc edx, ecx                      ;add total since Jan. 1, 2007 to current day clock ticks

!xor eax, a                        ;previous round a
!mov a,   eax                      ;lo save to a
!xor eax, b                        ;previous round b
!mov b,   eax                      ;save b
!xor edx, c                        ;previous round c
!mov c,   edx                      ;hi save to c
!xor edx, d                        ;previous round d
!mov d,   edx                      ;save to d

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)

!mov esi, pdw_OutBlk
!mov edi, keyPtr
!mov eax, a
!mov ebx, b
!mov ecx, c
!mov edx, d
!mov [esi+00], eax
!mov [esi+04], ebx
!mov [esi+08], ecx
!mov [esi+12], edx
'
END MACRO

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'

MACRO mRC6_EnCrypt(pdw_InBlk, pdw_OutBlk) ' encrypt a 16byte block OF TEXT
MACROTEMP a,b,c,d
LOCAL  a,b,c,d AS DWORD

!mov esi, pdw_InBlk
!mov edi, keyPtr
!mov eax, [esi+00]
!mov ebx, [esi+04]
!mov ecx, [esi+08]
!mov edx, [esi+12]
!mov a,   eax
!mov b,   ebx
!mov c,   ecx
!mov d,   edx
'    above asm does this:
'    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)

'    below asm does this:
'    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)
!mov esi, pdw_OutBlk
!mov edi, keyPtr
!mov eax, a
!mov ebx, b
!mov ecx, c
!mov edx, d
!mov [esi+00], eax
!mov [esi+04], ebx
!mov [esi+08], ecx
!mov [esi+12], edx
'
END MACRO

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'

MACRO mRC6_DeCrypt(pdw_InBlk, pdw_OutBlk) ' decrypt a 16byte block OF TEXT
MACROTEMP a,b,c,d
LOCAL  a,b,c,d AS DWORD

!mov esi, pdw_InBlk
!mov edi, keyPtr
!mov eax, [esi+00]
!mov ebx, [esi+04]
!mov ecx, [esi+08]
!mov edx, [esi+12]
!sub ecx, [edi+172]
!sub eax, [edi+168]
!mov a,   eax
!mov b,   ebx
!mov c,   ecx
!mov d,   edx
'above asm does this:
'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)

'below asm does this:
'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)
!mov esi, pdw_OutBlk
!mov edi, keyPtr
!mov eax, a
!mov ebx, b
!mov ecx, c
!mov edx, d
!sub ebx, [edi+00]
!sub edx, [edi+04]
!mov [esi+00], eax
!mov [esi+04], ebx
!mov [esi+08], ecx
!mov [esi+12], edx

END MACRO

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'

END TYPE

'------------------------------These two equates are for the cryptographically secure monotonic random generator
%CLOCKSPEED   = 2000000000 'Hz 'Enter your CPU speed. Round UP to the next nearest 10 million ticks to assure no possible
'monotonic timer overlap for the next 60 to 100+ years, depending on CPU speed.
'---------------------------------------------------------------------------------------------------------------

%DOTESTVECTORS =  0           'set to 1 or other non-zero to run test vector values to see if algorithm is correct

'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
FUNCTION PBMAIN() AS LONG

DIM RC6Key(43) AS STATIC DWORD
DIM plaintext(5) AS STRING, UserKey2(5) AS STRING, ciphertext(5) AS STRING
LOCAL KeyLen, SrcLen, encryptFiles, generateRnds, rndCount, keyPtr AS LONG
LOCAL initVector AS STRING * 16
LOCAL sKey, sFile, bsFile, sCipher, t, sFileName, ciphertext1, ciphertext2 AS STRING
LOCAL FileLen, i, k, hFile, PadLen, RetVal, nLoops, nBlocks, cryptFile, ii, tVect AS LONG
LOCAL PerfFreq, t1, t2, ticksSinceJan1st2007 AS QUAD
LOCAL Elapsed AS SINGLE
LOCAL st AS SYSTEMTIME, qt AS QUADTIME
LOCAL pIn, pOut AS BYTE PTR
LOCAL pi2, po2, did1file, gotList AS LONG

'------------Select here what you want to demo--------------------------------------
'Set choice to non-zero
encryptFiles = 0  'encrypt, decrypt and verify a file or list of files.
generateRnds = 0  'cryptographically secure monotonic counter random # generator. Cycle currently > 60 years. (as of 2007)
'  testVectors: Set %DOTESTVECTORS above to a non-zero value to run test vector check
'-------------------End of selections-----------------------------------------------

'             "12345678901234567890123456789012"
sKey    = "use up to A 32BYTE onom .&.TmPy%"            '32 bytes max--256 bits main key.

'   And if you're also generating secure randoms, enter that password too...
initVector = "ENTERyour16bytes"                         'You choose 16 bytes max. Only used in rand generator.
'-------------------End key---------------------------------------------------------

IF (encryptFiles AND generateRnds)     THEN encryptFiles = 0 'can't do both at the same time
IF (encryptFiles OR  generateRnds) = 0 THEN generateRnds = 1 'but you've gotta do something

RetVal = QueryPerformanceFrequency(PerfFreq) ' Checkhardware supports High Resolution Timer
getSystemTime(st)
systemTimeToFileTime(st, qt)
ticksSinceJan1st2007 = (qt.ftQuad - 1.28123856e17) * %CLOCKSPEEDADJ 'Explanation of this line follows...
'Take an example: for a 2ghz machine--100 nanosec/sysTimeTick * 2 clockTicks/nanosec = 200 clockTicks/sysTimeTick
'So, %CLOCKSPEEDADJ = 200 for 2GHz. The quantity (qt.ftQuad - 1.28123856e17) is the # of 100 nanosec intervals since
'Jan. 1, 1601, MINUS 406 years of 100 nanosec intervals (1.28123856e17 intervals) which = ticks since Jan. 1, 2007.
'To customize this and make it unique to you, you can reduce (or even slightly increase) this number. Reducing it,
'however, eats into the future years it has available before repeating its cycle. 30 years may just not be enough. ;)

IF generateRnds THEN OPEN "c:\monotonicRC6randoms.dat" FOR BINARY AS #1
IF encryptFiles THEN cryptFile = 1
DO

IF cryptFile = 1 THEN
cryptFile = 0
TRY
OPEN "C:\ListCryptFiles.txt" FOR INPUT LOCK SHARED AS #1 ' <<this is a list of all the files you want to en/decrypt
gotList = %TRUE                                   ' and check for correctness of en/decryption. Does not write
CATCH                                                ' to disk, only memory. 0 min size, 85MB max size tested.
END TRY
END IF

IF encryptFiles THEN
newFile:
IF gotList = %TRUE THEN
LINE INPUT #1, sfileName
IF EOF(1) THEN EXIT DO
ELSE
'if no filelist exists, try using just a single file
sFileName = "D:\ONTARIO.MPG" ' <<You can also test just a single file  **   CHANGE THIS to your filename  **
TRY
IF did1file = 1 THEN EXIT DO
OPEN sFileName FOR INPUT ACCESS READ LOCK SHARED AS #1
CLOSE #1
did1file = 1
CATCH
? "No file found to encode/decode.",,"RC6"
EXIT FUNCTION
END TRY
END IF
hFile = FREEFILE
OPEN sFileName FOR BINARY LOCK SHARED AS hFile
IF ERR THEN CLOSE hFile: GOTO newFile
IF LOF(hFile) < 0 OR LOF(hFile) > 85000000 THEN CLOSE hFile: GOTO newFile
GET\$ #hFile, LOF(hFile), sFile
CLOSE hFile '
END IF

IF generateRnds THEN
'-------cryptographically secure random generator code-------------------------------------------------------------
sFile = STRING\$(&h010000, 0)                            'string used only for rand generator.
!lea edx, initVector                                    ;now shuffle initVector a bit
!mov eax, [edx+00]
!mov ecx, [edx+04]
!mul ecx
!lea ecx, initVector
!xor [ecx+08], edx
!xor [ecx+12], eax
!mov eax, [ecx+06]
!mov ecx, [ecx+10]
!mul ecx
!lea ecx, initVector
!xor [ecx+00], edx
!xor [ecx+04], eax
'---end cryptographically secure random generator code-------------------------------------------------------------
END IF

#IF %DOTESTVECTORS
CALL FillTestVectors(plaintext(), UserKey2(), ciphertext())
nextVect:
sFile = plainText(tVect)
sFileName = "Test vector"
skey = userKey2(tVect)
ciphertext2 = cipherText(tVect) '<< plainText and userKey should result in this cipherText
INCR tVect
generateRnds = 0: encryptFiles = 1
#ENDIF

bsFile = sFile                                          ' REMOVE THIS LINE if not verification testing
SrcLen = LEN(sFile)
KeyLen = LEN(sKey)
REDIM UserKey(KeyLen) AS STATIC BYTE

POKE\$ VARPTR(UserKey(0)), sKey             ' key to byte array
RC6_set_key( UserKey(), KeyLen, RC6Key() ) ' Create password based key for crypt and decrypt

IF (SrcLen AND 15) <> 0 THEN PadLen = 16 - (SrcLen AND 15) ELSE padLen = 0
IF SrcLen = 0 THEN padLen = 16
nBlocks = (SrcLen + PadLen) \ 16
sCipher = zbs(SrcLen + PadLen) '

t = t + "Input File length :" + STR\$(SrcLen) + \$CRLF _
+ "Key length:" + STR\$(KeyLen) + " (max=32)" + \$CRLF _
+ "Input File: "+sFileName & \$CRLF    & \$CRLF _
+ "nBlocks :" + STR\$(nBlocks) + \$CRLF _
+ "Cipher length :" + STR\$(LEN(sCipher)) + \$CRLF

pIn  = STRPTR(sFile)
pOut = STRPTR(sCipher)
nLoops = 1
keyPtr = VARPTR(RC6Key(0))

' ----------------------------------------------------------  Encoding sCipher
QueryPerformanceCounter t1

time_stamp_count(cBeg) ' measuring cpu clock cycles. The overhead just for making this call is about 25 clocks

regenerate:
FOR k = 0 TO (nBlocks-1)*16 STEP 16
po2 = pOut+k
IF generateRnds THEN
mRC6_monotonicEncrypt(po2)
ELSE
pi2 = pIn+k
mRC6_EnCrypt(pi2, po2)
END IF
NEXT

IF generateRnds THEN
PUT #1, , sCipher
INCR rndCount
IF rndCount = 1600 THEN CLOSE: EXIT DO '~100MB file
GOTO regenerate
END IF

time_stamp_count(cEnd) ' measuring cpu clock cycles. The overhead just for making this call is about 25 clocks
sCipher = sCipher + CHR\$(PadLen) ' byte array to string
QueryPerformanceCounter t2 : Elapsed = (t2-t1)/PerfFreq*1000 ' m/s

#IF %DOTESTVECTORS
'    next lines are the test vector results you must match to be correct
IF LEFT\$(sCipher, SrcLen) = ciphertext2 THEN answer = "Yes it does!" ELSE answer = "No. Error in cipher!"
? "Does " & \$CRLF & strToHex(LEFT\$(sCipher, SrcLen)) & " =" & \$CRLF & _
strToHex(ciphertext2) & " ?" & \$CRLF & answer,,"RC6 Test Vector" & STR\$(tVect)
#ENDIF

t = t + "Encrypt Clock Cycles="+STR\$(cEnd-cBeg) + \$CRLF _
+ "Encrypted in:"+STR\$(Elapsed)+" m/s" + \$CRLF _
+ "Encrypt Clock Cycles per Byte:"+STR\$((cEnd-cBeg)\nLoops\LEN(sFile))+" c/b" + \$CRLF + \$CRLF _
+ "Cipher length :" + STR\$(LEN(sCipher)) + \$CRLF

' ----------------------------------------------------------  Decoding sCipher
QueryPerformanceCounter t1

SrcLen = LEN(sCipher) - 1
nBlocks = SrcLen \ 16
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 k = 0 TO (nBlocks-1)*16 STEP 16
pi2 = pIn+k
po2 = pOut+k
mRC6_DeCrypt(pi2, po2)
NEXT

time_stamp_count(cEnd) ' measuring cpu clock cycles. The overhead just for making this call is about 25 clocks

sFile = LEFT\$(sFile, SrcLen-PadLen) ' convert byte array to string
QueryPerformanceCounter t2 : Elapsed = (t2-t1)/PerfFreq*1000 ' m/s
IF sFile <> bsFile THEN ? "Error, decryption <> original!",64,"RC6"  'REMOVE THIS if not verification testing

#IF %DOTESTVECTORS
RESET t
IF sFile <> plainText(tVect - 1) THEN
? "Error! RC6 algorithm failed on a test vector.",64,"RC6 Test Vectors"
EXIT FUNCTION
END IF
IF tVect <= 5 THEN GOTO nextVect
? "All vectors matched, so this RC6 algorithm correctly handled the test vectors.",,"RC6 Test Vectors"
EXIT FUNCTION
#ENDIF

sCipher = "" ' Burn the Cipher
t = t + "Recovered PadLen :" + STR\$(PadLen) + \$CRLF _
+ "Recovered nBlocks :" + STR\$(nBlocks) + \$CRLF _
+ "Decrypt Clock Cycles="+STR\$( (cEnd-cBeg)\nLoops ) + \$CRLF _
+ "Decrypted File length :" + STR\$(LEN(sFile)) + \$CRLF _
+ "Decrypt Completed in:"+STR\$(Elapsed)+" m/s" + \$CRLF _
+ "Decrypt Clock Cycles per Byte:"+STR\$((cEnd-cBeg)\nLoops\LEN(sFile))+" c/b" + \$CRLF+ \$CRLF

? t,64,"RC6 Encryption"
RESET t': BEEP

LOOP UNTIL EOF(1)
? "done",, "RC6"
END FUNCTION

#IF %DOTESTVECTORS
SUB FillTestVectors(plaintext() AS STRING, UserKey() AS STRING, ciphertext() AS STRING)
'Official Test vectors for encryption with RC6. Thanks for the code Aleksandr Dobrev
'
plaintext(0) = CHR\$(&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00)
userkey(0)   = CHR\$(&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00)
ciphertext(0)= CHR\$(&H8f,&Hc3,&Ha5,&H36,&H56,&Hb1,&Hf7,&H78,&Hc1,&H29,&Hdf,&H4e,&H98,&H48,&Ha4,&H1e)
'
plaintext(1)=  CHR\$(&H02,&H13,&H24,&H35,&H46,&H57,&H68,&H79,&H8a,&H9b,&Hac,&Hbd,&Hce,&Hdf,&He0,&Hf1)
userkey(1)=    CHR\$(&H01,&H23,&H45,&H67,&H89,&Hab,&Hcd,&Hef,&H01,&H12,&H23,&H34,&H45,&H56,&H67,&H78)
ciphertext(1)= CHR\$(&H52,&H4e,&H19,&H2f,&H47,&H15,&Hc6,&H23,&H1f,&H51,&Hf6,&H36,&H7e,&Ha4,&H3f,&H18)
'
plaintext(2)=  CHR\$(&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00)
userkey(2)=    CHR\$(&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00)+_
CHR\$(&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00)
ciphertext(2)= CHR\$(&H6c,&Hd6,&H1b,&Hcb,&H19,&H0b,&H30,&H38,&H4e,&H8a,&H3f,&H16,&H86,&H90,&Hae,&H82)
'
plaintext(3)=  CHR\$(&H02,&H13,&H24,&H35,&H46,&H57,&H68,&H79,&H8a,&H9b,&Hac,&Hbd,&Hce,&Hdf,&He0,&Hf1)
userkey(3)=    CHR\$(&H01,&H23,&H45,&H67,&H89,&Hab,&Hcd,&Hef,&H01,&H12,&H23,&H34,&H45,&H56,&H67,&H78)+_
CHR\$(&H89,&H9a,&Hab,&Hbc,&Hcd,&Hde,&Hef,&Hf0)
ciphertext(3)= CHR\$(&H68,&H83,&H29,&Hd0,&H19,&He5,&H05,&H04,&H1e,&H52,&He9,&H2a,&Hf9,&H52,&H91,&Hd4)
'
plaintext(4)=  CHR\$(&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00)
userkey(4)=    CHR\$(&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00)+_
CHR\$(&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00)
ciphertext(4)= CHR\$(&H8f,&H5f,&Hbd,&H05,&H10,&Hd1,&H5f,&Ha8,&H93,&Hfa,&H3f,&Hda,&H6e,&H85,&H7e,&Hc2)
'
plaintext(5)=  CHR\$(&H02,&H13,&H24,&H35,&H46,&H57,&H68,&H79,&H8a,&H9b,&Hac,&Hbd,&Hce,&Hdf,&He0,&Hf1)
userkey(5)=    CHR\$(&H01,&H23,&H45,&H67,&H89,&Hab,&Hcd,&Hef,&H01,&H12,&H23,&H34,&H45,&H56,&H67,&H78)+_
CHR\$(&H89,&H9a,&Hab,&Hbc,&Hcd,&Hde,&Hef,&Hf0,&H10,&H32,&H54,&H76,&H98,&Hba,&Hdc,&Hfe)