2024-11-21

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

Twofish

Algorithm creator(s)

Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, Niels Ferguson


PB author(s)

Greg Turgeon


Description

Twofish is a 128-bit block cipher that accepts a variable-length key up to 256 bits. The cipher is a 16-round Feistel network with a bijective F function made up of four key-dependent 8-by-8-bit S-boxes, a fixed 4-by-4 maximum distance separable matrix over GF(28), a pseudo-Hadamard transform, bitwise rotations, and a carefully designed key schedule. A fully optimized implementation of Twofish encrypts on a Pentium Pro at 17.8 clock cycles per byte, and an 8-bit smart card implementation encrypts at 1820 clock cycles per byte. Twofish can be implemented in hardware in 14000 gates. The design of both the round function and the key schedule permits a wide variety of tradeoffs between speed, software size, key setup time, gate count, and memory.


Note

The Twofish algorithm is unpatented, uncopyrighted, and free for any use public or private, commercial or non-commercial.


Source

http://www.powerbasic.com/support/pbforums/showthread.php?t=23914


See also


Source Code

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

'This file contains two source code files.
'TWOFISH.INC is at the start, and a calling 
'demo (TESTBED.BAS) is at the end.
' 
'
'Start of TWOFISH.INC
#IF 0
=====================================================================
                         Twofish Encryption
=====================================================================
   
The block cipher Twofish was created by Bruce Schneier, John 
Kelsey, Doug Whiting, David Wagner, Chris Hall, AND Niels 
Ferguson.  The algorithm was one OF five finalists IN the 
international Advanced Encryption Standard competition TO SELECT 
a replacement FOR DES.  Information about Twofish can be obtained 
FROM Counterpane Labs AT: 
http://www.counterpane.com/twofish.html

The implementation presented here is based ON code IN C++ AND Java 
FROM a variety OF public domain sources.  Some aspects OF the PB code 
are based ON an implementation by Brian Gladman, IN which the 
following note appears: 
--------------------------------------------------------------------
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 Twofish algorithm is unpatented, uncopyrighted, AND free FOR ANY 
use public OR PRIVATE, commercial OR non-commercial.  

This 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 TWOFISH.INC file 
contents.  ALL code compiles WITH (AND requires) either PBCC 3.0+ OR 
PBWIN 7.0+. 
   
Implementation Notes
-- Twofish requires a large SET OF constant values.  These values 
can be hard-coded OR generated AT run-time depending ON the 
existence OF the %MAKE_TABLES equate.  IF the tables are 
generated AT run-time, the process occurs once only--during the 
first CALL TO Twofish_Init&(). 

-- The algorithm operates ON plaintext blocks OF 16 bytes.  Encryption 
OF shorter blocks is possible only by padding the plaintext (often  
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. 
   
-- 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). 

Thanks go TO Ken Meyers, who tested this version before I posted it ON 
the PB web site. 
   
Greg Turgeon 07/2003
#ENDIF

DEFLNG A-Z
'-- Rem out the following equate to hard-code the required constant values
'%MAKE_TABLES   = -1

%BLOCKSIZE     = 16
%ENCRYPT       = 1
%DECRYPT       = 2

TYPE TWOFISH_CONTEXT
   Action         AS LONG
   UserKeyLength  AS LONG
   UserKey        AS LONG PTR
   InBlock        AS LONG PTR
   OutBlock       AS LONG PTR

   KLength        AS LONG
   Q_0            AS BYTE PTR
   Q_1            AS BYTE PTR
   MDS_Table      AS LONG PTR
   XKey           AS LONG PTR       'expanded key
   XKey_Buffer    AS STRING * (40*4)
   S_Box          AS LONG PTR
   S_Box_Buffer   AS STRING * (4*256*4)
END TYPE


'--------------------
'Utility macros

'--------------------
MACRO Exit0 =FUNCTION = 0 : EXIT FUNCTION

'--------------------
MACRO zbs(x) =STRING$(x,0)

'--------------------
MACRO FUNCTION makebuffer(x)
MACROTEMP s
LOCAL s$
s = zbs(x)
END MACRO = STRPTR(s)

'--------------------
MACRO RepByte(x)
' x = x | (x<<8) | (x<<16) | (x<<24);
!mov  eax, x
!and  eax, &hff
!mov  edx, eax
!mov  ah, al
!mov  dh, dl
!shl  eax, 16
!or   eax, edx
!mov  x,   eax
END MACRO

'--------------------
MACRO FUNCTION shiftlc(x,constant_shiftval)
shl_ret = (x)
!shl shl_ret, constant_shiftval
END MACRO = shl_ret
'--------------------
MACRO FUNCTION shiftrc(x,constant_shiftval)
shr_ret = (x)
!shr shr_ret, constant_shiftval
END MACRO = shr_ret
'--------------------
MACRO FUNCTION rotlc(x,constant_rotate_val)
retval = (x)
!rol retval, constant_rotate_val
END MACRO = retval
'--------------------
MACRO FUNCTION rotrc(x,constant_rotate_val)
retval = (x)
!ror retval, constant_rotate_val
END MACRO = retval

'--------------------
MACRO idx0 =0 OF 3
MACRO idx1 =1 OF 3
MACRO idx2 =2 OF 3
MACRO idx3 =3 OF 3

'--------------------
MACRO FUNCTION byte3(x)
byte_ret = (x)
!mov   eax, byte_ret
!shr   eax, 24
!mov   byte_ret, eax
END MACRO = byte_ret

'--------------------
MACRO FUNCTION byte2(x)
byte_ret = (x)
!mov   eax, byte_ret
!shr   eax, 16
!and   eax, &hff
!mov   byte_ret, eax
END MACRO = byte_ret

'--------------------
MACRO FUNCTION byte1(x)
byte_ret = (x)
!mov   eax, byte_ret
!shr   eax, 8
!and   eax, &hff
!mov   byte_ret, eax
END MACRO = byte_ret

'--------------------
MACRO FUNCTION byte0(x)
byte_ret = (x)
!mov   eax, byte_ret
!and   eax, &hff
!mov   byte_ret, eax
END MACRO = byte_ret

'--------------------
' context shorthand macros
'--------------------
MACRO q0(n)       =Ctx.@Q_0[n]
MACRO q1(n)       =Ctx.@Q_1[n]
MACRO mds(n1,n2)  =Ctx.@MDS_Table[n1,n2]
MACRO sbox(n1,n2) =Ctx.@S_Box[n1,n2]


DECLARE FUNCTION Twofish_Init&(Ctx AS TWOFISH_CONTEXT)
DECLARE FUNCTION Set_Key&(Ctx AS TWOFISH_CONTEXT)
DECLARE FUNCTION EncryptBlock&(Ctx AS TWOFISH_CONTEXT)
DECLARE FUNCTION DecryptBlock&(Ctx AS TWOFISH_CONTEXT)

DECLARE FUNCTION hFunction&(Ctx AS TWOFISH_CONTEXT, BYVAL XX&, BYVAL Key AS LONG PTR)
DECLARE FUNCTION MDS_REM&(BYVAL p0&, BYVAL p1&)
DECLARE FUNCTION MakeSBoxes&(Ctx AS TWOFISH_CONTEXT, BYVAL Key AS LONG PTR)

#IF %DEF(%MAKE_TABLES)
DECLARE FUNCTION QP(BYVAL N&, BYVAL X?)
DECLARE FUNCTION Make_QTables&()
DECLARE FUNCTION Make_MDSTables&()
#ENDIF


