FileDocCategorySizeDatePackage
DESEngine.javaAPI DocAndroid 1.5 API17250Wed May 06 22:41:06 BST 2009org.bouncycastle.crypto.engines

DESEngine

public class DESEngine extends Object implements org.bouncycastle.crypto.BlockCipher
a class that provides a basic DES engine.

Fields Summary
protected static final int
BLOCK_SIZE
private int[]
workingKey
static short[]
Df_Key
what follows is mainly taken from "Applied Cryptography", by Bruce Schneier, however it also bears great resemblance to Richard Outerbridge's D3DES...
static short[]
bytebit
static int[]
bigbyte
static byte[]
pc1
static byte[]
totrot
static byte[]
pc2
static int[]
SP1
static int[]
SP2
static int[]
SP3
static int[]
SP4
static int[]
SP5
static int[]
SP6
static int[]
SP7
static int[]
SP8
Constructors Summary
public DESEngine()
standard constructor.


           
     
    
    
Methods Summary
protected voiddesFunc(int[] wKey, byte[] in, int inOff, byte[] out, int outOff)
the DES engine.

        int     work, right, left;

        left     = (in[inOff + 0] & 0xff) << 24;
        left    |= (in[inOff + 1] & 0xff) << 16;
        left    |= (in[inOff + 2] & 0xff) << 8;
        left    |= (in[inOff + 3] & 0xff);

        right     = (in[inOff + 4] & 0xff) << 24;
        right    |= (in[inOff + 5] & 0xff) << 16;
        right    |= (in[inOff + 6] & 0xff) << 8;
        right    |= (in[inOff + 7] & 0xff);

        work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
        right ^= work;
        left ^= (work << 4);
        work = ((left >>> 16) ^ right) & 0x0000ffff;
        right ^= work;
        left ^= (work << 16);
        work = ((right >>> 2) ^ left) & 0x33333333;
        left ^= work;
        right ^= (work << 2);
        work = ((right >>> 8) ^ left) & 0x00ff00ff;
        left ^= work;
        right ^= (work << 8);
        right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
        work = (left ^ right) & 0xaaaaaaaa;
        left ^= work;
        right ^= work;
        left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;

        for (int round = 0; round < 8; round++)
        {
            int     fval;

            work  = (right << 28) | (right >>> 4);
            work ^= wKey[round * 4 + 0];
            fval  = SP7[ work      & 0x3f];
            fval |= SP5[(work >>>  8) & 0x3f];
            fval |= SP3[(work >>> 16) & 0x3f];
            fval |= SP1[(work >>> 24) & 0x3f];
            work  = right ^ wKey[round * 4 + 1];
            fval |= SP8[ work      & 0x3f];
            fval |= SP6[(work >>>  8) & 0x3f];
            fval |= SP4[(work >>> 16) & 0x3f];
            fval |= SP2[(work >>> 24) & 0x3f];
            left ^= fval;
            work  = (left << 28) | (left >>> 4);
            work ^= wKey[round * 4 + 2];
            fval  = SP7[ work      & 0x3f];
            fval |= SP5[(work >>>  8) & 0x3f];
            fval |= SP3[(work >>> 16) & 0x3f];
            fval |= SP1[(work >>> 24) & 0x3f];
            work  = left ^ wKey[round * 4 + 3];
            fval |= SP8[ work      & 0x3f];
            fval |= SP6[(work >>>  8) & 0x3f];
            fval |= SP4[(work >>> 16) & 0x3f];
            fval |= SP2[(work >>> 24) & 0x3f];
            right ^= fval;
        }

        right = (right << 31) | (right >>> 1);
        work = (left ^ right) & 0xaaaaaaaa;
        left ^= work;
        right ^= work;
        left = (left << 31) | (left >>> 1);
        work = ((left >>> 8) ^ right) & 0x00ff00ff;
        right ^= work;
        left ^= (work << 8);
        work = ((left >>> 2) ^ right) & 0x33333333;
        right ^= work;
        left ^= (work << 2);
        work = ((right >>> 16) ^ left) & 0x0000ffff;
        left ^= work;
        right ^= (work << 16);
        work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
        left ^= work;
        right ^= (work << 4);

        out[outOff + 0] = (byte)((right >>> 24) & 0xff);
        out[outOff + 1] = (byte)((right >>> 16) & 0xff);
        out[outOff + 2] = (byte)((right >>>  8) & 0xff);
        out[outOff + 3] = (byte)(right         & 0xff);
        out[outOff + 4] = (byte)((left >>> 24) & 0xff);
        out[outOff + 5] = (byte)((left >>> 16) & 0xff);
        out[outOff + 6] = (byte)((left >>>  8) & 0xff);
        out[outOff + 7] = (byte)(left         & 0xff);
    
