AES_ECBpublic class AES_ECB extends BlockCipherBase This class is an implementation of AES cipher in ECB mode. |
Fields Summary |
---|
private static final byte[] | SBoxSubstitution values. | private static final byte[] | ISBoxInverse substitution table. | private int[] | SB0Precalculated table for matrix multiplication. | private int[] | SB1Precalculated table for matrix multiplication. | private int[] | SB2Precalculated table for matrix multiplication. | private int[] | SB3Precalculated table for matrix multiplication. | private static final byte[] | RconRound constants. | static final int | BLOCK_SIZEAES ciphers encrypt/decrypt in block size of 16 bytes. | private static final int | NbNumber of columns (32-bit words) comprising the state. | private int | NkNumber of 32-bit words comprising the key (4, 6, 8 for 128, 192
and 256 bits). | private int | NrNumber of rounds (10, 12, 14). | private int[] | WKey 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[] | stateInternal 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 void | KeyExpansion(byte[] data, int mode)Generates KeySchedule.
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 void | cipherBlock()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 void | decipherBlock()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 void | init(int mode, Key key, CryptoParameter params)Initializes this cipher with a key and a set of algorithm
parameters.
doInit(mode, "AES", key, false, null);
| void | initKey(byte[] data, int mode)Initializes key.
// 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 int | multiply(int a, int b)Calculates values for matrix 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 void | processBlock(byte[] out, int offset)Depending on the mode, either encrypts or decrypts data block.
holdCount = 0;
if (mode == Cipher.ENCRYPT_MODE) {
cipherBlock();
} else {
decipherBlock();
}
System.arraycopy(state, 0, out, offset, BLOCK_SIZE);
| protected void | setChainingModeAndPadding(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.
// Note: The chaining mode is implicitly set by using this class.
setPadding(padding);
|
|