'====================
FUNCTION Set_Key&(Ctx AS TWOFISH_CONTEXT)
LOCAL i&, j&, a&, b&, retval&, sboxkey AS LONG PTR

Twofish_Init Ctx

SELECT CASE AS LONG Ctx.UserKeyLength
   CASE <= 16
      Ctx.KLength = 2
   CASE <= 24
      Ctx.KLength = 3
   CASE <= 32
      Ctx.KLength = 4
   CASE ELSE
      Exit0
END SELECT

i = 0
DO WHILE i < 40
   a = hFunction&(Ctx,i,Ctx.UserKey)
   b = rotlc(hFunction&(Ctx,i+1,Ctx.UserKey+4),8)
   Ctx.@XKey[i]   = a + b
   Ctx.@XKey[i+1] = rotlc(a+2*b,9)
   INCR i : INCR i
LOOP

sboxkey = makebuffer(4*4)
j = Ctx.KLength-1
FOR i = 0 TO Ctx.KLength-1
   a = Ctx.@UserKey[2*i]
   b = Ctx.@UserKey[2*i+1]
   @sboxkey[j] = MDS_REM&(a,b)
   DECR j
NEXT i

MakeSBoxes Ctx, sboxkey
FUNCTION = -1
END FUNCTION


'====================
FUNCTION hFunction&(Ctx AS TWOFISH_CONTEXT, BYVAL XX&, BYVAL Key AS LONG PTR)
LOCAL x&, t0&, t1&, t2&, t3&, retval&, byte_ret&, shl_ret&
x = XX&
RepByte(x)
IF Ctx.KLength = 4 THEN GOTO Length4
IF Ctx.KLength = 3 THEN GOTO Length3
IF Ctx.KLength = 2 THEN GOTO Length2
Exit0

Length4:
   t0 =         q1(byte0(x))
   t1 = shiftlc(q0(byte1(x)),8)
   t2 = shiftlc(q0(byte2(x)),16) 
   t3 = shiftlc(q1(byte3(x)),24)
   x  = (t0 XOR t1 XOR t2 XOR t3) XOR @Key[6]
Length3:
   t0 =         q1(byte0(x))
   t1 = shiftlc(q1(byte1(x)),8)
   t2 = shiftlc(q0(byte2(x)),16) 
   t3 = shiftlc(q0(byte3(x)),24)
   x  = (t0 XOR t1 XOR t2 XOR t3) XOR @Key[4]
Length2:
   t0 =         q0(byte0(x)) 
   t1 = shiftlc(q1(byte1(x)),8)
   t2 = shiftlc(q0(byte2(x)),16) 
   t3 = shiftlc(q1(byte3(x)),24)
   x  = (t0 XOR t1 XOR t2 XOR t3) XOR @Key[2]

   t0 =         q0(byte0(x))
   t1 = shiftlc(q0(byte1(x)),8)
   t2 = shiftlc(q1(byte2(x)),16) 
   t3 = shiftlc(q1(byte3(x)),24)
   x  = (t0 XOR t1 XOR t2 XOR t3) XOR @Key[0]

t0 = byte0(x) : t1 = byte1(x) : t2 = byte2(x) : t3 = byte3(x)
FUNCTION = mds(t0 OF 255,idx0) XOR _
           mds(t1 OF 255,idx1) XOR _
           mds(t2 OF 255,idx2) XOR _
           mds(t3 OF 255,idx3)
END FUNCTION


%G_MOD         = &h0000014D???
%SHR1MODULUS   = &h000000A6???   'shr %G_MOD, 1
'====================
FUNCTION MDS_REM&(BYVAL p0&, BYVAL p1&)
LOCAL i&, t1&, t2&, t3&, tmp&, u&, retval&, shl_ret&, shr_ret&
FOR i = 0 TO 7
   t1 = p1&
   !shr t1, 24
   tmp = p1&
   !shl tmp, 8
   t2 = p0&
   !shr t2, 24
   p1& = tmp OR t2
   !shl p0&, 8
            
   u = t1
   !shl u, 1
   IF(t1 AND &h80) THEN u = u XOR %G_MOD
   tmp = u
   !shl tmp, 16
   p1& = p1& XOR t1 XOR tmp
   tmp = t1
   !shr tmp, 1
   u = u XOR tmp
   IF (t1 AND &h01) THEN u = u XOR %SHR1MODULUS
   t2 = u
   !shl t2, 24
   t3 = u
   !shl t3, 8
   p1& = p1& XOR t2 OR t3
NEXT i
FUNCTION = p1&
END FUNCTION

'-- Compiler limitation on nesting of macros requires the following forms:
MACRO q20(n) =(Ctx.@Q_0[Ctx.@Q_0[n] XOR byte0(@key[1])] XOR byte0(@key[0]))
MACRO q21(n) =(Ctx.@Q_0[Ctx.@Q_1[n] XOR byte1(@key[1])] XOR byte1(@key[0]))
MACRO q22(n) =(Ctx.@Q_1[Ctx.@Q_0[n] XOR byte2(@key[1])] XOR byte2(@key[0]))
MACRO q23(n) =(Ctx.@Q_1[Ctx.@Q_1[n] XOR byte3(@key[1])] XOR byte3(@key[0]))

MACRO q30(n) =(Ctx.@Q_0[Ctx.@Q_0[Ctx.@Q_1[n] XOR byte0(@key2)] XOR byte0(@key1)] XOR byte0(@key0))
MACRO q31(n) =(Ctx.@Q_0[Ctx.@Q_1[Ctx.@Q_1[n] XOR byte1(@key2)] XOR byte1(@key1)] XOR byte1(@key0))
MACRO q32(n) =(Ctx.@Q_1[Ctx.@Q_0[Ctx.@Q_0[n] XOR byte2(@key2)] XOR byte2(@key1)] XOR byte2(@key0))
MACRO q33(n) =(Ctx.@Q_1[Ctx.@Q_1[Ctx.@Q_0[n] XOR byte3(@key2)] XOR byte3(@key1)] XOR byte3(@key0))

'-- NOTE: If cutting & pasting, line lengths of next four lines = 125 chars each
MACRO q40(n) =(Ctx.@Q_0[Ctx.@Q_0[Ctx.@Q_1[Ctx.@Q_1[n] XOR byte0(@key3)] XOR byte0(@key2)] XOR byte0(@key1)] XOR byte0(@key0))
MACRO q41(n) =(Ctx.@Q_0[Ctx.@Q_1[Ctx.@Q_1[Ctx.@Q_0[n] XOR byte1(@key3)] XOR byte1(@key2)] XOR byte1(@key1)] XOR byte1(@key0))
MACRO q42(n) =(Ctx.@Q_1[Ctx.@Q_0[Ctx.@Q_0[Ctx.@Q_0[n] XOR byte2(@key3)] XOR byte2(@key2)] XOR byte2(@key1)] XOR byte2(@key0))
MACRO q43(n) =(Ctx.@Q_1[Ctx.@Q_1[Ctx.@Q_0[Ctx.@Q_1[n] XOR byte3(@key3)] XOR byte3(@key2)] XOR byte3(@key1)] XOR byte3(@key0))

