Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

The Promised RC6

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • The Promised RC6

    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: http://www.powerbasic.com/support/pb...ad.php?t=35257
    '  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
Working...
X