www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - twofish

reply r <r_member pathlink.com> writes:
see blowfish

/**
* A class that provides Twofish encryption operations.
*
* This Java implementation is based on the Java reference
* implementation provided by Bruce Schneier and developed
* by Raif S. Naffah.
*/
public class TwofishEngine
{
private static const ubyte[][] P =  [
[  // p0
cast(ubyte) 0xA9, cast(ubyte) 0x67, cast(ubyte) 0xB3, cast(ubyte) 0xE8,
cast(ubyte) 0x04, cast(ubyte) 0xFD, cast(ubyte) 0xA3, cast(ubyte) 0x76,
cast(ubyte) 0x9A, cast(ubyte) 0x92, cast(ubyte) 0x80, cast(ubyte) 0x78,
cast(ubyte) 0xE4, cast(ubyte) 0xDD, cast(ubyte) 0xD1, cast(ubyte) 0x38,
cast(ubyte) 0x0D, cast(ubyte) 0xC6, cast(ubyte) 0x35, cast(ubyte) 0x98,
cast(ubyte) 0x18, cast(ubyte) 0xF7, cast(ubyte) 0xEC, cast(ubyte) 0x6C,
cast(ubyte) 0x43, cast(ubyte) 0x75, cast(ubyte) 0x37, cast(ubyte) 0x26,
cast(ubyte) 0xFA, cast(ubyte) 0x13, cast(ubyte) 0x94, cast(ubyte) 0x48,
cast(ubyte) 0xF2, cast(ubyte) 0xD0, cast(ubyte) 0x8B, cast(ubyte) 0x30,
cast(ubyte) 0x84, cast(ubyte) 0x54, cast(ubyte) 0xDF, cast(ubyte) 0x23,
cast(ubyte) 0x19, cast(ubyte) 0x5B, cast(ubyte) 0x3D, cast(ubyte) 0x59,
cast(ubyte) 0xF3, cast(ubyte) 0xAE, cast(ubyte) 0xA2, cast(ubyte) 0x82,
cast(ubyte) 0x63, cast(ubyte) 0x01, cast(ubyte) 0x83, cast(ubyte) 0x2E,
cast(ubyte) 0xD9, cast(ubyte) 0x51, cast(ubyte) 0x9B, cast(ubyte) 0x7C,
cast(ubyte) 0xA6, cast(ubyte) 0xEB, cast(ubyte) 0xA5, cast(ubyte) 0xBE,
cast(ubyte) 0x16, cast(ubyte) 0x0C, cast(ubyte) 0xE3, cast(ubyte) 0x61,
cast(ubyte) 0xC0, cast(ubyte) 0x8C, cast(ubyte) 0x3A, cast(ubyte) 0xF5,
cast(ubyte) 0x73, cast(ubyte) 0x2C, cast(ubyte) 0x25, cast(ubyte) 0x0B,
cast(ubyte) 0xBB, cast(ubyte) 0x4E, cast(ubyte) 0x89, cast(ubyte) 0x6B,
cast(ubyte) 0x53, cast(ubyte) 0x6A, cast(ubyte) 0xB4, cast(ubyte) 0xF1,
cast(ubyte) 0xE1, cast(ubyte) 0xE6, cast(ubyte) 0xBD, cast(ubyte) 0x45,
cast(ubyte) 0xE2, cast(ubyte) 0xF4, cast(ubyte) 0xB6, cast(ubyte) 0x66,
cast(ubyte) 0xCC, cast(ubyte) 0x95, cast(ubyte) 0x03, cast(ubyte) 0x56,
cast(ubyte) 0xD4, cast(ubyte) 0x1C, cast(ubyte) 0x1E, cast(ubyte) 0xD7,
cast(ubyte) 0xFB, cast(ubyte) 0xC3, cast(ubyte) 0x8E, cast(ubyte) 0xB5,
cast(ubyte) 0xE9, cast(ubyte) 0xCF, cast(ubyte) 0xBF, cast(ubyte) 0xBA,
cast(ubyte) 0xEA, cast(ubyte) 0x77, cast(ubyte) 0x39, cast(ubyte) 0xAF,
cast(ubyte) 0x33, cast(ubyte) 0xC9, cast(ubyte) 0x62, cast(ubyte) 0x71,
cast(ubyte) 0x81, cast(ubyte) 0x79, cast(ubyte) 0x09, cast(ubyte) 0xAD,
cast(ubyte) 0x24, cast(ubyte) 0xCD, cast(ubyte) 0xF9, cast(ubyte) 0xD8,
cast(ubyte) 0xE5, cast(ubyte) 0xC5, cast(ubyte) 0xB9, cast(ubyte) 0x4D,
cast(ubyte) 0x44, cast(ubyte) 0x08, cast(ubyte) 0x86, cast(ubyte) 0xE7,
cast(ubyte) 0xA1, cast(ubyte) 0x1D, cast(ubyte) 0xAA, cast(ubyte) 0xED,
cast(ubyte) 0x06, cast(ubyte) 0x70, cast(ubyte) 0xB2, cast(ubyte) 0xD2,
cast(ubyte) 0x41, cast(ubyte) 0x7B, cast(ubyte) 0xA0, cast(ubyte) 0x11,
cast(ubyte) 0x31, cast(ubyte) 0xC2, cast(ubyte) 0x27, cast(ubyte) 0x90,
cast(ubyte) 0x20, cast(ubyte) 0xF6, cast(ubyte) 0x60, cast(ubyte) 0xFF,
cast(ubyte) 0x96, cast(ubyte) 0x5C, cast(ubyte) 0xB1, cast(ubyte) 0xAB,
cast(ubyte) 0x9E, cast(ubyte) 0x9C, cast(ubyte) 0x52, cast(ubyte) 0x1B,
cast(ubyte) 0x5F, cast(ubyte) 0x93, cast(ubyte) 0x0A, cast(ubyte) 0xEF,
cast(ubyte) 0x91, cast(ubyte) 0x85, cast(ubyte) 0x49, cast(ubyte) 0xEE,
cast(ubyte) 0x2D, cast(ubyte) 0x4F, cast(ubyte) 0x8F, cast(ubyte) 0x3B,
cast(ubyte) 0x47, cast(ubyte) 0x87, cast(ubyte) 0x6D, cast(ubyte) 0x46,
cast(ubyte) 0xD6, cast(ubyte) 0x3E, cast(ubyte) 0x69, cast(ubyte) 0x64,
cast(ubyte) 0x2A, cast(ubyte) 0xCE, cast(ubyte) 0xCB, cast(ubyte) 0x2F,
cast(ubyte) 0xFC, cast(ubyte) 0x97, cast(ubyte) 0x05, cast(ubyte) 0x7A,
cast(ubyte) 0xAC, cast(ubyte) 0x7F, cast(ubyte) 0xD5, cast(ubyte) 0x1A,
cast(ubyte) 0x4B, cast(ubyte) 0x0E, cast(ubyte) 0xA7, cast(ubyte) 0x5A,
cast(ubyte) 0x28, cast(ubyte) 0x14, cast(ubyte) 0x3F, cast(ubyte) 0x29,
cast(ubyte) 0x88, cast(ubyte) 0x3C, cast(ubyte) 0x4C, cast(ubyte) 0x02,
cast(ubyte) 0xB8, cast(ubyte) 0xDA, cast(ubyte) 0xB0, cast(ubyte) 0x17,
cast(ubyte) 0x55, cast(ubyte) 0x1F, cast(ubyte) 0x8A, cast(ubyte) 0x7D,
cast(ubyte) 0x57, cast(ubyte) 0xC7, cast(ubyte) 0x8D, cast(ubyte) 0x74,
cast(ubyte) 0xB7, cast(ubyte) 0xC4, cast(ubyte) 0x9F, cast(ubyte) 0x72,
cast(ubyte) 0x7E, cast(ubyte) 0x15, cast(ubyte) 0x22, cast(ubyte) 0x12,
cast(ubyte) 0x58, cast(ubyte) 0x07, cast(ubyte) 0x99, cast(ubyte) 0x34,
cast(ubyte) 0x6E, cast(ubyte) 0x50, cast(ubyte) 0xDE, cast(ubyte) 0x68,
cast(ubyte) 0x65, cast(ubyte) 0xBC, cast(ubyte) 0xDB, cast(ubyte) 0xF8,
cast(ubyte) 0xC8, cast(ubyte) 0xA8, cast(ubyte) 0x2B, cast(ubyte) 0x40,
cast(ubyte) 0xDC, cast(ubyte) 0xFE, cast(ubyte) 0x32, cast(ubyte) 0xA4,
cast(ubyte) 0xCA, cast(ubyte) 0x10, cast(ubyte) 0x21, cast(ubyte) 0xF0,
cast(ubyte) 0xD3, cast(ubyte) 0x5D, cast(ubyte) 0x0F, cast(ubyte) 0x00,
cast(ubyte) 0x6F, cast(ubyte) 0x9D, cast(ubyte) 0x36, cast(ubyte) 0x42,
cast(ubyte) 0x4A, cast(ubyte) 0x5E, cast(ubyte) 0xC1, cast(ubyte) 0xE0 ],
[  // p1
cast(ubyte) 0x75, cast(ubyte) 0xF3, cast(ubyte) 0xC6, cast(ubyte) 0xF4,
cast(ubyte) 0xDB, cast(ubyte) 0x7B, cast(ubyte) 0xFB, cast(ubyte) 0xC8,
cast(ubyte) 0x4A, cast(ubyte) 0xD3, cast(ubyte) 0xE6, cast(ubyte) 0x6B,
cast(ubyte) 0x45, cast(ubyte) 0x7D, cast(ubyte) 0xE8, cast(ubyte) 0x4B,
cast(ubyte) 0xD6, cast(ubyte) 0x32, cast(ubyte) 0xD8, cast(ubyte) 0xFD,
cast(ubyte) 0x37, cast(ubyte) 0x71, cast(ubyte) 0xF1, cast(ubyte) 0xE1,
cast(ubyte) 0x30, cast(ubyte) 0x0F, cast(ubyte) 0xF8, cast(ubyte) 0x1B,
cast(ubyte) 0x87, cast(ubyte) 0xFA, cast(ubyte) 0x06, cast(ubyte) 0x3F,
cast(ubyte) 0x5E, cast(ubyte) 0xBA, cast(ubyte) 0xAE, cast(ubyte) 0x5B,
cast(ubyte) 0x8A, cast(ubyte) 0x00, cast(ubyte) 0xBC, cast(ubyte) 0x9D,
cast(ubyte) 0x6D, cast(ubyte) 0xC1, cast(ubyte) 0xB1, cast(ubyte) 0x0E,
cast(ubyte) 0x80, cast(ubyte) 0x5D, cast(ubyte) 0xD2, cast(ubyte) 0xD5,
cast(ubyte) 0xA0, cast(ubyte) 0x84, cast(ubyte) 0x07, cast(ubyte) 0x14,
cast(ubyte) 0xB5, cast(ubyte) 0x90, cast(ubyte) 0x2C, cast(ubyte) 0xA3,
cast(ubyte) 0xB2, cast(ubyte) 0x73, cast(ubyte) 0x4C, cast(ubyte) 0x54,
cast(ubyte) 0x92, cast(ubyte) 0x74, cast(ubyte) 0x36, cast(ubyte) 0x51,
cast(ubyte) 0x38, cast(ubyte) 0xB0, cast(ubyte) 0xBD, cast(ubyte) 0x5A,
cast(ubyte) 0xFC, cast(ubyte) 0x60, cast(ubyte) 0x62, cast(ubyte) 0x96,
cast(ubyte) 0x6C, cast(ubyte) 0x42, cast(ubyte) 0xF7, cast(ubyte) 0x10,
cast(ubyte) 0x7C, cast(ubyte) 0x28, cast(ubyte) 0x27, cast(ubyte) 0x8C,
cast(ubyte) 0x13, cast(ubyte) 0x95, cast(ubyte) 0x9C, cast(ubyte) 0xC7,
cast(ubyte) 0x24, cast(ubyte) 0x46, cast(ubyte) 0x3B, cast(ubyte) 0x70,
cast(ubyte) 0xCA, cast(ubyte) 0xE3, cast(ubyte) 0x85, cast(ubyte) 0xCB,
cast(ubyte) 0x11, cast(ubyte) 0xD0, cast(ubyte) 0x93, cast(ubyte) 0xB8,
cast(ubyte) 0xA6, cast(ubyte) 0x83, cast(ubyte) 0x20, cast(ubyte) 0xFF,
cast(ubyte) 0x9F, cast(ubyte) 0x77, cast(ubyte) 0xC3, cast(ubyte) 0xCC,
cast(ubyte) 0x03, cast(ubyte) 0x6F, cast(ubyte) 0x08, cast(ubyte) 0xBF,
cast(ubyte) 0x40, cast(ubyte) 0xE7, cast(ubyte) 0x2B, cast(ubyte) 0xE2,
cast(ubyte) 0x79, cast(ubyte) 0x0C, cast(ubyte) 0xAA, cast(ubyte) 0x82,
cast(ubyte) 0x41, cast(ubyte) 0x3A, cast(ubyte) 0xEA, cast(ubyte) 0xB9,
cast(ubyte) 0xE4, cast(ubyte) 0x9A, cast(ubyte) 0xA4, cast(ubyte) 0x97,
cast(ubyte) 0x7E, cast(ubyte) 0xDA, cast(ubyte) 0x7A, cast(ubyte) 0x17,
cast(ubyte) 0x66, cast(ubyte) 0x94, cast(ubyte) 0xA1, cast(ubyte) 0x1D,
cast(ubyte) 0x3D, cast(ubyte) 0xF0, cast(ubyte) 0xDE, cast(ubyte) 0xB3,
cast(ubyte) 0x0B, cast(ubyte) 0x72, cast(ubyte) 0xA7, cast(ubyte) 0x1C,
cast(ubyte) 0xEF, cast(ubyte) 0xD1, cast(ubyte) 0x53, cast(ubyte) 0x3E,
cast(ubyte) 0x8F, cast(ubyte) 0x33, cast(ubyte) 0x26, cast(ubyte) 0x5F,
cast(ubyte) 0xEC, cast(ubyte) 0x76, cast(ubyte) 0x2A, cast(ubyte) 0x49,
cast(ubyte) 0x81, cast(ubyte) 0x88, cast(ubyte) 0xEE, cast(ubyte) 0x21,
cast(ubyte) 0xC4, cast(ubyte) 0x1A, cast(ubyte) 0xEB, cast(ubyte) 0xD9,
cast(ubyte) 0xC5, cast(ubyte) 0x39, cast(ubyte) 0x99, cast(ubyte) 0xCD,
cast(ubyte) 0xAD, cast(ubyte) 0x31, cast(ubyte) 0x8B, cast(ubyte) 0x01,
cast(ubyte) 0x18, cast(ubyte) 0x23, cast(ubyte) 0xDD, cast(ubyte) 0x1F,
cast(ubyte) 0x4E, cast(ubyte) 0x2D, cast(ubyte) 0xF9, cast(ubyte) 0x48,
cast(ubyte) 0x4F, cast(ubyte) 0xF2, cast(ubyte) 0x65, cast(ubyte) 0x8E,
cast(ubyte) 0x78, cast(ubyte) 0x5C, cast(ubyte) 0x58, cast(ubyte) 0x19,
cast(ubyte) 0x8D, cast(ubyte) 0xE5, cast(ubyte) 0x98, cast(ubyte) 0x57,
cast(ubyte) 0x67, cast(ubyte) 0x7F, cast(ubyte) 0x05, cast(ubyte) 0x64,
cast(ubyte) 0xAF, cast(ubyte) 0x63, cast(ubyte) 0xB6, cast(ubyte) 0xFE,
cast(ubyte) 0xF5, cast(ubyte) 0xB7, cast(ubyte) 0x3C, cast(ubyte) 0xA5,
cast(ubyte) 0xCE, cast(ubyte) 0xE9, cast(ubyte) 0x68, cast(ubyte) 0x44,
cast(ubyte) 0xE0, cast(ubyte) 0x4D, cast(ubyte) 0x43, cast(ubyte) 0x69,
cast(ubyte) 0x29, cast(ubyte) 0x2E, cast(ubyte) 0xAC, cast(ubyte) 0x15,
cast(ubyte) 0x59, cast(ubyte) 0xA8, cast(ubyte) 0x0A, cast(ubyte) 0x9E,
cast(ubyte) 0x6E, cast(ubyte) 0x47, cast(ubyte) 0xDF, cast(ubyte) 0x34,
cast(ubyte) 0x35, cast(ubyte) 0x6A, cast(ubyte) 0xCF, cast(ubyte) 0xDC,
cast(ubyte) 0x22, cast(ubyte) 0xC9, cast(ubyte) 0xC0, cast(ubyte) 0x9B,
cast(ubyte) 0x89, cast(ubyte) 0xD4, cast(ubyte) 0xED, cast(ubyte) 0xAB,
cast(ubyte) 0x12, cast(ubyte) 0xA2, cast(ubyte) 0x0D, cast(ubyte) 0x52,
cast(ubyte) 0xBB, cast(ubyte) 0x02, cast(ubyte) 0x2F, cast(ubyte) 0xA9,
cast(ubyte) 0xD7, cast(ubyte) 0x61, cast(ubyte) 0x1E, cast(ubyte) 0xB4,
cast(ubyte) 0x50, cast(ubyte) 0x04, cast(ubyte) 0xF6, cast(ubyte) 0xC2,
cast(ubyte) 0x16, cast(ubyte) 0x25, cast(ubyte) 0x86, cast(ubyte) 0x56,
cast(ubyte) 0x55, cast(ubyte) 0x09, cast(ubyte) 0xBE, cast(ubyte) 0x91  ]
];

/**
* Define the fixed p0/p1 permutations used in keyed S-box lookup.
* By changing the following constant definitions, the S-boxes will
* automatically get changed in the Twofish engine.
*/
private static const int P_00 = 1;
private static const int P_01 = 0;
private static const int P_02 = 0;
private static const int P_03 = P_01 ^ 1;
private static const int P_04 = 1;

private static const int P_10 = 0;
private static const int P_11 = 0;
private static const int P_12 = 1;
private static const int P_13 = P_11 ^ 1;
private static const int P_14 = 0;

private static const int P_20 = 1;
private static const int P_21 = 1;
private static const int P_22 = 0;
private static const int P_23 = P_21 ^ 1;
private static const int P_24 = 0;

private static const int P_30 = 0;
private static const int P_31 = 1;
private static const int P_32 = 1;
private static const int P_33 = P_31 ^ 1;
private static const int P_34 = 1;

/* Primitive polynomial for GF(256) */
//private static const int GF256_FDBK =   0x169;
private static const int GF256_FDBK_2 = 0x169 / 2;
private static const int GF256_FDBK_4 = 0x169 / 4;

private static const int RS_GF_FDBK = 0x14D; // field generator

//====================================
// Useful constants
//====================================

private static const int    ROUNDS = 16;
private static const int    MAX_ROUNDS = 16;  // bytes = 128 bits
private static const int    BLOCK_SIZE = 16;  // bytes = 128 bits
private static const int    MAX_KEY_BITS = 256;

private static const int    INPUT_WHITEN=0;
private static const int    OUTPUT_WHITEN=INPUT_WHITEN+BLOCK_SIZE/4; // 4
private static const int    ROUND_SUBKEYS=OUTPUT_WHITEN+BLOCK_SIZE/4;// 8

private static const int    TOTAL_SUBKEYS=ROUND_SUBKEYS+2*MAX_ROUNDS;// 40

private static const int    SK_STEP = 0x02020202;
private static const int    SK_BUMP = 0x01010101;
private static const int    SK_ROTL = 9;

private bool encrypting = false;

private int gMDS0[MAX_KEY_BITS];
private int gMDS1[MAX_KEY_BITS];
private int gMDS2[MAX_KEY_BITS];
private int gMDS3[MAX_KEY_BITS];

/**
* gSubKeys[] and gSBox[] are eventually used in the 
* encryption and decryption methods.
*/
private int[] gSubKeys;
private int[] gSBox;

private int k64Cnt = 0;

private ubyte[] workingKey = null;

public this()
{
// calculate the MDS matrix
int[] m1 = new int[2];
int[] mX = new int[2];
int[] mY = new int[2];
int j;

for (int i=0; i< MAX_KEY_BITS ; i++)
{
j = P[0][i] & 0xff;
m1[0] = j;
mX[0] = Mx_X(j) & 0xff;
mY[0] = Mx_Y(j) & 0xff;

j = P[1][i] & 0xff;
m1[1] = j;
mX[1] = Mx_X(j) & 0xff;
mY[1] = Mx_Y(j) & 0xff;

gMDS0[i] = m1[P_00]       | mX[P_00] <<  8 |
mY[P_00] << 16 | mY[P_00] << 24;

gMDS1[i] = mY[P_10]       | mY[P_10] <<  8 |
mX[P_10] << 16 | m1[P_10] << 24;

gMDS2[i] = mX[P_20]       | mY[P_20] <<  8 |
m1[P_20] << 16 | mY[P_20] << 24;

gMDS3[i] = mX[P_30]       | m1[P_30] <<  8 |
mY[P_30] << 16 | mX[P_30] << 24;
}
}

this(bool encrypting, ubyte[] key = null) {
this();
init(encrypting, key);
}

/**
* initialise a Twofish cipher.
*
*  param forEncryption whether or not we are for encryption.
*  param params the parameters required to set up the cipher.
*  exception ArgumentException if the params argument is
* inappropriate.
*/
public void init(bool encrypting, ubyte[] key = null)
{
if (key != null)
{
this.encrypting = encrypting;
this.workingKey = key;
this.k64Cnt = (this.workingKey.length / 8); // pre-padded ?
setKey(this.workingKey);
}
else
throw new Exception("invalid parameter passed to Twofish init - key");
}

public char[] getAlgorithmName()
{
return "Twofish";
}

public  int processBlock(ubyte[] inBytes, int inOff, ubyte[] outBytes, int
outOff)
{
if (workingKey == null)
{
throw new Exception("Twofish not initialised");
}
if ((inOff + BLOCK_SIZE) > inBytes.length)
{
throw new Exception("input buffer too short");
}
if ((outOff + BLOCK_SIZE) > outBytes.length)
{
throw new Exception("output buffer too short");
}
if (encrypting)
{
encryptBlock(inBytes, inOff, outBytes, outOff);
}
else
{    
decryptBlock(inBytes, inOff, outBytes, outOff);
}
return BLOCK_SIZE;
}

public int processBlock(ubyte[] inBytes, inout ubyte[] outBytes)
{
int pad = 0; int inOff = 0;
if(workingKey == null) {
throw new Exception("Twofish not initialised");
}
if(inBytes.length == 0) {
throw new Exception("input buffer too short");
}
pad = inBytes.length % BLOCK_SIZE;
if(pad != 0) {
pad = BLOCK_SIZE - pad;
while(inOff < pad) {
inBytes ~= 0x0;
inOff++;
}
}
outBytes.length = inBytes.length;
inOff = 0;
while(inOff < inBytes.length) {
if(encrypting) {
encryptBlock(inBytes, inOff, outBytes, inOff);
}
else {
decryptBlock(inBytes, inOff, outBytes, inOff);
}
inOff += BLOCK_SIZE;
}
return inBytes.length;
}

public void reset()
{
if (this.workingKey != null)
{
setKey(this.workingKey);
}
}

public int getBlockSize()
{
return BLOCK_SIZE;
}

//==================================
// Private Implementation
//==================================

private void setKey(ubyte[] key)
{
int[] k32e = new int[MAX_KEY_BITS/64]; // 4
int[] k32o = new int[MAX_KEY_BITS/64]; // 4 

int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4 
gSubKeys = new int[TOTAL_SUBKEYS];

if ((k64Cnt < 1) || (k64Cnt > 4))
{
throw new Exception("Key size larger than 256 bits");
}

/*
* k64Cnt is the number of 8 ubyte blocks (64 chunks)
* that are in the input key.  The input key is a
* maximum of 32 bytes ( 256 bits ), so the range
* for k64Cnt is 1..4
*/
for (int i=0,p=0; i<k64Cnt ; i++)
{
p = i* 8;

k32e[i] = BytesTo32Bits(key, p);
k32o[i] = BytesTo32Bits(key, p+4);

sBoxKeys[k64Cnt-1-i] = RS_MDS_Encode(k32e[i], k32o[i]);
}

int q,A,B;
for (int i=0; i < TOTAL_SUBKEYS / 2 ; i++) 
{
q = i*SK_STEP;
A = F32(q,         k32e);
B = F32(q+SK_BUMP, k32o);
B = B << 8 | cast(int)(cast(uint)B >> 24);
A += B;
gSubKeys[i*2] = A;
A += B;
gSubKeys[i*2 + 1] = A << SK_ROTL | cast(int)(cast(uint)A >> (32-SK_ROTL));
}

/*
* fully expand the table for speed
*/
int k0 = sBoxKeys[0];
int k1 = sBoxKeys[1];
int k2 = sBoxKeys[2];
int k3 = sBoxKeys[3];
int b0, b1, b2, b3;
gSBox = new int[4*MAX_KEY_BITS];
for (int i=0; i<MAX_KEY_BITS; i++)
{
b0 = b1 = b2 = b3 = i;
switch (k64Cnt & 3)
{
case 1:
gSBox[i*2]       = gMDS0[(P[P_01][b0] & 0xff) ^ m_b0(k0)];
gSBox[i*2+1]     = gMDS1[(P[P_11][b1] & 0xff) ^ m_b1(k0)];
gSBox[i*2+0x200] = gMDS2[(P[P_21][b2] & 0xff) ^ m_b2(k0)];
gSBox[i*2+0x201] = gMDS3[(P[P_31][b3] & 0xff) ^ m_b3(k0)];
break;
case 0: /* 256 bits of key */
b0 = (P[P_04][b0] & 0xff) ^ m_b0(k3);
b1 = (P[P_14][b1] & 0xff) ^ m_b1(k3);
b2 = (P[P_24][b2] & 0xff) ^ m_b2(k3);
b3 = (P[P_34][b3] & 0xff) ^ m_b3(k3);
goto case 3;
case 3: 
b0 = (P[P_03][b0] & 0xff) ^ m_b0(k2);
b1 = (P[P_13][b1] & 0xff) ^ m_b1(k2);
b2 = (P[P_23][b2] & 0xff) ^ m_b2(k2);
b3 = (P[P_33][b3] & 0xff) ^ m_b3(k2);
goto case 2;
case 2:
gSBox[i*2]   = gMDS0[( P[P_01][(P[P_02][b0] & 0xff ) ^ m_b0(k1)] & 0xff) ^
m_b0(k0)];
gSBox[i*2+1] = gMDS1[(P[P_11][(P[P_12][b1] & 0xff) ^ m_b1(k1)] & 0xff) ^
m_b1(k0)];
gSBox[i*2+0x200] = gMDS2[(P[P_21][(P[P_22][b2] & 0xff) ^ m_b2(k1)] & 0xff) ^
m_b2(k0)];
gSBox[i*2+0x201] = gMDS3[(P[P_31][(P[P_32][b3] & 0xff) ^ m_b3(k1)] & 0xff) ^
m_b3(k0)];
break;
default: {}
}
}

/* 
* the function exits having setup the gSBox with the 
* input key material.
*/
}

/**
* Encrypt the given input starting at the given offset and place
* the result in the provided buffer starting at the given offset.
* The input will be an exact multiple of our blocksize.
*
* encryptBlock uses the pre-calculated gSBox[] and subKey[]
* arrays.
*/
private void encryptBlock(
ubyte[] src, 
int srcIndex,
ubyte[] dst,
int dstIndex)
{
int x0 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[INPUT_WHITEN];
int x1 = BytesTo32Bits(src, srcIndex + 4) ^ gSubKeys[INPUT_WHITEN + 1];
int x2 = BytesTo32Bits(src, srcIndex + 8) ^ gSubKeys[INPUT_WHITEN + 2];
int x3 = BytesTo32Bits(src, srcIndex + 12) ^ gSubKeys[INPUT_WHITEN + 3];

int k = ROUND_SUBKEYS;
int t0, t1;
for (int r = 0; r < ROUNDS; r +=2)
{
t0 = Fe32_0(x0);
t1 = Fe32_3(x1);
x2 ^= t0 + t1 + gSubKeys[k++];
x2 = cast(int)(cast(uint)x2 >>1) | x2 << 31;
x3 = (x3 << 1 | cast(int) (cast(uint)x3 >> 31)) ^ (t0 + 2*t1 + gSubKeys[k++]);

t0 = Fe32_0(x2);
t1 = Fe32_3(x3);
x0 ^= t0 + t1 + gSubKeys[k++];
x0 = cast(int) (cast(uint)x0 >>1) | x0 << 31;
x1 = (x1 << 1 | cast(int)(cast(uint)x1 >> 31)) ^ (t0 + 2*t1 + gSubKeys[k++]);
}

Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], dst, dstIndex);
Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], dst, dstIndex + 4);
Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], dst, dstIndex + 8);
Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], dst, dstIndex + 12);
}