'====================
FUNCTION MakeSBoxes&(Ctx AS TWOFISH_CONTEXT, BYVAL Key AS LONG PTR)
LOCAL i&, byte_ret&
LOCAL key0 AS LONG PTR, key1 AS LONG PTR, key2 AS LONG PTR, key3 AS LONG PTR
key0 = Key : key1 = key0 + 4 : key2 = key0 + 8 : key3 = key0 + 12
SELECT CASE AS LONG Ctx.KLength
   CASE 2
      FOR i = 0 TO 255
         sbox(i OF 255,idx0) = mds(q20(i) OF 255,idx0)
         sbox(i OF 255,idx1) = mds(q21(i) OF 255,idx1)
         sbox(i OF 255,idx2) = mds(q22(i) OF 255,idx2) 
         sbox(i OF 255,idx3) = mds(q23(i) OF 255,idx3)
      NEXT i
   CASE 3
      FOR i = 0 TO 255
         sbox(i OF 255,idx0) = mds(q30(i) OF 255,idx0)
         sbox(i OF 255,idx1) = mds(q31(i) OF 255,idx1)
         sbox(i OF 255,idx2) = mds(q32(i) OF 255,idx2)
         sbox(i OF 255,idx3) = mds(q33(i) OF 255,idx3)
      NEXT i
   CASE 4
      FOR i = 0 TO 255
         sbox(i OF 255,idx0) = mds(q40(i) OF 255,idx0)
         sbox(i OF 255,idx1) = mds(q41(i) OF 255,idx1)
         sbox(i OF 255,idx2) = mds(q42(i) OF 255,idx2)
         sbox(i OF 255,idx3) = mds(q43(i) OF 255,idx3)
      NEXT i
END SELECT
END FUNCTION


'--------------------
MACRO FUNCTION g0_fun(n)
tt0 = sbox(byte0(n) OF 255,idx0)
tt1 = sbox(byte1(n) OF 255,idx1)
tt2 = sbox(byte2(n) OF 255,idx2)
tt3 = sbox(byte3(n) OF 255,idx3)
END MACRO = (tt0 XOR tt1 XOR tt2 XOR tt3)

'--------------------
MACRO FUNCTION g1_fun(n)
tt0 = sbox(byte3(n) OF 255,idx0)
tt1 = sbox(byte0(n) OF 255,idx1)
tt2 = sbox(byte1(n) OF 255,idx2)
tt3 = sbox(byte2(n) OF 255,idx3)
END MACRO = (tt0 XOR tt1 XOR tt2 XOR tt3)


'--------------------
MACRO f_rnd(i)
t1 = g1_fun(@blk[1]) : t0 = g0_fun(@blk[0])
t  = @blk[2] XOR (t0 + t1 + Ctx.@XKey[4*i+8])
!ror t, 1
@blk[2] = t
t  = @blk[3]
!rol t, 1
@blk[3] = t XOR (t0 + 2*t1 + Ctx.@XKey[4*i+9])
t1 = g1_fun(@blk[3]) : t0 = g0_fun(@blk[2])
t  = @blk[0] XOR (t0 + t1 + Ctx.@XKey[4*i+10])
!ror t, 1
@blk[0] = t
t  = @blk[1]
!rol t, 1
@blk[1] = t XOR (t0 + 2 * t1 + Ctx.@XKey[4*i+11])
END MACRO

'====================
FUNCTION EncryptBlock&(Ctx AS TWOFISH_CONTEXT)
LOCAL t&, t0&, t1&, tt0&, tt1&, tt2&, tt3&
LOCAL byte_ret&, blk AS LONG PTR

blk = makebuffer(%BLOCKSIZE)
@blk[0] = Ctx.@InBlock[0] XOR Ctx.@XKey[0]
@blk[1] = Ctx.@InBlock[1] XOR Ctx.@XKey[1]
@blk[2] = Ctx.@InBlock[2] XOR Ctx.@XKey[2]
@blk[3] = Ctx.@InBlock[3] XOR Ctx.@XKey[3]

f_rnd(0) : f_rnd(1) : f_rnd(2) : f_rnd(3)
f_rnd(4) : f_rnd(5) : f_rnd(6) : f_rnd(7)

Ctx.@OutBlock[0] = @blk[2] XOR Ctx.@XKey[4]
Ctx.@OutBlock[1] = @blk[3] XOR Ctx.@XKey[5]
Ctx.@OutBlock[2] = @blk[0] XOR Ctx.@XKey[6]
Ctx.@OutBlock[3] = @blk[1] XOR Ctx.@XKey[7] 
END FUNCTION


'--------------------
MACRO i_rnd(i)
t1 = g1_fun(@blk[1]) : t0 = g0_fun(@blk[0])
t  = @blk[2]
!rol t, 1
@blk[2] = t XOR (t0 + t1 + Ctx.@XKey[4*i+10])
t  = @blk[3] XOR (t0 + 2 * t1 + Ctx.@XKey[4*i+11])
!ror t, 1
@blk[3] = t
t1 = g1_fun(@blk[3]) : t0 = g0_fun(@blk[2])
t  = @blk[0]
!rol t, 1
@blk[0] = t  XOR (t0 + t1 + Ctx.@XKey[4*i+8])
t  = @blk[1] XOR (t0 + 2 * t1 + Ctx.@XKey[4*i+9])
!ror t, 1
@blk[1] = t
END MACRO

'====================
FUNCTION DecryptBlock&(Ctx AS TWOFISH_CONTEXT)
LOCAL t&, t0&, t1&, tt0&, tt1&, tt2&, tt3&
LOCAL byte_ret&, blk AS LONG PTR

blk = makebuffer(%BLOCKSIZE)
@blk[0] = Ctx.@InBlock[0] XOR Ctx.@XKey[4]
@blk[1] = Ctx.@InBlock[1] XOR Ctx.@XKey[5]
@blk[2] = Ctx.@InBlock[2] XOR Ctx.@XKey[6]
@blk[3] = Ctx.@InBlock[3] XOR Ctx.@XKey[7]

i_rnd(7) : i_rnd(6) : i_rnd(5) : i_rnd(4)
i_rnd(3) : i_rnd(2) : i_rnd(1) : i_rnd(0)

Ctx.@OutBlock[0] = @blk[2] XOR Ctx.@XKey[0]
Ctx.@OutBlock[1] = @blk[3] XOR Ctx.@XKey[1]
Ctx.@OutBlock[2] = @blk[0] XOR Ctx.@XKey[2]
Ctx.@OutBlock[3] = @blk[1] XOR Ctx.@XKey[3] 
END FUNCTION


'====================
FUNCTION Twofish_Init&(Ctx AS TWOFISH_CONTEXT)
STATIC pQTable0&, pQTable1&, pMDSTables&
Ctx.S_Box_Buffer  = zbs(SIZEOF(Ctx.S_Box_Buffer))
Ctx.S_Box         = VARPTR(Ctx.S_Box_Buffer)
Ctx.XKey_Buffer   = zbs(SIZEOF(Ctx.XKey_Buffer))
Ctx.XKey          = VARPTR(Ctx.XKey_Buffer)

IF pQTable0 = 0 THEN
   #IF %DEF(%MAKE_TABLES)
   pQTable0       = Make_QTables&
   pQTable1       = pQTable0 + 256
   pMDSTables     = Make_MDSTables&
   #ELSE
   pQTable0       = CODEPTR(Q_0)
   pQTable1       = CODEPTR(Q_1)
   pMDSTables     = CODEPTR(M_D_S)
   #ENDIF
END IF
Ctx.Q_0           = pQTable0
Ctx.Q_1           = pQTable1
Ctx.MDS_Table     = pMDSTables

