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

Serpent encryption for 7.0/3.0

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

  • Serpent encryption for 7.0/3.0

    #IF 0
    Code:
    =====================================================================
                            Serpent Encryption
    =====================================================================
       
    The authors of the Serpent encryption algorithm have placed it in the 
    public domain and make no restrictions on its use. The Serpent home 
    page is accessible at: 
     http://www.cl.cam.ac.uk/~rja14/serpent.html 
       
    From the Serpent home page:
    "Serpent is a 128-bit block cipher designed by Ross Anderson, Eli 
    Biham and Lars Knudsen as a candidate for the Advanced Encryption 
    Standard. It was a finalist in the AES competition. The winner, 
    Rijndael, got 86 votes at the last AES conference while Serpent got 59 
    votes, Twofish 31 votes, RC6 23 votes and MARS 13 votes. So NIST's 
    choice of Rijndael as the AES was not surprising, and we had to 
    content ourselves with silver in the `encryption olympics'. Serpent 
    and Rijndael are in fact somewhat similar; the main difference is that 
    Rijndael is faster (having fewer rounds) but Serpent is more secure." 
       
    The PowerBASIC implementation appearing here is based on that of Brian 
    Gladman, which is available at: 
     http://fp.gladman.plus.com/cryptography_technology/ 
    The following notice appears in Gladman's Serpent code.
    --------------------------------------------------------------------
     This is an independent implementation of the encryption algorithm:   
                                                                          
           Serpent by Ross Anderson, Eli Biham and Lars Knudsen         
                                                                          
     which is a candidate algorithm in the Advanced Encryption Standard   
     programme of the US National Institute of Standards and Technology.  
                                                                          
     Copyright in this implementation is held by Dr B R Gladman but I     
     hereby give permission for its free direct or derivative use subject 
     to acknowledgment of its origin and compliance with any conditions   
     that the originators of the algorithm place on its exploitation.     
                                                                          
     Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999   
    -------------------------------------------------------------------  
       
    The PB implementation is hereby placed in the public domain.  Use it 
    as you wish.  My hope is discourage reliance on home-grown encryption 
    schemes in favor of well-examined, strong, freely available 
    algorithms. 
       
    In this posting, test-bed code appears below the SERPENT.BAS file 
    contents.  All code requires compiler releases 3.0/7.0 or later.
       
       
    <U>Implementation Notes</U>
    -- The algorithm operates on plaintext blocks of 16 bytes.  Encryption 
    of shorter blocks is possible only by padding the plaintext (usually 
    with zero bytes), which can be accomplished through several methods.  
    The simplest of them assumes that the final byte of plaintext always 
    identifies the number of bytes of padding added, including the final 
    byte itself. 
       
    Examples: 
       
       total plaintext bytes         = 30
       plaintext blocks encrypted:   = 2
       final block                   = chr$(x1 to x14) + chr$(0,2)
       
       total plaintext bytes         = 40
       plaintext blocks encrypted:   = 3
       final block                   = chr$(x1 to x8) + chr$(0,0,0,0,0,0,0,8)
       
    -- Encryption key lengths can range from 1 to 32 bytes (8 to 256
    bits).  
       
    -- Implementation here is handled through an #INCLUDE file.  No global 
    data is employed.  
       
    -- As presented, the code does not supply a ready-to-use encryption 
    application.  It offers necessary pieces only, as well as an 
    illustration of their use.  Always keep in mind that most encryption 
    is broken because of implementation flaws and weaknesses. 
       
    -- Like most encryption algorithms, Serpent was designed on big-endian 
    systems.  For this reason, little-endian systems return correct test 
    vector results only through considerable byte-swapping, with 
    efficiency suffering as a result.  Because it adds nothing to the 
    encryption security, an efficient implementation should avoid the 
    byte-swapping.  Here the equate %VERIFY_IMPLEMENTATION can be remmed 
    to avoid this byte-swapping. 
       
    -- Because of the methods of data handling required for most 
    encryption and hashing, PowerBASIC's LONGs should be used to assure  
    correct bit-level results (as well as additional speed). 
       
    Greg Turgeon 07/2002
       
    #ENDIF
       
    '-- Rem this equate for any use other than verification of implementation.
    %VERIFY_IMPLEMENTATION = 1
       
    %BLOCKSIZE      = 16
    %KEY_SIZE       = 32
    %SUBKEY_SIZE    = 140
    %MIN_KEY_SIZE   = 1
    %MAX_KEY_SIZE   = 32
       
    '-- Note: Strings (UserKey, etc) are processed 
    '   as 32-bit values, so LONG PTRs required
    TYPE ENCRYPTION_CONTEXT
    UserKeyLength  AS LONG
    UserKey        AS LONG PTR
    InBlock        AS LONG PTR
    OutBlock       AS LONG PTR
    K              AS LONG PTR                  '<-- pointer to subkey buffer
    K_Buffer       AS STRING * (%SUBKEY_SIZE*4) '<-- subkey buffer itself
    END TYPE
       
    DECLARE SUB Serpent_Init(Ctx AS ENCRYPTION_CONTEXT)
    DECLARE FUNCTION Set_Key&(Ctx AS ENCRYPTION_CONTEXT)
    DECLARE FUNCTION EncryptBlock&(Ctx AS ENCRYPTION_CONTEXT)
    DECLARE FUNCTION DecryptBlock&(Ctx AS ENCRYPTION_CONTEXT)
       
       
    '--------------------
    ' Utility macros
    '--------------------
       
    '--------------------
    MACRO zbs(x) = string$(x,0)
       
    '--------------------
    MACRO FUNCTION byte_swap(x)
    !  mov      eax, x
    !  bswap    eax
    !  mov      x, eax
    END MACRO = x
       
    '--------------------
    MACRO FUNCTION shiftl(x,shiftval)
    retval = x
    !  shl   retval, shiftval
    END MACRO = retval
       
    '--------------------
    MACRO FUNCTION rotr(x,rotval)
    retval = x
    !  mov   ecx, rotval
    !  ror   retval, cl
    END MACRO = retval
       
    '--------------------
    MACRO FUNCTION rotl(x,rotval)
    retval = x
    !  mov   ecx, rotval
    !  rol   retval, cl
    END MACRO = retval
       
    '--------------------
    MACRO FUNCTION rotl_11(x)
    !  mov   ecx, 11
    !  rol   lk, cl
    END MACRO = x
       
    '--------------------
    MACRO make_marker(i,klen,lk)
    !  mov   ecx, klen
    !  mov   eax, ecx
    !  shr   eax, 5
    !  mov   i, eax
    !  and   ecx, 31
    !  mov   eax, 1
    !  shl   eax, cl
    !  mov   lk, eax
    END MACRO
       
       
    '--------------------
    'Serpent macros
    '--------------------
    MACRO sb0(a,b,c,d,e,f,g,h)
    t1 = a XOR d    : t2  = a AND d   : t3 = c XOR t1   : t6 = b AND t1
    t4 = b XOR t3   : t10 = NOT t3    : h = t2 XOR t4   : t7 = a XOR t6
    t14 = NOT t7    : t8 = c OR t7    : t11 = t3 XOR t7 : g = t4 XOR t8
    t12 = h AND t11 : f = t10 XOR t12 : e = t12 XOR t14
    END MACRO
       
    '--------------------
    MACRO ib0(a,b,c,d,e,f,g,h)
    t1 = NOT a     : t2 = a XOR b     : t3 = t1 OR t2   : t4 = d XOR t3
    t7 = d AND t2  : t5 = c XOR t4    : t8 = t1 XOR t7  : g = t2 XOR t5
    t11 = a AND t4 : t9 = g AND t8    : t14 = t5 XOR t8 : f = t4 XOR t9
    t12 = t5 OR f  : h  = t11 XOR t12 : e = h XOR t14
    END MACRO
       
    '--------------------
    MACRO sb1(a,b,c,d,e,f,g,h)
    t1 = NOT a       : t2 = b XOR t1 : t3 = a OR t2    : t4 = d OR t2
    t5 = c XOR t3    : g = d XOR t5  : t7 = b XOR t4   : t8 = t2 XOR g
    t9 = t5 AND t7   : h = t8 XOR t9 : t11 = t5 XOR t7 : f = h XOR t11
    t13 = t8 AND t11 : e = t5 XOR t13
    END MACRO
       
    '--------------------
    MACRO ib1(a,b,c,d,e,f,g,h)
    t1 = a XOR d  : t2 = a AND b    : t3 = b XOR c  : t4  = a XOR t3
    t5 = b OR d   : t7 = c OR t1    : h = t4 XOR t5 : t8  = b XOR t7
    t11 = NOT t2  : t9 = t4 AND t8  : f = t1 XOR t9 : t13 = t9 XOR t11
    t12 = h AND f : g = t12 XOR t13 : t15 = a AND d : t16 = c XOR t13
    e = t15 XOR t16
    END MACRO
       
    '--------------------
    MACRO sb2(a,b,c,d,e,f,g,h)
    t1 = NOT a     : t2 = b XOR d  : t3 = c AND t1   : t13 = d OR t1
    e = t2 XOR t3  : t5 = c XOR t1 : t6 = c XOR e    : t7 = b AND t6
    t10 = e OR t5  : h = t5 XOR t7 : t9 = d OR t7    : t11 = t9 AND t10
    t14 = t2 XOR h : g = a XOR t11 : t15 = g XOR t13 : f = t14 XOR t15
    END MACRO
       
    '--------------------
    MACRO ib2(a,b,c,d,e,f,g,h)
    t1 = b XOR d  : t2 = NOT t1     : t3 = a XOR c     : t4 = c XOR t1
    t7 = a OR t2  : t5 = b AND t4   : t8 = d XOR t7    : t11 = NOT t4
    e = t3 XOR t5 : t9 = t3 OR t8   : t14 = d AND t11  : h = t1 XOR t9
    t12 = e OR h  : f = t11 XOR t12 : t15 = t3 XOR t12 : g = t14 XOR t15
    END MACRO
       
    '--------------------
    MACRO sb3(a,b,c,d,e,f,g,h)
    t1 = a XOR c   : t2 = d XOR t1   : t3 = a AND t2   : t4 = d XOR t3
    t5 = b AND t4  : g = t2 XOR t5   : t7 = a OR g     : t8 = b OR d
    t11 = a OR d   : t9 = t4 AND t7  : f = t8 XOR t9   : t12 = b XOR t11
    t13 = g XOR t9 : t15 = t3 XOR t8 : h = t12 XOR t13 : t16 = c AND t15
    e = t12 XOR t16
    END MACRO
       
    '--------------------
    MACRO ib3(a,b,c,d,e,f,g,h)
    t1 = b XOR c    : t2 = b OR c    : t3 = a XOR c     : t7 = a XOR d
    t4 = t2 XOR t3  : t5 = d OR t4   : t9 = t2 XOR t7   : e = t1 XOR t5
    t8 = t1 OR t5   : t11 = a AND t4 : g = t8 XOR t9    : t12 = e OR t9
    f = t11 XOR t12 : t14 = a AND g  : t15 = t2 XOR t14 : t16 = e AND t15
    h = t4 XOR t16
    END MACRO
       
    '--------------------
    MACRO sb4(a,b,c,d,e,f,g,h)
    t1 = a XOR d   : t2 = d AND t1   : t3 = c XOR t2    : t4 = b OR t3
    h = t1 XOR t4  : t6 = NOT b      : t7 = t1 OR t6    : e = t3 XOR t7
    t9 = a AND e   : t10 = t1 XOR t6 : t11 = t4 AND t10 : g = t9 XOR t11
    t13 = a XOR t3 : t14 = t10 AND g : f = t13 XOR t14
    END MACRO
       
    '--------------------
    MACRO ib4(a,b,c,d,e,f,g,h)
    t1 = c XOR d   : t2 = c OR d   : t3 = b XOR t2    : t4 = a AND t3
    f = t1 XOR t4  : t6 = a XOR d  : t7 = b OR d      : t8 = t6 AND t7
    h = t3 XOR t8  : t10 = NOT a   : t11 = c XOR h    : t12 = t10 OR t11
    e = t3 XOR t12 : t14 = c OR t4 : t15 = t7 XOR t14 : t16 = h OR t10
    g = t15 XOR t16
    END MACRO
       
    '--------------------
    MACRO sb5(a,b,c,d,e,f,g,h)
    t1 = NOT a     : t2 = a XOR b    : t3 = a XOR d    : t4 = c XOR t1
    t5 = t2 OR t3  : e = t4 XOR t5   : t7 = d AND e    : t8 = t2 XOR e
    t10 = t1 OR e  : f = t7 XOR t8   : t11 = t2 OR t7  : t12 = t3 XOR t10
    t14 = b XOR t7 : g = t11 XOR t12 : t15 = f AND t12 : h = t14 XOR t15
    END MACRO
       
    '--------------------
    MACRO ib5(a,b,c,d,e,f,g,h)
    t1 = NOT c    : t2 = b AND t1   : t3 = d XOR t2   : t4 = a AND t3
    t5 = b XOR t1 : h = t4 XOR t5   : t7 = b OR h     : t8 = a AND t7
    f = t3 XOR t8 : t10 = a OR d    : t11 = t1 XOR t7 : e = t10 XOR t11
    t13 = a XOR c : t14 = b AND t10 : t15 = t4 OR t13 : g = t14 XOR t15
    END MACRO
       
    '--------------------
    MACRO sb6(a,b,c,d,e,f,g,h)
    t1 = NOT a    : t2 = a XOR d     : t3 = b XOR t2 : t4    = t1 OR t2
    t5 = c XOR t4 : f = b XOR t5     : t13 = NOT t5  : t7    = t2 OR f
    t8 = d XOR t7 : t9 = t5 AND t8   : g = t3 XOR t9 : t11   = t5 XOR t8
    e = g XOR t11 : t14 = t3 AND t11 : h = t13 XOR t14
    END MACRO
       
    '--------------------
    MACRO ib6(a,b,c,d,e,f,g,h)
    t1 = NOT a     : t2 = a XOR b     : t3 = c XOR t2 : t4 = c OR t1
    t5 = d XOR t4  : t13 = d AND t1   : f = t3 XOR t5 : t7 = t3 AND t5
    t8 = t2 XOR t7 : t9 = b OR t8     : h = t5 XOR t9 : t11 = b OR h
    e = t8 XOR t11 : t14 = t3 XOR t11 : g = t13 XOR t14
    END MACRO
       
    '--------------------
    MACRO sb7(a,b,c,d,e,f,g,h)
    t1 = NOT c     : t2 = b XOR c    : t3 = b OR t1    : t4 = d XOR t3
    t5 = a AND t4  : t7 = a XOR d    : h = t2 XOR t5   : t8 = b XOR t5
    t9 = t2 OR t8  : t11 = d AND t3  : f = t7 XOR t9   : t12 = t5 XOR f
    t15 = t1 OR t4 : t13 = h AND t12 : g = t11 XOR t13 : t16 = t12 XOR g
    e = t15 XOR t16
    END MACRO
       
    '--------------------
    MACRO ib7(a,b,c,d,e,f,g,h)
    t1 = a AND b    : t2 = a OR b   : t3 = c OR t1   : t4 = d AND t2
    h = t3 XOR t4   : t6 = NOT d    : t7 = b XOR t4  : t8 = h XOR t6
    t11 = c XOR t7  : t9 = t7 OR t8 : f = a XOR t9   : t12 = d OR f
    e = t11 XOR t12 : t14 = a AND h : t15 = t3 XOR f : t16 = e XOR t14
    g = t15 XOR t16
    END MACRO
       
    '--------------------
    MACRO k_xor(r,a,b,c,d)    
    a = a XOR @k[4*r+8]  : b = b XOR @k[4*r+9]
    c = c XOR @k[4*r+10] : d = d XOR @k[4*r+11]
    END MACRO
       
    '--------------------
    MACRO k_set(r,a,b,c,d)    
    a = @k[4*r+8]  : b = @k[4*r+9]
    c = @k[4*r+10] : d = @k[4*r+11]
    END MACRO
       
    '--------------------
    MACRO k_get(r,a,b,c,d)    
    @k[4*r+8] = a  : @k[4*r+9] = b
    @k[4*r+10] = c : @k[4*r+11] = d
    END MACRO
       
    '--------------------
    MACRO rot(a,b,c,d)    
    a = rotl(a,13)
    c = rotl(c,3)
    d = (d XOR c) XOR shiftl(a,3)
    b = b XOR a XOR c
    d = rotl(d,7)
    b = rotl(b,1)
    a = a XOR b XOR d
    c = (c XOR d) XOR shiftl(b,7)
    a = rotl(a,5)
    c = rotl(c,22)
    END MACRO
       
    '--------------------
    MACRO irot(a,b,c,d)   
    c = rotr(c,22)
    a = rotr(a,5)
    c = (c XOR d) XOR shiftl(b,7)
    a = a XOR b XOR d
    d = rotr(d,7)
    b = rotr(b,1)
    d = (d XOR c) XOR shiftl(a,3)
    b = b XOR a XOR c
    c = rotr(c,3)
    a = rotr(a,13)
    END MACRO
       
       
    '====================
    SUB Serpent_Init(Ctx AS ENCRYPTION_CONTEXT)
    Ctx.K_Buffer = zbs(%SUBKEY_SIZE*4)
    Ctx.K        = varptr(Ctx.K_BUFFER)
    END SUB
       
       
    '====================
    FUNCTION Set_Key&(Ctx AS ENCRYPTION_CONTEXT)
    '-- Returns %TRUE on success
    LOCAL k AS LONG PTR, uk AS LONG PTR
    LOCAL i&, j&, lk&, x&
    LOCAL a&, b&, c&, d&, e&, f&, g&, h&
    LOCAL t1&, t2&, t3&, t4&, t5&, t6&, t7&, t8&
    LOCAL t9&, t10&, t11&, t12&, t13&, t14&, t15&, t16&
    LOCAL retval& 'for macro use
       
    '-- Verify that Serpent_Init has been called
    if Ctx.K = 0 then
       function = 0 : exit function
    end if
       
    x = Ctx.UserKeyLength
       
    if(x < %MIN_KEY_SIZE) OR (x > %MAX_KEY_SIZE) then
       function = 0 : exit function
    end if
       
    '-- bytes --> bits
    x = (x * 8)
       
    uk = Ctx.UserKey : k = Ctx.K  'local copies
       
    i = 0 : lk = ((x + 31) \ 32) 
    do while (i < lk)
       #IF %def(%VERIFY_IMPLEMENTATION)
       j = @uk[lk-i-1] : @k[i] = byte_swap(j)
       #ELSE
       @k[i] = @uk[lk-i-1]
       #ENDIF
       incr i
    loop
       
    if (x < 256) then
       do while (i < 8)
          @k[i] = 0 : incr i
       loop
       make_marker(i,x,lk)
       @k[i] = @k[i] AND (lk-1) OR lk
    end if
       
    for i = 0 to 131
       lk = @k[i] XOR @k[i+3] XOR @k[i+5] XOR @k[i+7] XOR &h9e3779b9 XOR i
       @k[i+8] = rotl_11(lk)
    next i
       
    k_set(0,a,b,c,d)  : sb3(a,b,c,d,e,f,g,h) : k_get(0,e,f,g,h)
    k_set(1,a,b,c,d)  : sb2(a,b,c,d,e,f,g,h) : k_get(1,e,f,g,h)
    k_set(2,a,b,c,d)  : sb1(a,b,c,d,e,f,g,h) : k_get(2,e,f,g,h)
    k_set(3,a,b,c,d)  : sb0(a,b,c,d,e,f,g,h) : k_get(3,e,f,g,h)
    k_set(4,a,b,c,d)  : sb7(a,b,c,d,e,f,g,h) : k_get(4,e,f,g,h)
    k_set(5,a,b,c,d)  : sb6(a,b,c,d,e,f,g,h) : k_get(5,e,f,g,h)
    k_set(6,a,b,c,d)  : sb5(a,b,c,d,e,f,g,h) : k_get(6,e,f,g,h)
    k_set(7,a,b,c,d)  : sb4(a,b,c,d,e,f,g,h) : k_get(7,e,f,g,h)
    k_set(8,a,b,c,d)  : sb3(a,b,c,d,e,f,g,h) : k_get(8,e,f,g,h)
    k_set(9,a,b,c,d)  : sb2(a,b,c,d,e,f,g,h) : k_get(9,e,f,g,h)
    k_set(10,a,b,c,d) : sb1(a,b,c,d,e,f,g,h) : k_get(10,e,f,g,h)
    k_set(11,a,b,c,d) : sb0(a,b,c,d,e,f,g,h) : k_get(11,e,f,g,h)
    k_set(12,a,b,c,d) : sb7(a,b,c,d,e,f,g,h) : k_get(12,e,f,g,h)
    k_set(13,a,b,c,d) : sb6(a,b,c,d,e,f,g,h) : k_get(13,e,f,g,h)
    k_set(14,a,b,c,d) : sb5(a,b,c,d,e,f,g,h) : k_get(14,e,f,g,h)
    k_set(15,a,b,c,d) : sb4(a,b,c,d,e,f,g,h) : k_get(15,e,f,g,h)
    k_set(16,a,b,c,d) : sb3(a,b,c,d,e,f,g,h) : k_get(16,e,f,g,h)
    k_set(17,a,b,c,d) : sb2(a,b,c,d,e,f,g,h) : k_get(17,e,f,g,h)
    k_set(18,a,b,c,d) : sb1(a,b,c,d,e,f,g,h) : k_get(18,e,f,g,h)
    k_set(19,a,b,c,d) : sb0(a,b,c,d,e,f,g,h) : k_get(19,e,f,g,h)
    k_set(20,a,b,c,d) : sb7(a,b,c,d,e,f,g,h) : k_get(20,e,f,g,h)
    k_set(21,a,b,c,d) : sb6(a,b,c,d,e,f,g,h) : k_get(21,e,f,g,h)
    k_set(22,a,b,c,d) : sb5(a,b,c,d,e,f,g,h) : k_get(22,e,f,g,h)
    k_set(23,a,b,c,d) : sb4(a,b,c,d,e,f,g,h) : k_get(23,e,f,g,h)
    k_set(24,a,b,c,d) : sb3(a,b,c,d,e,f,g,h) : k_get(24,e,f,g,h)
    k_set(25,a,b,c,d) : sb2(a,b,c,d,e,f,g,h) : k_get(25,e,f,g,h)
    k_set(26,a,b,c,d) : sb1(a,b,c,d,e,f,g,h) : k_get(26,e,f,g,h)
    k_set(27,a,b,c,d) : sb0(a,b,c,d,e,f,g,h) : k_get(27,e,f,g,h)
    k_set(28,a,b,c,d) : sb7(a,b,c,d,e,f,g,h) : k_get(28,e,f,g,h)
    k_set(29,a,b,c,d) : sb6(a,b,c,d,e,f,g,h) : k_get(29,e,f,g,h)
    k_set(30,a,b,c,d) : sb5(a,b,c,d,e,f,g,h) : k_get(30,e,f,g,h)
    k_set(31,a,b,c,d) : sb4(a,b,c,d,e,f,g,h) : k_get(31,e,f,g,h)
    k_set(32,a,b,c,d) : sb3(a,b,c,d,e,f,g,h) : k_get(32,e,f,g,h)
       
    function = -1
    END FUNCTION
       
       
    '====================
    FUNCTION EncryptBlock&(CTX AS ENCRYPTION_CONTEXT)
    LOCAL a&, b&, c&, d&, e&, f&, g&, h&
    LOCAL t1&, t2&, t3&, t4&, t5&, t6&, t7&, t8&
    LOCAL t9&, t10&, t11&, t12&, t13&, t14&, t15&, t16&
    LOCAL k AS LONG PTR
    LOCAL retval& 'for macro use
       
    #IF %def(%VERIFY_IMPLEMENTATION)
    a = Ctx.@InBlock[3] : a = byte_swap(a)
    b = Ctx.@InBlock[2] : b = byte_swap(b)
    c = Ctx.@InBlock[1] : c = byte_swap(c)
    d = Ctx.@InBlock[0] : d = byte_swap(d)
    #ELSE
    a = Ctx.@InBlock[3]
    b = Ctx.@InBlock[2]
    c = Ctx.@InBlock[1]
    d = Ctx.@InBlock[0]
    #ENDIF
       
    k = Ctx.K 'local copy
    k_xor(0,a,b,c,d)  : sb0(a,b,c,d,e,f,g,h) : rot(e,f,g,h)
    k_xor(1,e,f,g,h)  : sb1(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(2,a,b,c,d)  : sb2(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(3,e,f,g,h)  : sb3(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(4,a,b,c,d)  : sb4(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(5,e,f,g,h)  : sb5(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(6,a,b,c,d)  : sb6(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(7,e,f,g,h)  : sb7(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(8,a,b,c,d)  : sb0(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(9,e,f,g,h)  : sb1(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(10,a,b,c,d) : sb2(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(11,e,f,g,h) : sb3(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(12,a,b,c,d) : sb4(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(13,e,f,g,h) : sb5(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(14,a,b,c,d) : sb6(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(15,e,f,g,h) : sb7(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(16,a,b,c,d) : sb0(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(17,e,f,g,h) : sb1(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(18,a,b,c,d) : sb2(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(19,e,f,g,h) : sb3(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(20,a,b,c,d) : sb4(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(21,e,f,g,h) : sb5(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(22,a,b,c,d) : sb6(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(23,e,f,g,h) : sb7(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(24,a,b,c,d) : sb0(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(25,e,f,g,h) : sb1(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(26,a,b,c,d) : sb2(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(27,e,f,g,h) : sb3(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(28,a,b,c,d) : sb4(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(29,e,f,g,h) : sb5(e,f,g,h,a,b,c,d) : rot(a,b,c,d) 
    k_xor(30,a,b,c,d) : sb6(a,b,c,d,e,f,g,h) : rot(e,f,g,h) 
    k_xor(31,e,f,g,h) : sb7(e,f,g,h,a,b,c,d)
    k_xor(32,a,b,c,d)
       
    #IF %def(%VERIFY_IMPLEMENTATION)
    Ctx.@OutBlock[3] = byte_swap(a)
    Ctx.@OutBlock[2] = byte_swap(b)
    Ctx.@OutBlock[1] = byte_swap(c)
    Ctx.@OutBlock[0] = byte_swap(d)
    #ELSE
    Ctx.@OutBlock[3] = a
    Ctx.@OutBlock[2] = b
    Ctx.@OutBlock[1] = c
    Ctx.@OutBlock[0] = d
    #ENDIF
    END FUNCTION
       
    '====================
    FUNCTION DecryptBlock&(CTX AS ENCRYPTION_CONTEXT)
    LOCAL a&, b&, c&, d&, e&, f&, g&, h&
    LOCAL t1&, t2&, t3&, t4&, t5&, t6&, t7&, t8&
    LOCAL t9&, t10&, t11&, t12&, t13&, t14&, t15&, t16&
    LOCAL retval& 'for macro use
    LOCAL k AS LONG PTR
       
    #IF %def(%VERIFY_IMPLEMENTATION)
    a = Ctx.@InBlock[3] : a = byte_swap(a)
    b = Ctx.@InBlock[2] : b = byte_swap(b)
    c = Ctx.@InBlock[1] : c = byte_swap(c)
    d = Ctx.@InBlock[0] : d = byte_swap(d)
    #ELSE
    a = Ctx.@InBlock[3]
    b = Ctx.@InBlock[2]
    c = Ctx.@InBlock[1]
    d = Ctx.@InBlock[0]
    #ENDIF
       
    k = Ctx.K 'local copy
       
    k_xor(32,a,b,c,d)
                    ib7(a,b,c,d,e,f,g,h) : k_xor(31,e,f,g,h)
    irot(e,f,g,h) : ib6(e,f,g,h,a,b,c,d) : k_xor(30,a,b,c,d)
    irot(a,b,c,d) : ib5(a,b,c,d,e,f,g,h) : k_xor(29,e,f,g,h)
    irot(e,f,g,h) : ib4(e,f,g,h,a,b,c,d) : k_xor(28,a,b,c,d)
    irot(a,b,c,d) : ib3(a,b,c,d,e,f,g,h) : k_xor(27,e,f,g,h)
    irot(e,f,g,h) : ib2(e,f,g,h,a,b,c,d) : k_xor(26,a,b,c,d)
    irot(a,b,c,d) : ib1(a,b,c,d,e,f,g,h) : k_xor(25,e,f,g,h)
    irot(e,f,g,h) : ib0(e,f,g,h,a,b,c,d) : k_xor(24,a,b,c,d)
    irot(a,b,c,d) : ib7(a,b,c,d,e,f,g,h) : k_xor(23,e,f,g,h)
    irot(e,f,g,h) : ib6(e,f,g,h,a,b,c,d) : k_xor(22,a,b,c,d)
    irot(a,b,c,d) : ib5(a,b,c,d,e,f,g,h) : k_xor(21,e,f,g,h)
    irot(e,f,g,h) : ib4(e,f,g,h,a,b,c,d) : k_xor(20,a,b,c,d)
    irot(a,b,c,d) : ib3(a,b,c,d,e,f,g,h) : k_xor(19,e,f,g,h)
    irot(e,f,g,h) : ib2(e,f,g,h,a,b,c,d) : k_xor(18,a,b,c,d)
    irot(a,b,c,d) : ib1(a,b,c,d,e,f,g,h) : k_xor(17,e,f,g,h)
    irot(e,f,g,h) : ib0(e,f,g,h,a,b,c,d) : k_xor(16,a,b,c,d)
    irot(a,b,c,d) : ib7(a,b,c,d,e,f,g,h) : k_xor(15,e,f,g,h)
    irot(e,f,g,h) : ib6(e,f,g,h,a,b,c,d) : k_xor(14,a,b,c,d)
    irot(a,b,c,d) : ib5(a,b,c,d,e,f,g,h) : k_xor(13,e,f,g,h)
    irot(e,f,g,h) : ib4(e,f,g,h,a,b,c,d) : k_xor(12,a,b,c,d)
    irot(a,b,c,d) : ib3(a,b,c,d,e,f,g,h) : k_xor(11,e,f,g,h)
    irot(e,f,g,h) : ib2(e,f,g,h,a,b,c,d) : k_xor(10,a,b,c,d)
    irot(a,b,c,d) : ib1(a,b,c,d,e,f,g,h) : k_xor( 9,e,f,g,h)
    irot(e,f,g,h) : ib0(e,f,g,h,a,b,c,d) : k_xor( 8,a,b,c,d)
    irot(a,b,c,d) : ib7(a,b,c,d,e,f,g,h) : k_xor( 7,e,f,g,h)
    irot(e,f,g,h) : ib6(e,f,g,h,a,b,c,d) : k_xor( 6,a,b,c,d)
    irot(a,b,c,d) : ib5(a,b,c,d,e,f,g,h) : k_xor( 5,e,f,g,h)
    irot(e,f,g,h) : ib4(e,f,g,h,a,b,c,d) : k_xor( 4,a,b,c,d)
    irot(a,b,c,d) : ib3(a,b,c,d,e,f,g,h) : k_xor( 3,e,f,g,h)
    irot(e,f,g,h) : ib2(e,f,g,h,a,b,c,d) : k_xor( 2,a,b,c,d)
    irot(a,b,c,d) : ib1(a,b,c,d,e,f,g,h) : k_xor( 1,e,f,g,h)
    irot(e,f,g,h) : ib0(e,f,g,h,a,b,c,d) : k_xor( 0,a,b,c,d)
       
    #IF %def(%VERIFY_IMPLEMENTATION)
    Ctx.@OutBlock[3] = byte_swap(a)
    Ctx.@OutBlock[2] = byte_swap(b)
    Ctx.@OutBlock[1] = byte_swap(c)
    Ctx.@OutBlock[0] = byte_swap(d)
    #ELSE
    Ctx.@OutBlock[3] = a
    Ctx.@OutBlock[2] = b
    Ctx.@OutBlock[1] = c
    Ctx.@OutBlock[0] = d
    #ENDIF
    END FUNCTION
    '-- end SERPENT.BAS
       
       
    '=====================================================================
    '                         Serpent Test Bed code
    '               Compiles with either PBWIN 7.0+ or PBCC 3.0+
    '=====================================================================
    #COMPILE EXE
    #REGISTER NONE
    #DIM ALL
    '============
    DEFLNG A-Z
       
    '--------------------
    '-- Utility macros
    '--------------------
       
    #IF %def(%pb_win32)
       MACRO eol=$CR
       MACRO mbox(t)=msgbox t
    #ELSEIF %def(%pb_cc32)
       MACRO eol=$CRLF
       MACRO mbox(t)=stdout t
    #ENDIF
       
    '--------------------
    MACRO EnterCC
    #IF %def(%pb_cc32)
       LOCAL launched&
       if (cursory = 1) and (cursorx = 1) then launched = -1
    #ENDIF
    END MACRO
       
    '--------------------
    MACRO ExitCC
    #IF %def(%pb_cc32)
       if launched then
          input flush
          stdout "Press any key to end"
          waitkey$
       end if
    #ENDIF
    END MACRO
       
    '--------------------
    ''MACRO zbs(x)=string$(x,0) 'also defined in SERPENT.BAS
       
    #INCLUDE "SERPENT.BAS"
       
    DECLARE FUNCTION Hex2Show$(Buffer$)
       
    '====================
    FUNCTION PBMain&()
    EnterCC
    LOCAL i&, key$, plain$, cipher$, shouldbe$, t$
    LOCAL ctx AS ENCRYPTION_CONTEXT  ' defined in SERPENT.BAS
       
    Serpent_Init ctx
       
    '-- Standard Serpent test vectors:
    '-- 256-bit key
    key      = chr$(&h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77,&h88,&h99,&haa,&hbb,&hcc,&hdd,&hee,&hff, _
                    &hff,&hee,&hdd,&hcc,&hbb,&haa,&h99,&h88,&h77,&h66,&h55,&h44,&h33,&h22,&h11,&h00)
    plain    = chr$(&h10,&h32,&h54,&h76,&h98,&hba,&hdc,&hfe,&hef,&hcd,&hab,&h89,&h67,&h45,&h23,&h01)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&h93,&hdf,&h9a,&h3c,&haf,&he3,&h87,&hbd,&h99,&h9e,&heb,&he3,&h93,&ha1,&h7f,&hca)
       
    t = "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key      =  chr$(&h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77,&h88,&h99,&haa,&hbb,&hcc,&hdd,&hee,&hff, _
                     &hff,&hee,&hdd,&hcc,&hbb,&haa,&h99,&h88,&h77,&h66,&h55,&h44,&h33,&h22,&h11,&h00)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
       
       
    '-- 192-bit key
    key      = chr$(&h88,&h99,&haa,&hbb,&hcc,&hdd,&hee,&hff,&hff,&hee,&hdd,&hcc,&hbb,&haa,&h99,&h88, _
                    &h77,&h66,&h55,&h44,&h33,&h22,&h11,&h00)
    plain    = chr$(&h10,&h32,&h54,&h76,&h98,&hba,&hdc,&hfe,&hef,&hcd,&hab,&h89,&h67,&h45,&h23,&h01)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&hda,&h86,&h08,&h42,&hb7,&h20,&h80,&h2b,&hf4,&h04,&ha4,&hc7,&h10,&h34,&h87,&h9a)
       
    t = t + "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key      = chr$(&h88,&h99,&haa,&hbb,&hcc,&hdd,&hee,&hff,&hff,&hee,&hdd,&hcc,&hbb,&haa,&h99,&h88, _
                    &h77,&h66,&h55,&h44,&h33,&h22,&h11,&h00)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
       
       
    '-- 128-bit key
    key      = chr$(&hff,&hee,&hdd,&hcc,&hbb,&haa,&h99,&h88,&h77,&h66,&h55,&h44,&h33,&h22,&h11,&h00)
    plain    = chr$(&h10,&h32,&h54,&h76,&h98,&hba,&hdc,&hfe,&hef,&hcd,&hab,&h89,&h67,&h45,&h23,&h01)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&hd5,&hba,&ha0,&h0a,&h4b,&hb9,&hd8,&ha7,&hc9,&h81,&hc8,&hdc,&h90,&hd8,&h9d,&h92)
       
    t = t + "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key      = chr$(&hff,&hee,&hdd,&hcc,&hbb,&haa,&h99,&h88,&h77,&h66,&h55,&h44,&h33,&h22,&h11,&h00)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
       
    mbox(t)
       
    '============
    ExitPBMain:
    ExitCC
    exit function
       
    '============
    DoEncrypt:
    #IF %def(%VERIFY_IMPLEMENTATION)    ' Set in SERPENT.BAS
    '-- Because test vectors are reversed in the published documentation, the following
    '   action is necessary when verifying the implementation.
    plain = strreverse$(plain) : key = strreverse$(key) : shouldbe = strreverse$(shouldbe)
    #ENDIF
       
    ctx.UserKey       = strptr(key)
    ctx.UserKeyLength = len(key)
    ctx.InBlock       = strptr(plain)
    ctx.OutBlock      = strptr(cipher)
    if Set_Key&(ctx) then 
       for i = 1 to (len(plain)\%BLOCKSIZE)  '<-- Required: (len(plain) mod 16) = 0
          EncryptBlock ctx
          ctx.InBlock  = ctx.InBlock  + %BLOCKSIZE
          ctx.OutBlock = ctx.OutBlock + %BLOCKSIZE
       next i&
    else
       mbox("Error")
    end if
    '-- Burn the subkey
    poke$ Ctx.K, zbs(sizeof(Ctx.K_Buffer))
    RETURN
       
    '============
    DoDecrypt:
    #IF %def(%VERIFY_IMPLEMENTATION)
    key = strreverse$(key)
    #ENDIF
    ctx.UserKey       = strptr(key)
    ctx.UserKeyLength = len(key)
    ctx.InBlock       = strptr(cipher)
    ctx.OutBlock      = strptr(plain)
    if Set_Key&(ctx) then 
       for i = 1 to (len(plain)\%BLOCKSIZE)  '<-- Required: (len(plain) mod 16) = 0
          DecryptBlock ctx
          ctx.InBlock  = ctx.InBlock  + %BLOCKSIZE
          ctx.OutBlock = ctx.OutBlock + %BLOCKSIZE
       next i
    else
       mbox("Error")
    end if
    #IF %def(%VERIFY_IMPLEMENTATION)
    plain = strreverse$(plain)
    #ENDIF
    '-- Burn the subkey
    poke$ Ctx.K, zbs(sizeof(Ctx.K_Buffer))
    RETURN
    END FUNCTION
       
    '====================
    FUNCTION Hex2Show$(Buffer$)
    REGISTER i&
    LOCAL t$, b AS BYTE PTR
    b = strptr(Buffer$)
    for i = 0 to len(Buffer$)-1
       t = t + hex$(@b[i],2) + " "
    next i
    function = t
    END FUNCTION
    '-- end TESTBED.BAS
    [This message has been edited by Greg Turgeon (edited July 09, 2002).]
Working...
X