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

RC6 Encryption

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

  • RC6 Encryption

    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
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
    Last edited by Mike Trader; 12 Oct 2007, 12:17 PM.

  • #2
    Small correction

    A small logical error was made;

    sFileName = "1MBBinary.exe" ' <+++++--------- ** CHANGE THIS **
    hFile = FREEFILE ' Save the Declarations
    OPEN "1MBBinary.exe" FOR BINARY SHARED AS hFile

    the last line logically should read:
    OPEN sFileName FOR BINARY SHARED AS hFile


    Have fun and Mike thanx for sharing this with us.
    Regards,

    Henk
    Henk Broekhuizen, PA3BLP
    powerbasicforum -at- doorhet.net
    Sexbierum, The Netherlands
    ========================

    Comment


    • #3
      Same error in 8.03 / 7.04

      "Decryption Operation Failed"
      "The trouble with quotes on the Internet is that you can never know if they are genuine." - Abraham Lincoln.

      Comment


      • #4
        Code:
                        
        ' Corrected Padding and added test vectors - NOT confirmed
        
        ' 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
                   
        '  The key schedule of RC6-w r bis practically identical to the key schedule of RC5. 
        '  The only diference is that more words are derived from the user-supplied key for 
        '  use during encryption and decryption. The user supplies a key of b bytes. 
        '  Suficient zero bytes are appended to give a key length equal to a non-zero 
        '  integral number of words; these key bytes are then loaded in little-endian 
        '  fashion into an array of c w-bit words.Thus the first byte of key is stored as 
        '  the low-order byte of LO, and is padded with high-order zero bytes if necessary. 
        '  Note that if b= 0 then c=1 and L0 = 0. The number ofw-bit words that will be generated 
        '  for the additive round keys is 2r+4 and these are stored in the array.
        '  http://people.csail.mit.edu/rivest/Rc6.pdf
        
        
        #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  
        
        '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
        FUNCTION Hex2Show( sBin AS STRING ) AS STRING  ' For Debugging
                    
          REGISTER i AS LONG
          LOCAL t AS STRING
          LOCAL b AS BYTE PTR  
        
            b = STRPTR(sBin)
            FOR i = 0 TO LEN(sBin)-1
               t = t + HEX$(@b[i],2) + " "  ' String concatenation
            NEXT i 
        
          FUNCTION = t ' return string
        
        END FUNCTION
                     
                  
        '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
        FUNCTION Show2Hex( sShow AS STRING ) AS STRING  ' Convert to string of Chars with hex values specified
                    
          REGISTER i AS LONG
          LOCAL BinLen AS LONG
          LOCAL t AS STRING
          LOCAL b AS BYTE PTR  
                              
            BinLen = PARSECOUNT(sShow, " ") '
        
            FOR i = 1 TO BinLen 
               t = t + CHR$( VAL("&H"+PARSE$(sShow, " ", i)) )  ' String concatenation 
            NEXT i ' MSGBOX STR$(LEN(t))
        
          FUNCTION = t ' 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, sTestFile, sTestKey, sTestCipher AS STRING 
          LOCAL FileLen, i, k, hFile, PadLen, RetVal, nLoops, nBlocks, ExtraBytes 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 "1MBBinary.exe" 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 ' 
                     
                           
        '          "12345678901234567890123456789012"          
            sKey = "RC6SixteenByteKe" 
        
        
        
        
        '    sTestFile   = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
        '    sTestKey    = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
        '    sTestCipher = "8f c3 a5 36 56 b1 f7 78 c1 29 df 4e 98 48 a4 1e"
                                                                 
            sTestFile   = "02 13 24 35 46 57 68 79 8a 9b ac bd ce df e0 f1"
            sTestKey    = "01 23 45 67 89 ab cd ef 01 12 23 34 45 56 67 78"
            sTestCipher = "52 4e 19 2f 47 15 c6 23 1f 51 f6 36 7e a4 3f 18"
                                                               
        '    sTestFile   = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
        '    sTestKey    = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
        '    sTestCipher = "6c d6 1b cb 19 0b 30 38 4e 8a 3f 16 86 90 ae 82"
        
        '    sTestFile   = "02 13 24 35 46 57 68 79 8a 9b ac bd ce df e0 f1"
        '    sTestKey    = "01 23 45 67 89 ab cd ef 01 12 23 34 45 56 67 78 89 9a ab bc cd de ef f0"
        '    sTestCipher = "68 83 29 d0 19 e5 05 04 1e 52 e9 2a f9 52 91 d4"
        
        '    sTestFile   = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
        '    sTestKey    = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
        '    sTestCipher = "8f 5f bd 05 10 d1 5f a8 93 fa 3f da 6e 85 7e c2"
        
        '    sTestFile   = "02 13 24 35 46 57 68 79 8a 9b ac bd ce df e0 f1"
        '    sTestKey    = "01 23 45 67 89 ab cd ef 01 12 23 34 45 56 67 78 89 9a ab bc cd de ef f0 10 32 54 76 98 ba dc fe"
        '    sTestCipher = "c8 24 18 16 f0 d7 e4 89 20 ad 16 a1 67 4e 5d 48"  
        
        
        
            sFile   = Show2Hex(sTestFile)
            sKey    = Show2Hex(sTestKey) ' MSGBOX sKey + $CRLF + Hex2Show( Show2Hex(sKey) )
        
                        
        
        
            t = t + Hex2Show(sFile) + $CRLF + $CRLF   ' COMMENT OUT FOR BINARY FILE **************  
        
            SrcLen = LEN(sFile)
            t = t + "Input File length :" + STR$(SrcLen) + $CRLF  
                       
        
        
                      
            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 + sTestKey  + $CRLF
            t = t + Hex2Show(sKey)  + $CRLF + $CRLF
            t = t + "Input File: '"+sFileName+"', length=" + STR$(LEN(sFile)) + $CRLF   
        
                             
        
            ExtraBytes = SrcLen MOD 16 ' MSGBOX STR$(ExtraBytes)
            IF ExtraBytes THEN PadLen = 16 - ExtraBytes ELSE PadLen = 0  
        
            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 + "Known Cipher:" + $CRLF  
           t = t + sTestCipher + $CRLF + $CRLF 
                        
            t = t + "Calculated Cipher length :" + STR$(LEN(sCipher)) + $CRLF 
           t = t + Hex2Show(sCipher) + $CRLF + $CRLF + $CRLF ' COMMENT OUT FOR BINARY FILE **************   
                                 
              
        
        
        
        
        ' ----------------------------------------------------------  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 + Hex2Show(sFile) + $CRLF ' COMMENT OUT FOR BINARY FILE **************
        
            MSGBOX t,64,"RC6 Encryption"  
        
        
        END FUNCTION
        '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'
        Last edited by Mike Trader; 28 Oct 2007, 02:52 PM.

        Comment


        • #5
          Code:
          '======================================================================================================
          ' Mike Trader, there is/was an error in the RC6 algorithm you posted previously, as fully 1/2 of the
          ' equations like u = rotl(d * (d + d + 1), 5) thunk to zero because they exceed the size of a DWORD.
          ' I'm certain Ron Rivest did not intend that to happen by design. This is probably just an exact copy
          ' of the code Aleksandr Dobrev posted from the C port, so the mistake may go back a ways. I fixed the
          ' code below to do the multiplication correctly, but this fixed version will no longer work with any
          ' file encoded with the old version. I have a new optimized version of this fixed RC6 algo that is
          ' many times faster, and some may find it of interest so will link to from here in a day or two.
          ' Oct. 21, 07, John Gleason
          ' Discussion here:http://www.powerbasic.com/support/pb...ad.php?t=35257
          '======================================================================================================
          
          '  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
             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
          
          ' 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)                  'here's the section I modified to fix an error----(John Gleason)--------------------
            MACROTEMP u,t
            DIM u AS DWORD,t AS DWORD
                  u = d
                  BIT RESET u, 31                 'if top bit of d is 1, set top bit to zero, or u will go out of range and reset to 0.
                  u = rotl(u * (u + u + 1), 5)    'previously was: u = rotl(d * (d + d + 1), 5)
                  t = b
                  BIT RESET t, 31                 'if top bit of b is 1, set top bit to zero, or t will go out of range and reset to 0.
                  t = rotl(t * (t + t + 1), 5)    'previously was: 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 = d
                  BIT RESET u, 31                 'if top bit of d is 1, set top bit to zero, or u will go out of range and reset to 0.
                  u = rotl(u * (u + u + 1), 5)    'previously was: u = rotl(d * (d + d + 1), 5)
                  t = b
                  BIT RESET t, 31                 'if top bit of b is 1, set top bit to zero, or t will go out of range and reset to 0.
                  t = rotl(t * (t + t + 1), 5)    'previously was: 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                               'end of the section I modified to fix an error--------------------------------------
          
          
          
          
          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
              ? "yow"
              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 = "D:\fileToEncrypt.AVI" ' <+++++++++++++++++++++++++++++++++++-----------------------  **   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
          
              t = t + "Encrypted in:"+STR$(Elapsed)+" m/s" + $CRLF
              t = t + "Encrypt Clock Cycles per Byte:"+STR$((cEnd-cBeg)\nLoops\LEN(sFile))+" c/b" + $CRLF + $CRLF
              sFile = "" ' Burn the Input.
              t = t + "Cipher length :" + STR$(LEN(sCipher)) + $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
              t = t + "Decrypt Clock Cycles per Byte:"+STR$((cEnd-cBeg)\nLoops\LEN(sFile))+" c/b" + $CRLF+ $CRLF
          
              MSGBOX t,64,"RC6 Encryption"
          
          
          END FUNCTION
          Last edited by John Gleason; 21 Oct 2007, 06:40 PM. Reason: Fixed significant error in RC6 algorithm

          Comment


          • #6
            see:
            http://www.powerbasic.com/support/pb...ad.php?t=35257
            Last edited by Mike Trader; 28 Oct 2007, 02:49 PM.

            Comment

            Working...
            X