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

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

    Leave a comment:


  • John Gleason
    replied
    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

    Leave a comment:


  • Mike Trader
    replied
    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.

    Leave a comment:


  • Arthur Gomide
    replied
    Same error in 8.03 / 7.04

    "Decryption Operation Failed"

    Leave a comment:


  • Henk Broekhuizen
    replied
    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

    Leave a comment:


  • Mike Trader
    started a topic RC6 Encryption

    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.
Working...
X