#IF NOT %DEF(%MAKE_TABLES)
EXIT FUNCTION
Q_0:
!DB   &hA9, &h67, &hB3, &hE8, &h04, &hFD, &hA3, &h76, &h9A, &h92, &h80, &h78
!DB   &hE4, &hDD, &hD1, &h38, &h0D, &hC6, &h35, &h98, &h18, &hF7, &hEC, &h6C
!DB   &h43, &h75, &h37, &h26, &hFA, &h13, &h94, &h48, &hF2, &hD0, &h8B, &h30
!DB   &h84, &h54, &hDF, &h23, &h19, &h5B, &h3D, &h59, &hF3, &hAE, &hA2, &h82
!DB   &h63, &h01, &h83, &h2E, &hD9, &h51, &h9B, &h7C, &hA6, &hEB, &hA5, &hBE
!DB   &h16, &h0C, &hE3, &h61, &hC0, &h8C, &h3A, &hF5, &h73, &h2C, &h25, &h0B
!DB   &hBB, &h4E, &h89, &h6B, &h53, &h6A, &hB4, &hF1, &hE1, &hE6, &hBD, &h45
!DB   &hE2, &hF4, &hB6, &h66, &hCC, &h95, &h03, &h56, &hD4, &h1C, &h1E, &hD7
!DB   &hFB, &hC3, &h8E, &hB5, &hE9, &hCF, &hBF, &hBA, &hEA, &h77, &h39, &hAF
!DB   &h33, &hC9, &h62, &h71, &h81, &h79, &h09, &hAD, &h24, &hCD, &hF9, &hD8
!DB   &hE5, &hC5, &hB9, &h4D, &h44, &h08, &h86, &hE7, &hA1, &h1D, &hAA, &hED
!DB   &h06, &h70, &hB2, &hD2, &h41, &h7B, &hA0, &h11, &h31, &hC2, &h27, &h90
!DB   &h20, &hF6, &h60, &hFF, &h96, &h5C, &hB1, &hAB, &h9E, &h9C, &h52, &h1B
!DB   &h5F, &h93, &h0A, &hEF, &h91, &h85, &h49, &hEE, &h2D, &h4F, &h8F, &h3B
!DB   &h47, &h87, &h6D, &h46, &hD6, &h3E, &h69, &h64, &h2A, &hCE, &hCB, &h2F
!DB   &hFC, &h97, &h05, &h7A, &hAC, &h7F, &hD5, &h1A, &h4B, &h0E, &hA7, &h5A
!DB   &h28, &h14, &h3F, &h29, &h88, &h3C, &h4C, &h02, &hB8, &hDA, &hB0, &h17
!DB   &h55, &h1F, &h8A, &h7D, &h57, &hC7, &h8D, &h74, &hB7, &hC4, &h9F, &h72
!DB   &h7E, &h15, &h22, &h12, &h58, &h07, &h99, &h34, &h6E, &h50, &hDE, &h68
!DB   &h65, &hBC, &hDB, &hF8, &hC8, &hA8, &h2B, &h40, &hDC, &hFE, &h32, &hA4
!DB   &hCA, &h10, &h21, &hF0, &hD3, &h5D, &h0F, &h00, &h6F, &h9D, &h36, &h42
!DB   &h4A, &h5E, &hC1, &hE0
Q_1:
!DB   &h75, &hF3, &hC6, &hF4, &hDB, &h7B, &hFB, &hC8, &h4A, &hD3, &hE6, &h6B
!DB   &h45, &h7D, &hE8, &h4B, &hD6, &h32, &hD8, &hFD, &h37, &h71, &hF1, &hE1
!DB   &h30, &h0F, &hF8, &h1B, &h87, &hFA, &h06, &h3F, &h5E, &hBA, &hAE, &h5B
!DB   &h8A, &h00, &hBC, &h9D, &h6D, &hC1, &hB1, &h0E, &h80, &h5D, &hD2, &hD5
!DB   &hA0, &h84, &h07, &h14, &hB5, &h90, &h2C, &hA3, &hB2, &h73, &h4C, &h54
!DB   &h92, &h74, &h36, &h51, &h38, &hB0, &hBD, &h5A, &hFC, &h60, &h62, &h96
!DB   &h6C, &h42, &hF7, &h10, &h7C, &h28, &h27, &h8C, &h13, &h95, &h9C, &hC7
!DB   &h24, &h46, &h3B, &h70, &hCA, &hE3, &h85, &hCB, &h11, &hD0, &h93, &hB8
!DB   &hA6, &h83, &h20, &hFF, &h9F, &h77, &hC3, &hCC, &h03, &h6F, &h08, &hBF
!DB   &h40, &hE7, &h2B, &hE2, &h79, &h0C, &hAA, &h82, &h41, &h3A, &hEA, &hB9
!DB   &hE4, &h9A, &hA4, &h97, &h7E, &hDA, &h7A, &h17, &h66, &h94, &hA1, &h1D
!DB   &h3D, &hF0, &hDE, &hB3, &h0B, &h72, &hA7, &h1C, &hEF, &hD1, &h53, &h3E
!DB   &h8F, &h33, &h26, &h5F, &hEC, &h76, &h2A, &h49, &h81, &h88, &hEE, &h21
!DB   &hC4, &h1A, &hEB, &hD9, &hC5, &h39, &h99, &hCD, &hAD, &h31, &h8B, &h01
!DB   &h18, &h23, &hDD, &h1F, &h4E, &h2D, &hF9, &h48, &h4F, &hF2, &h65, &h8E
!DB   &h78, &h5C, &h58, &h19, &h8D, &hE5, &h98, &h57, &h67, &h7F, &h05, &h64
!DB   &hAF, &h63, &hB6, &hFE, &hF5, &hB7, &h3C, &hA5, &hCE, &hE9, &h68, &h44
!DB   &hE0, &h4D, &h43, &h69, &h29, &h2E, &hAC, &h15, &h59, &hA8, &h0A, &h9E
!DB   &h6E, &h47, &hDF, &h34, &h35, &h6A, &hCF, &hDC, &h22, &hC9, &hC0, &h9B
!DB   &h89, &hD4, &hED, &hAB, &h12, &hA2, &h0D, &h52, &hBB, &h02, &h2F, &hA9
!DB   &hD7, &h61, &h1E, &hB4, &h50, &h04, &hF6, &hC2, &h16, &h25, &h86, &h56
!DB   &h55, &h09, &hBE, &h91