/**
* Decrypt the given input starting at the given offset and place
* the result in the provided buffer starting at the given offset.
* The input will be an exact multiple of our blocksize.
*/
private void decryptBlock(ubyte[] src, int srcIndex, ubyte[] dst, int dstIndex)
{
int x2 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
int x3 = BytesTo32Bits(src, srcIndex+4) ^ gSubKeys[OUTPUT_WHITEN + 1];
int x0 = BytesTo32Bits(src, srcIndex+8) ^ gSubKeys[OUTPUT_WHITEN + 2];
int x1 = BytesTo32Bits(src, srcIndex+12) ^ gSubKeys[OUTPUT_WHITEN + 3];

int k = ROUND_SUBKEYS + 2 * ROUNDS -1 ;
int t0, t1;
for (int r = 0; r< ROUNDS ; r +=2)
{
t0 = Fe32_0(x2);
t1 = Fe32_3(x3);
x1 ^= t0 + 2*t1 + gSubKeys[k--];
x0 = (x0 << 1 | cast(int)(cast(uint) x0 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
x1 = cast(int) (cast(uint)x1 >>1) | x1 << 31;

t0 = Fe32_0(x0);
t1 = Fe32_3(x1);
x3 ^= t0 + 2*t1 + gSubKeys[k--];
x2 = (x2 << 1 | cast(int)(cast(uint)x2 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
x3 = cast(int)(cast(uint)x3 >>1) | x3 << 31;
}

Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], dst, dstIndex);
Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], dst, dstIndex + 4);
Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], dst, dstIndex + 8);
Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], dst, dstIndex + 12);
}