protected int[]generateWorkingKey(boolean encrypting, byte[] key)
generate an integer based working key based on our secret key and what we processing we are planning to do. Acknowledgements for this routine go to James Gillogly & Phil Karn. (whoever, and wherever they are!).


                                                     
      
         
          
    
        int[]       newKey = new int[32];
        boolean[]   pc1m = new boolean[56],
                    pcr = new boolean[56];

        for (int j = 0; j < 56; j++)
        {
            int    l = pc1[j];

            pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
        }

        for (int i = 0; i < 16; i++)
        {
            int    l, m, n;

            if (encrypting)
            {
                m = i << 1;
            }
            else
            {
                m = (15 - i) << 1;
            }

            n = m + 1;
            newKey[m] = newKey[n] = 0;

            for (int j = 0; j < 28; j++)
            {
                l = j + totrot[i];
                if (l < 28)
                {
                    pcr[j] = pc1m[l];
                }
                else
                {
                    pcr[j] = pc1m[l - 28];
                }
            }

            for (int j = 28; j < 56; j++)
            {
                l = j + totrot[i];
                if (l < 56)
                {
                    pcr[j] = pc1m[l];
                }
                else
                {
                    pcr[j] = pc1m[l - 28];
                }
            }

            for (int j = 0; j < 24; j++)
            {
                if (pcr[pc2[j]])
                {
                    newKey[m] |= bigbyte[j];
                }

                if (pcr[pc2[j + 24]])
                {
                    newKey[n] |= bigbyte[j];
                }
            }
        }

        //
        // store the processed key
        //
        for (int i = 0; i != 32; i += 2)
        {
            int    i1, i2;

            i1 = newKey[i];
            i2 = newKey[i + 1];

            newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10)
                                   | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6);

            newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16)
                                   | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
        }

        return newKey;
    
public java.lang.StringgetAlgorithmName()

        return "DES";
    
public intgetBlockSize()

        return BLOCK_SIZE;
    
public voidinit(boolean encrypting, org.bouncycastle.crypto.CipherParameters params)
initialise a DES cipher.

param
encrypting whether or not we are for encryption.
param
params the parameters required to set up the cipher.
exception
IllegalArgumentException if the params argument is inappropriate.

        if (params instanceof KeyParameter)
        {
            if (((KeyParameter)params).getKey().length > 8)
            {
                throw new IllegalArgumentException("DES key too long - should be 8 bytes");
            }
            
            workingKey = generateWorkingKey(encrypting,
                                  ((KeyParameter)params).getKey());

            return;
        }

        throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
    
public intprocessBlock(byte[] in, int inOff, byte[] out, int outOff)

        if (workingKey == null)
        {
            throw new IllegalStateException("DES engine not initialised");
        }

        if ((inOff + BLOCK_SIZE) > in.length)
        {
            throw new DataLengthException("input buffer too short");
        }

        if ((outOff + BLOCK_SIZE) > out.length)
        {
            throw new DataLengthException("output buffer too short");
        }

        desFunc(workingKey, in, inOff, out, outOff);

        return BLOCK_SIZE;
    
public voidreset()