M_D_S:
' idx0:
! DD  &hbcbc3275, &hecec21f3, &h202043c6, &hb3b3c9f4, &hdada03db, &h02028b7b, &he2e22bfb, &h9e9efac8
! DD  &hc9c9ec4a, &hd4d409d3, &h18186be6, &h1e1e9f6b, &h98980e45, &hb2b2387d, &ha6a6d2e8, &h2626b74b
! DD  &h3c3c57d6, &h93938a32, &h8282eed8, &h525298fd, &h7b7bd437, &hbbbb3771, &h5b5b97f1, &h474783e1
! DD  &h24243c30, &h5151e20f, &hbabac6f8, &h4a4af31b, &hbfbf4887, &h0d0d70fa, &hb0b0b306, &h7575de3f
! DD  &hd2d2fd5e, &h7d7d20ba, &h666631ae, &h3a3aa35b, &h59591c8a, &h00000000, &hcdcd93bc, &h1a1ae09d
! DD  &haeae2c6d, &h7f7fabc1, &h2b2bc7b1, &hbebeb90e, &he0e0a080, &h8a8a105d, &h3b3b52d2, &h6464bad5
! DD  &hd8d888a0, &he7e7a584, &h5f5fe807, &h1b1b1114, &h2c2cc2b5, &hfcfcb490, &h3131272c, &h808065a3
! DD  &h73732ab2, &h0c0c8173, &h79795f4c, &h6b6b4154, &h4b4b0292, &h53536974, &h94948f36, &h83831f51
! DD  &h2a2a3638, &hc4c49cb0, &h2222c8bd, &hd5d5f85a, &hbdbdc3fc, &h48487860, &hffffce62, &h4c4c0796
! DD  &h4141776c, &hc7c7e642, &hebeb24f7, &h1c1c1410, &h5d5d637c, &h36362228, &h6767c027, &he9e9af8c
! DD  &h4444f913, &h1414ea95, &hf5f5bb9c, &hcfcf18c7, &h3f3f2d24, &hc0c0e346, &h7272db3b, &h54546c70
! DD  &h29294cca, &hf0f035e3, &h0808fe85, &hc6c617cb, &hf3f34f11, &h8c8ce4d0, &ha4a45993, &hcaca96b8
! DD  &h68683ba6, &hb8b84d83, &h38382820, &he5e52eff, &hadad569f, &h0b0b8477, &hc8c81dc3, &h9999ffcc
! DD  &h5858ed03, &h19199a6f, &h0e0e0a08, &h95957ebf, &h70705040, &hf7f730e7, &h6e6ecf2b, &h1f1f6ee2
! DD  &hb5b53d79, &h09090f0c, &h616134aa, &h57571682, &h9f9f0b41, &h9d9d803a, &h111164ea, &h2525cdb9
! DD  &hafafdde4, &h4545089a, &hdfdf8da4, &ha3a35c97, &heaead57e, &h353558da, &hededd07a, &h4343fc17
! DD  &hf8f8cb66, &hfbfbb194, &h3737d3a1, &hfafa401d, &hc2c2683d, &hb4b4ccf0, &h32325dde, &h9c9c71b3
! DD  &h5656e70b, &he3e3da72, &h878760a7, &h15151b1c, &hf9f93aef, &h6363bfd1, &h3434a953, &h9a9a853e
! DD  &hb1b1428f, &h7c7cd133, &h88889b26, &h3d3da65f, &ha1a1d7ec, &he4e4df76, &h8181942a, &h91910149
! DD  &h0f0ffb81, &heeeeaa88, &h161661ee, &hd7d77321, &h9797f5c4, &ha5a5a81a, &hfefe3feb, &h6d6db5d9
! DD  &h7878aec5, &hc5c56d39, &h1d1de599, &h7676a4cd, &h3e3edcad, &hcbcb6731, &hb6b6478b, &hefef5b01
! DD  &h12121e18, &h6060c523, &h6a6ab0dd, &h4d4df61f, &hcecee94e, &hdede7c2d, &h55559df9, &h7e7e5a48
! DD  &h2121b24f, &h03037af2, &ha0a02665, &h5e5e198e, &h5a5a6678, &h65654b5c, &h62624e58, &hfdfd4519
! DD  &h0606f48d, &h404086e5, &hf2f2be98, &h3333ac57, &h17179067, &h05058e7f, &he8e85e05, &h4f4f7d64
! DD  &h89896aaf, &h10109563, &h74742fb6, &h0a0a75fe, &h5c5c92f5, &h9b9b74b7, &h2d2d333c, &h3030d6a5
! DD  &h2e2e49ce, &h494989e9, &h46467268, &h77775544, &ha8a8d8e0, &h9696044d, &h2828bd43, &ha9a92969
! DD  &hd9d97929, &h8686912e, &hd1d187ac, &hf4f44a15, &h8d8d1559, &hd6d682a8, &hb9b9bc0a, &h42420d9e
! DD  &hf6f6c16e, &h2f2fb847, &hdddd06df, &h23233934, &hcccc6235, &hf1f1c46a, &hc1c112cf, &h8585ebdc
! DD  &h8f8f9e22, &h7171a1c9, &h9090f0c0, &haaaa539b, &h0101f189, &h8b8be1d4, &h4e4e8ced, &h8e8e6fab
! DD  &hababa212, &h6f6f3ea2, &he6e6540d, &hdbdbf252, &h92927bbb, &hb7b7b602, &h6969ca2f, &h3939d9a9
! DD  &hd3d30cd7, &ha7a72361, &ha2a2ad1e, &hc3c399b4, &h6c6c4450, &h07070504, &h04047ff6, &h272746c2
! DD  &hacaca716, &hd0d07625, &h50501386, &hdcdcf756, &h84841a55, &he1e15109, &h7a7a25be, &h1313ef91
' idx1:
! DD  &ha9d93939, &h67901717, &hb3719c9c, &he8d2a6a6, &h04050707, &hfd985252, &ha3658080, &h76dfe4e4
! DD  &h9a084545, &h92024b4b, &h80a0e0e0, &h78665a5a, &he4ddafaf, &hddb06a6a, &hd1bf6363, &h38362a2a
! DD  &h0d54e6e6, &hc6432020, &h3562cccc, &h98bef2f2, &h181e1212, &hf724ebeb, &hecd7a1a1, &h6c774141
! DD  &h43bd2828, &h7532bcbc, &h37d47b7b, &h269b8888, &hfa700d0d, &h13f94444, &h94b1fbfb, &h485a7e7e
! DD  &hf27a0303, &hd0e48c8c, &h8b47b6b6, &h303c2424, &h84a5e7e7, &h54416b6b, &hdf06dddd, &h23c56060
! DD  &h1945fdfd, &h5ba33a3a, &h3d68c2c2, &h59158d8d, &hf321ecec, &hae316666, &ha23e6f6f, &h82165757
! DD  &h63951010, &h015befef, &h834db8b8, &h2e918686, &hd9b56d6d, &h511f8383, &h9b53aaaa, &h7c635d5d
! DD  &ha63b6868, &heb3ffefe, &ha5d63030, &hbe257a7a, &h16a7acac, &h0c0f0909, &he335f0f0, &h6123a7a7
! DD  &hc0f09090, &h8cafe9e9, &h3a809d9d, &hf5925c5c, &h73810c0c, &h2c273131, &h2576d0d0, &h0be75656
! DD  &hbb7b9292, &h4ee9cece, &h89f10101, &h6b9f1e1e, &h53a93434, &h6ac4f1f1, &hb499c3c3, &hf1975b5b
! DD  &he1834747, &he66b1818, &hbdc82222, &h450e9898, &he26e1f1f, &hf4c9b3b3, &hb62f7474, &h66cbf8f8
! DD  &hccff9999, &h95ea1414, &h03ed5858, &h56f7dcdc, &hd4e18b8b, &h1c1b1515, &h1eada2a2, &hd70cd3d3
! DD  &hfb2be2e2, &hc31dc8c8, &h8e195e5e, &hb5c22c2c, &he9894949, &hcf12c1c1, &hbf7e9595, &hba207d7d
! DD  &hea641111, &h77840b0b, &h396dc5c5, &haf6a8989, &h33d17c7c, &hc9a17171, &h62ceffff, &h7137bbbb
! DD  &h81fb0f0f, &h793db5b5, &h0951e1e1, &haddc3e3e, &h242d3f3f, &hcda47676, &hf99d5555, &hd8ee8282
! DD  &he5864040, &hc5ae7878, &hb9cd2525, &h4d049696, &h44557777, &h080a0e0e, &h86135050, &he730f7f7
! DD  &ha1d33737, &h1d40fafa, &haa346161, &hed8c4e4e, &h06b3b0b0, &h706c5454, &hb22a7373, &hd2523b3b
! DD  &h410b9f9f, &h7b8b0202, &ha088d8d8, &h114ff3f3, &h3167cbcb, &hc2462727, &h27c06767, &h90b4fcfc
! DD  &h20283838, &hf67f0404, &h60784848, &hff2ee5e5, &h96074c4c, &h5c4b6565, &hb1c72b2b, &hab6f8e8e
! DD  &h9e0d4242, &h9cbbf5f5, &h52f2dbdb, &h1bf34a4a, &h5fa63d3d, &h9359a4a4, &h0abcb9b9, &hef3af9f9
! DD  &h91ef1313, &h85fe0808, &h49019191, &hee611616, &h2d7cdede, &h4fb22121, &h8f42b1b1, &h3bdb7272
! DD  &h47b82f2f, &h8748bfbf, &h6d2caeae, &h46e3c0c0, &hd6573c3c, &h3e859a9a, &h6929a9a9, &h647d4f4f
! DD  &h2a948181, &hce492e2e, &hcb17c6c6, &h2fca6969, &hfcc3bdbd, &h975ca3a3, &h055ee8e8, &h7ad0eded
! DD  &hac87d1d1, &h7f8e0505, &hd5ba6464, &h1aa8a5a5, &h4bb72626, &h0eb9bebe, &ha7608787, &h5af8d5d5
! DD  &h28223636, &h14111b1b, &h3fde7575, &h2979d9d9, &h88aaeeee, &h3c332d2d, &h4c5f7979, &h02b6b7b7
! DD  &hb896caca, &hda583535, &hb09cc4c4, &h17fc4343, &h551a8484, &h1ff64d4d, &h8a1c5959, &h7d38b2b2
! DD  &h57ac3333, &hc718cfcf, &h8df40606, &h74695353, &hb7749b9b, &hc4f59797, &h9f56adad, &h72dae3e3
! DD  &h7ed5eaea, &h154af4f4, &h229e8f8f, &h12a2abab, &h584e6262, &h07e85f5f, &h99e51d1d, &h34392323
! DD  &h6ec1f6f6, &h50446c6c, &hde5d3232, &h68724646, &h6526a0a0, &hbc93cdcd, &hdb03dada, &hf8c6baba
! DD  &hc8fa9e9e, &ha882d6d6, &h2bcf6e6e, &h40507070, &hdceb8585, &hfe750a0a, &h328a9393, &ha48ddfdf
! DD  &hca4c2929, &h10141c1c, &h2173d7d7, &hf0ccb4b4, &hd309d4d4, &h5d108a8a, &h0fe25151, &h00000000
! DD  &h6f9a1919, &h9de01a1a, &h368f9494, &h42e6c7c7, &h4aecc9c9, &h5efdd2d2, &hc1ab7f7f, &he0d8a8a8
' idx2:
! DD  &hbc75bc32, &hecf3ec21, &h20c62043, &hb3f4b3c9, &hdadbda03, &h027b028b, &he2fbe22b, &h9ec89efa
! DD  &hc94ac9ec, &hd4d3d409, &h18e6186b, &h1e6b1e9f, &h9845980e, &hb27db238, &ha6e8a6d2, &h264b26b7
! DD  &h3cd63c57, &h9332938a, &h82d882ee, &h52fd5298, &h7b377bd4, &hbb71bb37, &h5bf15b97, &h47e14783
! DD  &h2430243c, &h510f51e2, &hbaf8bac6, &h4a1b4af3, &hbf87bf48, &h0dfa0d70, &hb006b0b3, &h753f75de
! DD  &hd25ed2fd, &h7dba7d20, &h66ae6631, &h3a5b3aa3, &h598a591c, &h00000000, &hcdbccd93, &h1a9d1ae0
! DD  &hae6dae2c, &h7fc17fab, &h2bb12bc7, &hbe0ebeb9, &he080e0a0, &h8a5d8a10, &h3bd23b52, &h64d564ba
! DD  &hd8a0d888, &he784e7a5, &h5f075fe8, &h1b141b11, &h2cb52cc2, &hfc90fcb4, &h312c3127, &h80a38065
! DD  &h73b2732a, &h0c730c81, &h794c795f, &h6b546b41, &h4b924b02, &h53745369, &h9436948f, &h8351831f
! DD  &h2a382a36, &hc4b0c49c, &h22bd22c8, &hd55ad5f8, &hbdfcbdc3, &h48604878, &hff62ffce, &h4c964c07
! DD  &h416c4177, &hc742c7e6, &hebf7eb24, &h1c101c14, &h5d7c5d63, &h36283622, &h672767c0, &he98ce9af
! DD  &h441344f9, &h149514ea, &hf59cf5bb, &hcfc7cf18, &h3f243f2d, &hc046c0e3, &h723b72db, &h5470546c
! DD  &h29ca294c, &hf0e3f035, &h088508fe, &hc6cbc617, &hf311f34f, &h8cd08ce4, &ha493a459, &hcab8ca96
! DD  &h68a6683b, &hb883b84d, &h38203828, &he5ffe52e, &had9fad56, &h0b770b84, &hc8c3c81d, &h99cc99ff
! DD  &h580358ed, &h196f199a, &h0e080e0a, &h95bf957e, &h70407050, &hf7e7f730, &h6e2b6ecf, &h1fe21f6e
! DD  &hb579b53d, &h090c090f, &h61aa6134, &h57825716, &h9f419f0b, &h9d3a9d80, &h11ea1164, &h25b925cd
! DD  &hafe4afdd, &h459a4508, &hdfa4df8d, &ha397a35c, &hea7eead5, &h35da3558, &hed7aedd0, &h431743fc
! DD  &hf866f8cb, &hfb94fbb1, &h37a137d3, &hfa1dfa40, &hc23dc268, &hb4f0b4cc, &h32de325d, &h9cb39c71
! DD  &h560b56e7, &he372e3da, &h87a78760, &h151c151b, &hf9eff93a, &h63d163bf, &h345334a9, &h9a3e9a85
! DD  &hb18fb142, &h7c337cd1, &h8826889b, &h3d5f3da6, &ha1eca1d7, &he476e4df, &h812a8194, &h91499101
! DD  &h0f810ffb, &hee88eeaa, &h16ee1661, &hd721d773, &h97c497f5, &ha51aa5a8, &hfeebfe3f, &h6dd96db5
! DD  &h78c578ae, &hc539c56d, &h1d991de5, &h76cd76a4, &h3ead3edc, &hcb31cb67, &hb68bb647, &hef01ef5b
! DD  &h1218121e, &h602360c5, &h6add6ab0, &h4d1f4df6, &hce4ecee9, &hde2dde7c, &h55f9559d, &h7e487e5a
! DD  &h214f21b2, &h03f2037a, &ha065a026, &h5e8e5e19, &h5a785a66, &h655c654b, &h6258624e, &hfd19fd45
! DD  &h068d06f4, &h40e54086, &hf298f2be, &h335733ac, &h17671790, &h057f058e, &he805e85e, &h4f644f7d
! DD  &h89af896a, &h10631095, &h74b6742f, &h0afe0a75, &h5cf55c92, &h9bb79b74, &h2d3c2d33, &h30a530d6
! DD  &h2ece2e49, &h49e94989, &h46684672, &h77447755, &ha8e0a8d8, &h964d9604, &h284328bd, &ha969a929
! DD  &hd929d979, &h862e8691, &hd1acd187, &hf415f44a, &h8d598d15, &hd6a8d682, &hb90ab9bc, &h429e420d
! DD  &hf66ef6c1, &h2f472fb8, &hdddfdd06, &h23342339, &hcc35cc62, &hf16af1c4, &hc1cfc112, &h85dc85eb
! DD  &h8f228f9e, &h71c971a1, &h90c090f0, &haa9baa53, &h018901f1, &h8bd48be1, &h4eed4e8c, &h8eab8e6f
! DD  &hab12aba2, &h6fa26f3e, &he60de654, &hdb52dbf2, &h92bb927b, &hb702b7b6, &h692f69ca, &h39a939d9
! DD  &hd3d7d30c, &ha761a723, &ha21ea2ad, &hc3b4c399, &h6c506c44, &h07040705, &h04f6047f, &h27c22746
! DD  &hac16aca7, &hd025d076, &h50865013, &hdc56dcf7, &h8455841a, &he109e151, &h7abe7a25, &h139113ef
' idx3:
! DD  &hd939a9d9, &h90176790, &h719cb371, &hd2a6e8d2, &h05070405, &h9852fd98, &h6580a365, &hdfe476df
! DD  &h08459a08, &h024b9202, &ha0e080a0, &h665a7866, &hddafe4dd, &hb06addb0, &hbf63d1bf, &h362a3836
! DD  &h54e60d54, &h4320c643, &h62cc3562, &hbef298be, &h1e12181e, &h24ebf724, &hd7a1ecd7, &h77416c77
! DD  &hbd2843bd, &h32bc7532, &hd47b37d4, &h9b88269b, &h700dfa70, &hf94413f9, &hb1fb94b1, &h5a7e485a
! DD  &h7a03f27a, &he48cd0e4, &h47b68b47, &h3c24303c, &ha5e784a5, &h416b5441, &h06dddf06, &hc56023c5
! DD  &h45fd1945, &ha33a5ba3, &h68c23d68, &h158d5915, &h21ecf321, &h3166ae31, &h3e6fa23e, &h16578216
! DD  &h95106395, &h5bef015b, &h4db8834d, &h91862e91, &hb56dd9b5, &h1f83511f, &h53aa9b53, &h635d7c63
! DD  &h3b68a63b, &h3ffeeb3f, &hd630a5d6, &h257abe25, &ha7ac16a7, &h0f090c0f, &h35f0e335, &h23a76123
! DD  &hf090c0f0, &hafe98caf, &h809d3a80, &h925cf592, &h810c7381, &h27312c27, &h76d02576, &he7560be7
! DD  &h7b92bb7b, &he9ce4ee9, &hf10189f1, &h9f1e6b9f, &ha93453a9, &hc4f16ac4, &h99c3b499, &h975bf197
! DD  &h8347e183, &h6b18e66b, &hc822bdc8, &h0e98450e, &h6e1fe26e, &hc9b3f4c9, &h2f74b62f, &hcbf866cb
! DD  &hff99ccff, &hea1495ea, &hed5803ed, &hf7dc56f7, &he18bd4e1, &h1b151c1b, &hada21ead, &h0cd3d70c
! DD  &h2be2fb2b, &h1dc8c31d, &h195e8e19, &hc22cb5c2, &h8949e989, &h12c1cf12, &h7e95bf7e, &h207dba20
! DD  &h6411ea64, &h840b7784, &h6dc5396d, &h6a89af6a, &hd17c33d1, &ha171c9a1, &hceff62ce, &h37bb7137
! DD  &hfb0f81fb, &h3db5793d, &h51e10951, &hdc3eaddc, &h2d3f242d, &ha476cda4, &h9d55f99d, &hee82d8ee
! DD  &h8640e586, &hae78c5ae, &hcd25b9cd, &h04964d04, &h55774455, &h0a0e080a, &h13508613, &h30f7e730
! DD  &hd337a1d3, &h40fa1d40, &h3461aa34, &h8c4eed8c, &hb3b006b3, &h6c54706c, &h2a73b22a, &h523bd252
! DD  &h0b9f410b, &h8b027b8b, &h88d8a088, &h4ff3114f, &h67cb3167, &h4627c246, &hc06727c0, &hb4fc90b4
! DD  &h28382028, &h7f04f67f, &h78486078, &h2ee5ff2e, &h074c9607, &h4b655c4b, &hc72bb1c7, &h6f8eab6f
! DD  &h0d429e0d, &hbbf59cbb, &hf2db52f2, &hf34a1bf3, &ha63d5fa6, &h59a49359, &hbcb90abc, &h3af9ef3a
! DD  &hef1391ef, &hfe0885fe, &h01914901, &h6116ee61, &h7cde2d7c, &hb2214fb2, &h42b18f42, &hdb723bdb
! DD  &hb82f47b8, &h48bf8748, &h2cae6d2c, &he3c046e3, &h573cd657, &h859a3e85, &h29a96929, &h7d4f647d
! DD  &h94812a94, &h492ece49, &h17c6cb17, &hca692fca, &hc3bdfcc3, &h5ca3975c, &h5ee8055e, &hd0ed7ad0
! DD  &h87d1ac87, &h8e057f8e, &hba64d5ba, &ha8a51aa8, &hb7264bb7, &hb9be0eb9, &h6087a760, &hf8d55af8
! DD  &h22362822, &h111b1411, &hde753fde, &h79d92979, &haaee88aa, &h332d3c33, &h5f794c5f, &hb6b702b6
! DD  &h96cab896, &h5835da58, &h9cc4b09c, &hfc4317fc, &h1a84551a, &hf64d1ff6, &h1c598a1c, &h38b27d38
! DD  &hac3357ac, &h18cfc718, &hf4068df4, &h69537469, &h749bb774, &hf597c4f5, &h56ad9f56, &hdae372da
! DD  &hd5ea7ed5, &h4af4154a, &h9e8f229e, &ha2ab12a2, &h4e62584e, &he85f07e8, &he51d99e5, &h39233439
! DD  &hc1f66ec1, &h446c5044, &h5d32de5d, &h72466872, &h26a06526, &h93cdbc93, &h03dadb03, &hc6baf8c6
! DD  &hfa9ec8fa, &h82d6a882, &hcf6e2bcf, &h50704050, &heb85dceb, &h750afe75, &h8a93328a, &h8ddfa48d
! DD  &h4c29ca4c, &h141c1014, &h73d72173, &hccb4f0cc, &h09d4d309, &h108a5d10, &he2510fe2, &h00000000
! DD  &h9a196f9a, &he01a9de0, &h8f94368f, &he6c742e6, &hecc94aec, &hfdd25efd, &hab7fc1ab, &hd8a8e0d8
#ENDIF   '%def(%MAKE_TABLES)
END FUNCTION

