FileDocCategorySizeDatePackage
AES_ECB.javaAPI DocphoneME MR2 API (J2ME)13875Wed May 02 18:00:00 BST 2007com.sun.midp.crypto

AES_ECB

public class AES_ECB extends BlockCipherBase
This class is an implementation of AES cipher in ECB mode.

Fields Summary
private static final byte[]
SBox
Substitution values.
private static final byte[]
ISBox
Inverse substitution table.
private int[]
SB0
Precalculated table for matrix multiplication.
private int[]
SB1
Precalculated table for matrix multiplication.
private int[]
SB2
Precalculated table for matrix multiplication.
private int[]
SB3
Precalculated table for matrix multiplication.
private static final byte[]
Rcon
Round constants.
static final int
BLOCK_SIZE
AES ciphers encrypt/decrypt in block size of 16 bytes.
private static final int
Nb
Number of columns (32-bit words) comprising the state.
private int
Nk
Number of 32-bit words comprising the key (4, 6, 8 for 128, 192 and 256 bits).
private int
Nr
Number of rounds (10, 12, 14).
private int[]
W
Key Schedule. Length depends on Block and Key length. Block length = 128 bits or 16 bytes. For 128 bit key W.length = Nb * (Nr + 1) == 4(10 + 1) = 44 Words = 44 * 4 bytes = 176 bytes
protected byte[]
state
Internal buffer.
Constructors Summary
public AES_ECB()
Constructor.


          
       
        super(BLOCK_SIZE);
        state = new byte[BLOCK_SIZE];
        SB0 = new int[256];
        SB1 = new int[256];
        SB2 = new int[256];
        SB3 = new int[256];
    
Methods Summary
private voidKeyExpansion(byte[] data, int mode)
Generates KeySchedule.

param
data key data
param
mode cipher mode


        byte[] W = new byte[Nb * (Nr + 1) << 2];

        int diff;
        System.arraycopy(data, 0, W, 0, (diff = Nk << 2));

        int round = 1;
        for (int i = Nk; i < Nb * (Nr + 1); i++) {

            int v = i << 2;

            if (i % Nk == 0) {
                int u = v - 1;
                for (int j = 0; j < 4; j++, v++) {
                    W[v] = (byte)((W[v - diff] ^
                            SBox[W[u - ((6 - j) & 3)] & 0xff]));
                }
                W[i << 2] ^= Rcon[round++];
            } else
            if (Nk > 6 && i % Nk == 4) {
                for (int j = 0; j < 4; j++, v++) {
                    W[v] = (byte) (W[v - diff] ^ SBox[W[v - 4] & 0xff]);
                }
            } else {
                for (int j = 0; j < 4; j++, v++) {
                    W[v] = (byte) (W[v - diff] ^ W[v - 4]);
                }
            }
        }

        int[] V = (this.W = new int[W.length >> 2]);
        for (int i = 0; i < V.length; i++) {
            V[i] = Util.getInt(W, i * 4);
        }

        if (mode == Cipher.DECRYPT_MODE) {
            for (int i = 4; i < Nr * 4; i++) {
                V[i] = SB0[SBox[W[i * 4] & 0xff] & 0xff] ^
                       SB1[SBox[W[i * 4 + 1] & 0xff] & 0xff] ^
                       SB2[SBox[W[i * 4 + 2] & 0xff] & 0xff] ^
                       SB3[SBox[W[i * 4 + 3] & 0xff] & 0xff];
            }
        }
    
