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
'  code by Mike Trader.
'  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.
'  Discussion here: [URL="http://www.powerbasic.com/support/pbforums/showthread.php?t=35257"]http://www.powerbasic.com/support/pbforums/showthread.php?t=35257[/URL]
'  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

' Padding and testbed Mike Trader 2007


#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

'--------------------------------added 2 macros
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
'----------------------------end added 2 macros

'  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
        !add eax, [edx+ecx*4]
        !mov a, eax         ;a = a + RC6Key(i)

        !mov eax, c
        !xor eax, u
        !mov ecx, t
        !rol eax, cl
        !mov ecx, i
        !add ecx, 1
        !add eax, [edx+ecx*4]
        !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
        !add eax, eax
        !add eax, 1
        !mul ecx
        !mov d2,  eax
        rotl2(d2, 5)       'rotl2(d * (d + d + 1), 5)
        !mov u, eax

        !mov eax, b
        !mov ecx, b
        !add eax, eax
        !add eax, 1
        !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
    !add eax, [edi+00]                 ;add key(0)
    !xor eax, b                        ;previous round b
    !mov b,   eax                      ;save b
    !xor edx, c                        ;previous round c
    !mov c,   edx                      ;hi save to c
    !add edx, [edi+04]                 ;key(1)
    !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
    !add eax, [edi+168]
    !add ecx, [edi+172]
    !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]
    !add ebx, [edi+00]
    !add edx, [edi+04]
    !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
    !add eax, [edi+168]
    !add ecx, [edi+172]
    !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

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

TYPE QUADTIME
  ftQuad AS QUAD  'fileTime as a quad
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.
%CLOCKSPEEDADJ= %CLOCKSPEED \ 10000000
'---------------------------------------------------------------------------------------------------------------

%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 cBeg, cEnd 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-----------------------------------------------

'------Enter here your secret RC6 password key for this run-------------------------
'             "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
    sFile = sFile + zbs(PadLen)
    sCipher = zbs(SrcLen + PadLen) '

    t = t + "Input File length :" + STR$(SrcLen) + $CRLF _
          + "Key length:" + STR$(KeyLen) + " (max=32)" + $CRLF _
          + "Input File: "+sFileName & $CRLF    & $CRLF _
          + "PadLen :" + STR$(PadLen) + $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
  LOCAL answer AS STRING
    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

    PadLen = ASC(RIGHT$(sCipher, 1))
    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)
  ciphertext(5)= CHR$(&Hc8,&H24,&H18,&H16,&Hf0,&Hd7,&He4,&H89,&H20,&Had,&H16,&Ha1,&H67,&H4e,&H5d,&H48)
END SUB
#ENDIF