#IF %DEF(%MAKE_TABLES)
'====================
FUNCTION QP(BYVAL N&, BYVAL X?)
LOCAL a0?, a1?, a2?, a3?, a4?, b0?, b1?, b2?, b3?, b4?, shl_ret&, shr_ret&
LOCAL ror4 AS BYTE PTR, ashx AS BYTE PTR
LOCAL qt0 AS BYTE PTR, qt1 AS BYTE PTR, qt2 AS BYTE PTR, qt3 AS BYTE PTR

ror4 = CODEPTR(ror_4) : ashx = CODEPTR(ash_x)
qt0 = CODEPTR(qt_0) : qt1 = CODEPTR(qt_1) : qt2 = CODEPTR(qt_2) : qt3 = CODEPTR(qt_3)

a0 = shiftrc(X?,4)            : b0 = X? AND 15
a1 = a0 XOR b0                : b1 = @ror4[b0] XOR @ashx[a0]
a2 = @qt0[a1 OF 15,N& OF 15]  : b2 = @qt1[b1 OF 15,N& OF 15]
a3 = a2 XOR b2                : b3 = @ror4[b2] XOR @ashx[a2]
a4 = @qt2[a3 OF 15,N& OF 15]  : b4 = @qt3[b3 OF 15,N& OF 15]
FUNCTION = shiftlc(b4,4) OR a4
EXIT FUNCTION
ror_4:
!DB   0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
ash_x:
!DB   0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7
qt_0: '(16,2)
!DB   8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4
!DB   2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5
qt_1:  '(16,2)
!DB   14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13
!DB   1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8
qt_2:  '(16,2)
!DB   11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1
!DB   4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15
qt_3:  '(16,2)
!DB   13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10  
!DB   11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10
END FUNCTION