/* 
* TODO:  This can be optimised and made cleaner by combining
* the functionality in this function and applying it appropriately
* to the creation of the subkeys during key setup.
*/
private  int F32(int x, int[] k32)
{
int b0 = m_b0(x);
int b1 = m_b1(x);
int b2 = m_b2(x);
int b3 = m_b3(x);
int k0 = k32[0];
int k1 = k32[1];
int k2 = k32[2];
int k3 = k32[3];

int result = 0;
switch (k64Cnt & 3)
{
case 1:
result = gMDS0[(P[P_01][b0] & 0xff) ^ m_b0(k0)] ^
gMDS1[(P[P_11][b1] & 0xff) ^ m_b1(k0)] ^
gMDS2[(P[P_21][b2] & 0xff) ^ m_b2(k0)] ^
gMDS3[(P[P_31][b3] & 0xff) ^ m_b3(k0)];
break;
case 0: /* 256 bits of key */
b0 = (P[P_04][b0] & 0xff) ^ m_b0(k3);
b1 = (P[P_14][b1] & 0xff) ^ m_b1(k3);
b2 = (P[P_24][b2] & 0xff) ^ m_b2(k3);
b3 = (P[P_34][b3] & 0xff) ^ m_b3(k3);
goto case 3;
case 3: 
b0 = (P[P_03][b0] & 0xff) ^ m_b0(k2);
b1 = (P[P_13][b1] & 0xff) ^ m_b1(k2);
b2 = (P[P_23][b2] & 0xff) ^ m_b2(k2);
b3 = (P[P_33][b3] & 0xff) ^ m_b3(k2);
goto case 2;
case 2:
result = 
gMDS0[(P[P_01][(P[P_02][b0]&0xff)^m_b0(k1)]&0xff)^m_b0(k0)] ^ 
gMDS1[(P[P_11][(P[P_12][b1]&0xff)^m_b1(k1)]&0xff)^m_b1(k0)] ^
gMDS2[(P[P_21][(P[P_22][b2]&0xff)^m_b2(k1)]&0xff)^m_b2(k0)] ^
gMDS3[(P[P_31][(P[P_32][b3]&0xff)^m_b3(k1)]&0xff)^m_b3(k0)];
break;
default:{}
}
return result;
}

