?
import java.util.Arrays;
public class MyAES256
{
private final byte[] key = new byte[32];
private final byte[] enckey = new byte[32];
private final byte[] deckey = new byte[32];
private final byte[] sbox =
{
99, 124, 119, 123, -14, 107, 111, -59, 48, 1, 103, 43, -2, -41, -85, 118,
-54, -126, -55, 125, -6, 89, 71, -16, -83, -44, -94, -81, -100, -92, 114, -64,
-73, -3, -109, 38, 54, 63, -9, -52, 52, -91, -27, -15, 113, -40, 49, 21,
4, -57, 35, -61, 24, -106, 5, -102, 7, 18, -128, -30, -21, 39, -78, 117,
9, -125, 44, 26, 27, 110, 90, -96, 82, 59, -42, -77, 41, -29, 47, -124,
83, -47, 0, -19, 32, -4, -79, 91, 106, -53, -66, 57, 74, 76, 88, -49,
-48, -17, -86, -5, 67, 77, 51, -123, 69, -7, 2, 127, 80, 60, -97, -88,
81, -93, 64, -113, -110, -99, 56, -11, -68, -74, -38, 33, 16, -1, -13, -46,
-51, 12, 19, -20, 95, -105, 68, 23, -60, -89, 126, 61, 100, 93, 25, 115,
96, -127, 79, -36, 34, 42, -112, -120, 70, -18, -72, 20, -34, 94, 11, -37,
-32, 50, 58, 10, 73, 6, 36, 92, -62, -45, -84, 98, -111, -107, -28, 121,
-25, -56, 55, 109, -115, -43, 78, -87, 108, 86, -12, -22, 101, 122, -82, 8,
-70, 120, 37, 46, 28, -90, -76, -58, -24, -35, 116, 31, 75, -67, -117, -118,
112, 62, -75, 102, 72, 3, -10, 14, 97, 53, 87, -71, -122, -63, 29, -98,
-31, -8, -104, 17, 105, -39, -114, -108, -101, 30, -121, -23, -50, 85, 40, -33,
-116, -95, -119, 13, -65, -26, 66, 104, 65, -103, 45, 15, -80, 84, -69, 22
};
private final int xtime[] =
{
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94,
96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158,
160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190,
192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222,
224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254,
-229, -231, -225, -227, -237, -239, -233, -235, -245, -247, -241, -243, -253, -255, -249, -251,
-197, -199, -193, -195, -205, -207, -201, -203, -213, -215, -209, -211, -221, -223, -217, -219,
-165, -167, -161, -163, -173, -175, -169, -171, -181, -183, -177, -179, -189, -191, -185, -187,
-133, -135, -129, -131, -141, -143, -137, -139, -149, -151, -145, -147, -157, -159, -153, -155,
-101, -103, -97, -99, -109, -111, -105, -107, -117, -119, -113, -115, -125, -127, -121, -123,
-69, -71, -65, -67, -77, -79, -73, -75, -85, -87, -81, -83, -93, -95, -89, -91,
-37, -39, -33, -35, -45, -47, -41, -43, -53, -55, -49, -51, -61, -63, -57, -59,
-5, -7, -1, -3, -13, -15, -9, -11, -21, -23, -17, -19, -29, -31, -25, -27
};
private void addRoundKey(byte[] buf, byte[] key, int keyoffset)
{
int i = 16;
while (i-- != 0)
{
buf[i] ^= key[i + keyoffset];
}
}
private void addRoundKeyAndCopy(byte[] buf, byte[] key, byte[] cpk)
{
int i = 16;
while (i-- != 0)
{
buf[i] ^= (cpk[i] = key[i]);
cpk[16 + i] = key[16 + i];
}
}
private void shiftRows(byte[] buf)
{
byte i;
i = buf[1];
buf[1] = buf[5];
buf[5] = buf[9];
buf[9] = buf[13];
buf[13] = i;
i = buf[10];
buf[10] = buf[2];
buf[2] = i;
i = buf[3];
buf[3] = buf[15];
buf[15] = buf[11];
buf[11] = buf[7];
buf[7] = i;
i = buf[14];
buf[14] = buf[6];
buf[6] = i;
}
private void inverseShiftRows(byte[] buf)
{
byte i;
i = buf[1];
buf[1] = buf[13];
buf[13] = buf[9];
buf[9] = buf[5];
buf[5] = i;
i = buf[2];
buf[2] = buf[10];
buf[10] = i;
i = buf[3];
buf[3] = buf[7];
buf[7] = buf[11];
buf[11] = buf[15];
buf[15] = i;
i = buf[6];
buf[6] = buf[14];
buf[14] = i;
}
private void mixColumns(byte[] buf)
{
int i;
int a, b, c, d, e;
for (i = 0; i < 16; i += 4)
{
a = buf[i];
b = buf[i + 1];
c = buf[i + 2];
d = buf[i + 3];
e = a ^ b ^ c ^ d;
buf[i] ^= e ^ xtime[(a ^ b) & 0xff];
buf[i + 1] ^= e ^ xtime[(b ^ c) & 0xff];
buf[i + 2] ^= e ^ xtime[(c ^ d) & 0xff];
buf[i + 3] ^= e ^ xtime[(d ^ a) & 0xff];
}
}
private int expandEncryptionKey(byte[] k, int rc)
{
int i;
k[0] ^= sbox[k[29] & 0xff] ^ rc;
k[1] ^= sbox[k[30] & 0xff];
k[2] ^= sbox[k[31] & 0xff];
k[3] ^= sbox[k[28] & 0xff];
rc = rc << 1 ^ ((rc & 0xff) >>> 7 & 1) * 0x1b;
for (i = 4; i < 16; i += 4)
{
k[i] ^= k[i - 4];
k[i + 1] ^= k[i - 3];
k[i + 2] ^= k[i - 2];
k[i + 3] ^= k[i - 1];
}
k[16] ^= sbox[k[12] & 0xff];
k[17] ^= sbox[k[13] & 0xff];
k[18] ^= sbox[k[14] & 0xff];
k[19] ^= sbox[k[15] & 0xff];
for (i = 20; i < 32; i += 4)
{
k[i] ^= k[i - 4];
k[i + 1] ^= k[i - 3];
k[i + 2] ^= k[i - 2];
k[i + 3] ^= k[i - 1];
}
return rc;
}
/**
* Call this first
* @param k Key used for en- and decryption. Must be 32 byte long
*/
void init(byte[] k)
{
int rcon = 1;
int i;
for (i = 0; i < key.length; i++)
{
enckey[i] = deckey[i] = k[i];
}
for (i = 8; --i != 0; )
{
rcon = expandEncryptionKey(deckey, rcon);
}
}
/**
* Encrypts a chunk of 16 byte
* @param buf Points to the beginning of the block that should be encrypted
*/
void encrypt(byte[] buf)
{
int i;
int rcon = 1;
addRoundKeyAndCopy(buf, enckey, key);
for (i = 1; i < 14; ++i)
{
int i1 = 16;
while (i1-- != 0)
{
buf[i1] = sbox[buf[i1] & 0xff];
}
shiftRows(buf);
mixColumns(buf);
if ((i & 1) == 1)
{
addRoundKey(buf, key, 16);
}
else
{
rcon = expandEncryptionKey(key, rcon);
addRoundKey(buf, key, 0);
}
}
int i1 = 16;
while (i1-- != 0)
{
buf[i1] = sbox[buf[i1] & 0xff];
}
shiftRows(buf);
expandEncryptionKey(key, rcon);
addRoundKey(buf, key, 0);
}
/**
* Decrypts a chunk of 16 bytes
* Much more complex than encrypt due to inlining
* @param buf Points to the beginning of the block that should be decrypted
*/
void decrypt(byte[] buf)
{
int i = 16, i1;
int rcon = 0x80;
addRoundKeyAndCopy(buf, deckey, key);
inverseShiftRows(buf);
while (i-- != 0)
{
byte j = 0;
do
{
if (sbox[(int)j & 0xff] == buf[i])
{
buf[i] = j;
break;
}
}
while (++j != 0);
}
for (i = 14; (--i) != 0; )
{
if ((i & 1) == 1)
{
for (i1 = 28; i1 > 16; i1 -= 4)
{
key[i1] ^= key[i1 - 4];
key[i1 + 1] ^= key[i1 - 3];
key[i1 + 2] ^= key[i1 - 2];
key[i1 + 3] ^= key[i1 - 1];
}
key[16] ^= sbox[key[12] & 0xff];
key[17] ^= sbox[key[13] & 0xff];
key[18] ^= sbox[key[14] & 0xff];
key[19] ^= sbox[key[15] & 0xff];
for (i1 = 12; i1 > 0; i1 -= 4)
{
key[i1] ^= key[i1 - 4];
key[i1 + 1] ^= key[i1 - 3];
key[i1 + 2] ^= key[i1 - 2];
key[i1 + 3] ^= key[i1 - 1];
}
if ((rcon & 1) == 1)
{
rcon = (rcon & 0xff) >>> 1 ^ 0x8d;
}
else
{
rcon = (rcon & 0xff) >>> 1;
}
key[0] ^= sbox[key[29] & 0xff] ^ rcon;
key[1] ^= sbox[key[30] & 0xff];
key[2] ^= sbox[key[31] & 0xff];
key[3] ^= sbox[key[28] & 0xff];
addRoundKey(buf, key, 16);
}
else
{
addRoundKey(buf, key, 0);
}
for (i1 = 0; i1 < 16; i1 += 4)
{
int a = buf[i1];
int b = buf[i1 + 1];
int c = buf[i1 + 2];
int d = buf[i1 + 3];
int e = a ^ b ^ c ^ d;
int z = xtime[e & 0xff];
int x = e ^ xtime[xtime[(z ^ a ^ c) & 0xff] & 0xff];
int y = e ^ xtime[xtime[(z ^ b ^ d) & 0xff] & 0xff];
buf[i1] ^= x ^ xtime[(a ^ b) & 0xff];
buf[i1 + 1] ^= y ^ xtime[(b ^ c) & 0xff];
buf[i1 + 2] ^= x ^ xtime[(c ^ d) & 0xff];
buf[i1 + 3] ^= y ^ xtime[(d ^ a) & 0xff];
}
inverseShiftRows(buf);
i1 = 16;
while (i1-- != 0)
{
byte j = 0;
do
{
if (sbox[j & 0xff] == buf[i1])
{
buf[i1] = j;
break;
}
}
while (++j != 0);
}
}
addRoundKey(buf, key, 0);
}
/**
* A little test routine
* Encrypts 1...16 and then decrypts them
*/
static void test()
{
byte[] test1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
byte[] test2 = { -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16 };
System.out.println("before: " + Arrays.toString(test1));
System.out.println("before: " + Arrays.toString(test2));
MyAES256 aes = new MyAES256();
byte key[] = new byte[32];
for (int s = 0; s < key.length; s++)
{
key[s] = (byte)(Math.random() * 256);
}
System.out.println("key: " + Arrays.toString(key));
aes.init(key);
aes.encrypt(test1);
System.out.println("after: " + Arrays.toString(test1));
aes.encrypt(test2);
System.out.println("after: " + Arrays.toString(test2));
aes.decrypt(test1);
System.out.println("decrypted: " + Arrays.toString(test1));
aes.decrypt(test2);
System.out.println("decrypted: " + Arrays.toString(test2));
}
}
^^ viel spass