'====================
FUNCTION Make_QTables&()
STATIC qbuffer$
LOCAL i&, qq_0 AS BYTE PTR, qq_1 AS BYTE PTR
qbuffer = zbs(256*2) : qq_0 = STRPTR(qbuffer) : qq_1 = qq_0+256
FOR i = 0 TO 255
   @qq_0[i] = QP(0,(i AND &hff)) : @qq_1[i] = QP(1,(i AND &hff))
NEXT i
FUNCTION = qq_0
END FUNCTION

'--------------------
MACRO FUNCTION ffm_5b(x)
t0 = x
t1 = x
!shr t1, 2
END MACRO = (t0 XOR t1 XOR @tab_5b[x AND 3])
'--------------------
MACRO FUNCTION ffm_ef(x)
t0 = x
!shr t0, 1
t1 = x
!shr t1, 2
END MACRO = (x XOR t0 XOR t1 XOR @tab_ef[x AND 3])

'====================
FUNCTION Make_MDSTables&()
STATIC mdsbuffer$
LOCAL i&, t0&, t1&, t2&, retval&, shl_ret&, m AS LONG PTR
LOCAL f01&, f5b&, fef&, tab_5b AS LONG PTR, tab_ef AS LONG PTR

mdsbuffer = zbs(256*4*4) : m = STRPTR(mdsbuffer)
tab_5b = CODEPTR(table_5b) : tab_ef = CODEPTR(table_ef)
FOR i = 0 TO 255
   f01 = QP(1,i)       : f5b = ffm_5b(f01)    : fef = ffm_ef(f01)
   t0 = shiftlc(f5b,8) : t1 = shiftlc(fef,16) : t2 = shiftlc(fef,24)
   @m[i OF 255,idx0]   = f01 + t0 + t1 + t2
   t0 = shiftlc(fef,8) : t1 = shiftlc(f01,16) : t2 = shiftlc(fef,24)
   @m[i OF 255,idx2]   = f5b + t0 + t1 + t2

   f01 = QP(0,i)       : f5b = ffm_5b(f01)    : fef = ffm_ef(f01)
   t0 = shiftlc(fef,8) : t1 = shiftlc(f5b,16) : t2 = shiftlc(f01,24)
   @m[i OF 255,idx1]   = fef + t0 + t1 + t2
   t0 = shiftlc(f01,8) : t1 = shiftlc(fef,16) : t2 = shiftlc(f5b,24)
   @m[i OF 255,idx3]   = f5b + t0 + t1 + t2