/**
* Use (12, 8) Reed-Solomon code over GF(256) to produce
* a key S-box 32-bit entity from 2 key material 32-bit
* entities.
*
*  param    k0 first 32-bit entity
*  param    k1 second 32-bit entity
*  return     Remainder polynomial generated using RS code
*/
private  int RS_MDS_Encode(int k0, int k1)
{
int r = k1;
for (int i = 0 ; i < 4 ; i++) // shift 1 ubyte at a time
{
r = RS_rem(r);
}
r ^= k0;
for (int i=0 ; i < 4 ; i++)
{
r = RS_rem(r);
}

return r;
}

/**
* Reed-Solomon code parameters: (12,8) reversible code:<p>
* <pre>
* g(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
* </pre>
* where a = primitive root of field generator 0x14D
*/
private  int RS_rem(int x)
{
int b = cast(int) ((cast(uint)x >> 24) & 0xff);
int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
int g3 = (cast(int)(cast(uint)b >> 1) ^ ((b & 0x01) != 0 ?
cast(int)(cast(uint)RS_GF_FDBK >> 1) : 0)) ^ g2 ;
return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
}

private  int LFSR1(int x)
{
return (x >> 1) ^ (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
}

private  int LFSR2(int x)
{
return (x >> 2) ^	(((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^ (((x & 0x01) != 0) ?
GF256_FDBK_4 : 0);
}

private  int Mx_X(int x)
{
return x ^ LFSR2(x);
} // 5B

private  int Mx_Y(int x)
{
return x ^ LFSR1(x) ^ LFSR2(x);
} // EF

private  int m_b0(int x)
{
return x & 0xff;
}

private  int m_b1(int x)
{
return cast(int)(cast(uint)x >> 8) & 0xff;
}

private  int m_b2(int x)
{
return cast(int)(cast(uint)x >> 16) & 0xff;
}

private  int m_b3(int x)
{
return cast(int)(cast(uint)x >> 24) & 0xff;
}

private  int Fe32_0(int x)
{
return gSBox[ 0x000 + 2*(x & 0xff) ] ^
gSBox[ 0x001 + 2*(cast(int)(cast(uint)x >> 8) & 0xff) ] ^
gSBox[ 0x200 + 2*(cast(int)(cast(uint)x >> 16) & 0xff) ] ^
gSBox[ 0x201 + 2*(cast(int)(cast(uint)x >> 24) & 0xff) ];
}

private  int Fe32_3(int x)
{
return gSBox[ 0x000 + 2*(cast(int)(cast(uint)x >> 24) & 0xff) ] ^
gSBox[ 0x001 + 2*(x & 0xff) ] ^
gSBox[ 0x200 + 2*(cast(int)(cast(uint)x >> 8) & 0xff) ] ^
gSBox[ 0x201 + 2*(cast(int)(cast(uint)x >> 16) & 0xff) ];
}

private  int BytesTo32Bits(ubyte[] b, int p)
{
return ((b[p] & 0xff) ) | 
((b[p+1] & 0xff) << 8) |
((b[p+2] & 0xff) << 16) |
((b[p+3] & 0xff) << 24);
}

private  void Bits32ToBytes(int inData,  ubyte[] b, int offset)
{
b[offset] = cast(ubyte)inData;
b[offset + 1] = cast(ubyte)(inData >> 8);
b[offset + 2] = cast(ubyte)(inData >> 16);
b[offset + 3] = cast(ubyte)(inData >> 24);
}
}


int main() {
ubyte[] bkey;
ubyte[] ins;
ubyte[] outs;
ubyte[] xx;
bkey.length = 8; ins.length = 17; outs.length = 32;   xx.length = 32;
bkey = cast(ubyte[])"xxxxxxxx";
ins = cast(ubyte[])"ttttttttttttttttz";

TwofishEngine cl;
cl = new TwofishEngine();
cl.init(true, bkey);
cl.processBlock(ins, outs);
printf(">|  %s\n", toStringz(cast(char[])outs));

TwofishEngine cl1;
cl1 = new TwofishEngine();
cl1.init(false, bkey);
cl1.processBlock(outs, xx);
printf(">|  %s\n", toStringz(cast(char[])xx));
printf(">|  %s\n", toStringz(cast(char[])xx));

return 1;
}
Mar 23 2006
next sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
I wonder if the Unittest for encryption and decryption libraries should, 
as test cases, contain a piece of nontrivial text (and possibly a tough 
binary file) that is originally [en/de]crypted with a _known_good_ 
implementation.

And a good explanation of how to acquire such a Known Good reference, so 
that anybody interested could try to repeat the test. (This is standard 
procedure in science, and cryptology is about the only thing where such 
(over ambitious) diligence makes sense in programming.)

How else would one know whether the code has only been debugged with its 
own counterpart, or with a universally accepted "base"? (Of course I'm 
talking corner cases, exceptional input, and the like, which usually 
slips past the original coder, IMHO, including myself.)

I think this goes for _any_ crypto SW submitted to the D community.

(This is not to say I have doubts on this particular implementation, 
this is a suggestion for a Best Practice.)
Mar 23 2006
parent Brad Anderson <brad dsource.dot.org> writes:
Georg Wrede wrote:
 I wonder if the Unittest for encryption and decryption libraries should,
 as test cases, contain a piece of nontrivial text (and possibly a tough
 binary file) that is originally [en/de]crypted with a _known_good_
 implementation.
 
 And a good explanation of how to acquire such a Known Good reference, so
 that anybody interested could try to repeat the test. (This is standard
 procedure in science, and cryptology is about the only thing where such
 (over ambitious) diligence makes sense in programming.)
 
 How else would one know whether the code has only been debugged with its
 own counterpart, or with a universally accepted "base"? (Of course I'm
 talking corner cases, exceptional input, and the like, which usually
 slips past the original coder, IMHO, including myself.)
 
 I think this goes for _any_ crypto SW submitted to the D community.
 
 (This is not to say I have doubts on this particular implementation,
 this is a suggestion for a Best Practice.)
Eric Young has some for Blowfish: Rough version: http://www.schneier.com/code/vectors.txt Ready for coding: http://www.schneier.com/code/vectors2.txt BA
Mar 23 2006
prev sibling parent reply r <r_member pathlink.com> writes:
i tried it, tried the vectors of the lib src. it works with the encryptions i
have from a c lib. 
i thought somebody can use it. i hope i did not offend somebody.

r
Mar 23 2006
parent MicroWizard <MicroWizard_member pathlink.com> writes:
Don't get bored. These guys are able to criticise everything ;-)

Really nice work.
It needs only some housekeeping as others have mentioned with other words.
(Best practice is to post only a link to the file or attach it.
Next time you'll do it better!)

Keep working and see you soon in this forum again!

Tamas Nagy

In article <dvv2bk$26h5$1 digitaldaemon.com>, r says...
i tried it, tried the vectors of the lib src. it works with the encryptions i
have from a c lib. 
i thought somebody can use it. i hope i did not offend somebody.

r
Mar 23 2006