protected voidcipherBlock()
Performs the encryption of data.


        int t0 = Util.getInt(holdData, 0) ^ W[0];
        int t1 = Util.getInt(holdData, 4) ^ W[1];
        int t2 = Util.getInt(holdData, 8) ^ W[2];
        int t3 = Util.getInt(holdData, 12) ^ W[3];

        int j = 4;
        for (int i = 1; i < Nr; i++) {
            int v0, v1, v2;
            t0 = SB0[(v0 = t0) >>> 24] ^ SB1[(v1 = t1) >>> 16 & 0xff] ^
                 SB2[(v2 = t2) >>> 8 & 0xff] ^ SB3[t3 & 0xff] ^ W[j];
            t1 = SB0[v1 >>> 24] ^ SB1[v2 >>> 16 & 0xff] ^
                 SB2[t3 >>> 8 & 0xff] ^ SB3[v0 & 0xff] ^ W[j + 1];
            t2 = SB0[v2 >>> 24] ^ SB1[t3 >>> 16 & 0xff] ^
                 SB2[v0 >>> 8 & 0xff] ^ SB3[v1 & 0xff] ^ W[j + 2];
            t3 = SB0[t3 >>> 24] ^ SB1[v0 >>> 16 & 0xff] ^
                 SB2[v1 >>> 8 & 0xff] ^ SB3[v2 & 0xff] ^ W[j + 3];
            j += 4;
        }

        int k;
        byte out[];
        (out = state)[0] = (byte)(SBox[t0 >>> 24] ^ (k = W[j]) >>> 24);
        out[1] = (byte)(SBox[t1 >>> 16 & 0xff] ^ k >>> 16);
        out[2] = (byte)(SBox[t2 >>> 8 & 0xff] ^ k >>> 8);
        out[3] = (byte)(SBox[t3 & 0xff] ^ k);
        out[4] = (byte)(SBox[t1 >>> 24] ^ (k = W[j + 1]) >>> 24);
        out[5] = (byte)(SBox[t2 >>> 16 & 0xff] ^ k >>> 16);
        out[6] = (byte)(SBox[t3 >>> 8 & 0xff] ^ k >>> 8);
        out[7] = (byte)(SBox[t0 & 0xff] ^ k);
        out[8] = (byte)(SBox[t2 >>> 24] ^ (k = W[j + 2]) >>> 24);
        out[9] = (byte)(SBox[t3 >>> 16 & 0xff] ^ k >>> 16);
        out[10] = (byte)(SBox[t0 >>> 8 & 0xff] ^ k >>> 8);
        out[11] = (byte)(SBox[t1 & 0xff] ^ k);
        out[12] = (byte)(SBox[t3 >>> 24] ^ (k = W[j + 3]) >>> 24);
        out[13] = (byte)(SBox[t0 >>> 16 & 0xff] ^ k >>> 16);
        out[14] = (byte)(SBox[t1 >>> 8 & 0xff] ^ k >>> 8);
        out[15] = (byte)(SBox[t2 & 0xff] ^ k);
    
protected voiddecipherBlock()
Performs the decryption of data.


        int j;
        int t0 = Util.getInt(holdData, 0) ^ W[j = Nr * 4];
        int t1 = Util.getInt(holdData, 4) ^ W[j + 1];
        int t2 = Util.getInt(holdData, 8) ^ W[j + 2];
        int t3 = Util.getInt(holdData, 12) ^ W[j + 3];

        for (int i = 1; i < Nr; i++) {
            int v0, v1, v2;
            t0 = SB0[(v0 = t0) >>> 24] ^ SB1[t3 >>> 16 & 0xff] ^
                 SB2[(v2 = t2) >>> 8 & 0xff] ^
                 SB3[(v1 = t1) & 0xff] ^ W[j = j - 4];
            t1 = SB0[v1 >>> 24] ^ SB1[v0 >>> 16 & 0xff] ^
                 SB2[t3 >>> 8 & 0xff] ^ SB3[v2 & 0xff] ^ W[j + 1];
            t2 = SB0[v2 >>> 24] ^ SB1[v1 >>> 16 & 0xff] ^
                 SB2[v0 >>> 8 & 0xff] ^ SB3[t3 & 0xff] ^ W[j + 2];
            t3 = SB0[t3 >>> 24] ^ SB1[v2 >>> 16 & 0xff] ^
                 SB2[v1 >>> 8 & 0xff] ^ SB3[v0 & 0xff] ^ W[j + 3];
        }

        int k;
        byte out[];
        (out = state)[0] = (byte)(ISBox[t0 >>> 24] ^ (k = W[0])>>> 24);
        out[1] = (byte)(ISBox[t3 >>> 16 & 0xff] ^ k >>> 16);
        out[2] = (byte)(ISBox[t2 >>> 8 & 0xff] ^ k >>> 8);
        out[3] = (byte)(ISBox[t1 & 0xff] ^ k);
        out[4] = (byte)(ISBox[t1 >>> 24] ^ (k = W[1]) >>> 24);
        out[5] = (byte)(ISBox[t0 >>> 16 & 0xff] ^ k >>> 16);
        out[6] = (byte)(ISBox[t3 >>> 8 & 0xff] ^ k >>> 8);
        out[7] = (byte)(ISBox[t2 & 0xff] ^ k);
        out[8] = (byte)(ISBox[t2 >>> 24] ^ (k = W[2]) >>> 24);
        out[9] = (byte)(ISBox[t1 >>> 16 & 0xff] ^ k >>> 16);
        out[10] = (byte)(ISBox[t0 >>> 8 & 0xff] ^ k >>> 8);
        out[11] = (byte)(ISBox[t3 & 0xff] ^ k);
        out[12] = (byte)(ISBox[t3 >>> 24] ^ (k = W[3]) >>> 24);
        out[13] = (byte)(ISBox[t2 >>> 16 & 0xff] ^ k >>> 16);
        out[14] = (byte)(ISBox[t1 >>> 8 & 0xff] ^ k >>> 8);
        out[15] = (byte)(ISBox[t0 & 0xff] ^ k);
    