NEXT i
FUNCTION = m
EXIT FUNCTION
table_5b:
!DD   &h00000000, &h0000005A, &h000000B4, &h000000EE
table_ef:
!DD   &h00000000, &h000000EE, &h000000B4, &h0000005A
END FUNCTION
#ENDIF
'-- end TWOFISH.INC
'
'
'
'
'
'
'#####################################################################
'
'
'
'
'
'
'=====================================================================
'                       Twofish Test Bed code
'               Compiles with either PBWIN 7.0+ or PBCC 3.0+
'=====================================================================
#COMPILE EXE
#REGISTER NONE
#DIM ALL
'============
DEFLNG A-Z
%USEMACROS = 1
#INCLUDE "WIN32API.INC"

'--------------------
'-- 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 TWOFISH.INC

'--------------------
MACRO hex8(x)=HEX$(x,8)+"h"

#INCLUDE "TWOFISH.INC"
DECLARE FUNCTION Hex2Show$(Buffer$)

'====================
FUNCTION PBMAIN&()
REGISTER i&
LOCAL key$, plain$, cipher$, shouldbe$, t$
LOCAL ctx AS TWOFISH_CONTEXT  ' defined in TWOFISH.INC
EnterCC

'-- Standard Twofish test vectors (from ECB_IVAL.TXT)
'-- 128-bit key
key$     = CHR$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
plain    = CHR$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
cipher   = zbs(LEN(plain))
shouldbe = CHR$(&h9F,&h58,&h9F,&h5C,&hF6,&h12,&h2C,&h32,&hB6,&hBF,&hEC,&h2F,&h2A,&hE8,&hC3,&h5A)
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,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
GOSUB DoDecrypt
t = t + "plain:    " + Hex2Show$(plain) + eol + eol

'-- 192-bit key
key      = CHR$(&h01,&h23,&h45,&h67,&h89,&hAB,&hCD,&hEF,&hFE,&hDC,&hBA,&h98,&h76,&h54,&h32,&h10, _
                &h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77)
plain    = CHR$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
cipher   = zbs(LEN(plain))
shouldbe = CHR$(&hCF,&hD1,&hD2,&hE5,&hA9,&hBE,&h9C,&hDF,&h50,&h1F,&h13,&hB8,&h92,&hBD,&h22,&h48)
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$(&h01,&h23,&h45,&h67,&h89,&hAB,&hCD,&hEF,&hFE,&hDC,&hBA,&h98,&h76,&h54,&h32,&h10, _
                &h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77)
GOSUB DoDecrypt
t = t + "plain:    " + Hex2Show$(plain) + eol + eol

'-- 256-bit key
key      = CHR$(&h01,&h23,&h45,&h67,&h89,&hAB,&hCD,&hEF,&hFE,&hDC,&hBA,&h98,&h76,&h54,&h32,&h10, _
                &h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77,&h88,&h99,&hAA,&hBB,&hCC,&hDD,&hEE,&hFF)
plain    = CHR$(&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00,&h00)
cipher   = zbs(LEN(plain))
shouldbe = CHR$(&h37,&h52,&h7B,&hE0,&h05,&h23,&h34,&hB8,&h9F,&h0C,&hFC,&hCA,&hE8,&h7C,&hFA,&h20)

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$(&h01,&h23,&h45,&h67,&h89,&hAB,&hCD,&hEF,&hFE,&hDC,&hBA,&h98,&h76,&h54,&h32,&h10, _
                &h00,&h11,&h22,&h33,&h44,&h55,&h66,&h77,&h88,&h99,&hAA,&hBB,&hCC,&hDD,&hEE,&hFF)
GOSUB DoDecrypt
t = t + "plain:    " + Hex2Show$(plain) + eol + eol
mbox(t)

Done:
ExitCC
EXIT FUNCTION

'============
DoEncrypt:
ctx.action        = %ENCRYPT
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("DoEncrypt SetKey Error")
END IF
'-- Burn the subkey
IF Ctx.S_Box THEN ZeroMemory(Ctx.S_Box,SIZEOF(Ctx.S_Box_Buffer))
IF Ctx.XKey  THEN ZeroMemory(Ctx.XKey, SIZEOF(Ctx.XKey_Buffer))
RETURN

'============
DoDecrypt:
ctx.action        = %DECRYPT
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("DoDecrypt SetKey Error")
END IF
'-- Burn the subkey
IF Ctx.S_Box THEN ZeroMemory(Ctx.S_Box,SIZEOF(Ctx.S_Box_Buffer))
IF Ctx.XKey  THEN ZeroMemory(Ctx.XKey, SIZEOF(Ctx.XKey_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