2024-04-29

Navigation

Skip Navigation Links

Hash algorithms

Asymmetric Algorithms

Symmetric Cipher Algorithms

Encoding Algorithms

Compression Algorithms

Pseudo Random Number Algorithms

Steganography

Library Wrappers

String Comparison

Others

Syntax highlighting by Prism
PBCrypto.com Mirror

Serpent

Algorithm creator(s)

Ross Anderson, Eli Biham, Lars Knudsen


PB author(s)

Greg Turgeon


Description

A 128-bit block cipher, finalist in the AES competition losing only to Rijndael. Serpent and Rijndael are in fact somewhat similar; the main difference is that Rijndael is faster (having fewer rounds) but Serpent is more secure.


Note

Please read source header for implementation notes.


Source

https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/24061-serpent-encryption-for-7-0-3-0?t=23436


See also

n/a


Source Code

Download source code file serpent.bas (Right-click -> "Save as ...")

#IF 0 

=====================================================================
                        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. Implementation Notes 
-- 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

Mirror provided by Knuth Konrad