public voidinit(int mode, Key key, CryptoParameter params)
Initializes this cipher with a key and a set of algorithm parameters.

param
mode the operation mode of this cipher
param
key the encryption key
param
params the algorithm parameters
exception
java.security.InvalidKeyException if the given key is inappropriate for initializing this cipher
exception
java.security.InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate for this cipher


        doInit(mode, "AES", key, false, null);
    
voidinitKey(byte[] data, int mode)
Initializes key.

param
data key data
param
mode cipher mode
exception
InvalidKeyException if the given key is inappropriate for this cipher


        // Min key 128 bits, max key 256 bits
        if (data.length != 16 && data.length != 24 && data.length != 32) {
            throw new InvalidKeyException();
        }

        Nk = data.length >> 2;
        Nr = 6 + Nk;

        int row = 0x0e090d0b;
        byte[] box = ISBox;
        if (mode == Cipher.ENCRYPT_MODE) {
            row = 0x02010103;
            box = SBox;
        }

        if (multiply(row, box[0]) != SB0[0]) {
            for (int i = 0; i < 256; i++) {
                int j;
                SB0[i] = j = multiply(row, box[i]);
                SB1[i] = (j >>> 8) | (j << 24);
                SB2[i] = (j >>> 16) | (j << 16);
                SB3[i] = (j >>> 24) | (j << 8);
            }
        }

        KeyExpansion(data, mode);
    
private static intmultiply(int a, int b)
Calculates values for matrix multiplication.

param
a represents a matrix column (4 bytes).
param
b multiplier
return
result of multiplication.

        int result = 0;
        b &= 0xff;
        for (int i = 0; i < 4; i++) {
            result ^= ((a >> i) & 0x01010101) * b;
            b = b < 128 ? b << 1 : (b << 1) ^ 0x11b;
        }
        return result;
    
protected voidprocessBlock(byte[] out, int offset)
Depending on the mode, either encrypts or decrypts data block.

param
out will contain the result of encryption or decryption operation
param
offset is the offset in out


        holdCount = 0;

        if (mode == Cipher.ENCRYPT_MODE)  {
            cipherBlock();
        } else {
            decipherBlock();
        }

        System.arraycopy(state, 0, out, offset, BLOCK_SIZE);
    
protected voidsetChainingModeAndPadding(java.lang.String mode, java.lang.String padding)
Called by the factory method to set the mode and padding parameters. Need because Class.newInstance does not take args.

param
mode the mode parsed from the transformation parameter of getInstance and upper cased
param
padding the paddinge parsed from the transformation parameter of getInstance and upper cased

        // Note: The chaining mode is implicitly set by using this class.

        setPadding(padding);