mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-23 20:44:39 +08:00
2790 lines
47 KiB
Java
2790 lines
47 KiB
Java
package com.thealgorithms.ciphers;
|
|
|
|
import java.math.BigInteger;
|
|
import java.util.Scanner;
|
|
|
|
/**
|
|
* This class is build to demonstrate the application of the AES-algorithm on a
|
|
* single 128-Bit block of data.
|
|
*/
|
|
public class AES {
|
|
|
|
/**
|
|
* Precalculated values for x to the power of 2 in Rijndaels galois field.
|
|
* Used as 'RCON' during the key expansion.
|
|
*/
|
|
private static final int[] RCON = {
|
|
0x8d,
|
|
0x01,
|
|
0x02,
|
|
0x04,
|
|
0x08,
|
|
0x10,
|
|
0x20,
|
|
0x40,
|
|
0x80,
|
|
0x1b,
|
|
0x36,
|
|
0x6c,
|
|
0xd8,
|
|
0xab,
|
|
0x4d,
|
|
0x9a,
|
|
0x2f,
|
|
0x5e,
|
|
0xbc,
|
|
0x63,
|
|
0xc6,
|
|
0x97,
|
|
0x35,
|
|
0x6a,
|
|
0xd4,
|
|
0xb3,
|
|
0x7d,
|
|
0xfa,
|
|
0xef,
|
|
0xc5,
|
|
0x91,
|
|
0x39,
|
|
0x72,
|
|
0xe4,
|
|
0xd3,
|
|
0xbd,
|
|
0x61,
|
|
0xc2,
|
|
0x9f,
|
|
0x25,
|
|
0x4a,
|
|
0x94,
|
|
0x33,
|
|
0x66,
|
|
0xcc,
|
|
0x83,
|
|
0x1d,
|
|
0x3a,
|
|
0x74,
|
|
0xe8,
|
|
0xcb,
|
|
0x8d,
|
|
0x01,
|
|
0x02,
|
|
0x04,
|
|
0x08,
|
|
0x10,
|
|
0x20,
|
|
0x40,
|
|
0x80,
|
|
0x1b,
|
|
0x36,
|
|
0x6c,
|
|
0xd8,
|
|
0xab,
|
|
0x4d,
|
|
0x9a,
|
|
0x2f,
|
|
0x5e,
|
|
0xbc,
|
|
0x63,
|
|
0xc6,
|
|
0x97,
|
|
0x35,
|
|
0x6a,
|
|
0xd4,
|
|
0xb3,
|
|
0x7d,
|
|
0xfa,
|
|
0xef,
|
|
0xc5,
|
|
0x91,
|
|
0x39,
|
|
0x72,
|
|
0xe4,
|
|
0xd3,
|
|
0xbd,
|
|
0x61,
|
|
0xc2,
|
|
0x9f,
|
|
0x25,
|
|
0x4a,
|
|
0x94,
|
|
0x33,
|
|
0x66,
|
|
0xcc,
|
|
0x83,
|
|
0x1d,
|
|
0x3a,
|
|
0x74,
|
|
0xe8,
|
|
0xcb,
|
|
0x8d,
|
|
0x01,
|
|
0x02,
|
|
0x04,
|
|
0x08,
|
|
0x10,
|
|
0x20,
|
|
0x40,
|
|
0x80,
|
|
0x1b,
|
|
0x36,
|
|
0x6c,
|
|
0xd8,
|
|
0xab,
|
|
0x4d,
|
|
0x9a,
|
|
0x2f,
|
|
0x5e,
|
|
0xbc,
|
|
0x63,
|
|
0xc6,
|
|
0x97,
|
|
0x35,
|
|
0x6a,
|
|
0xd4,
|
|
0xb3,
|
|
0x7d,
|
|
0xfa,
|
|
0xef,
|
|
0xc5,
|
|
0x91,
|
|
0x39,
|
|
0x72,
|
|
0xe4,
|
|
0xd3,
|
|
0xbd,
|
|
0x61,
|
|
0xc2,
|
|
0x9f,
|
|
0x25,
|
|
0x4a,
|
|
0x94,
|
|
0x33,
|
|
0x66,
|
|
0xcc,
|
|
0x83,
|
|
0x1d,
|
|
0x3a,
|
|
0x74,
|
|
0xe8,
|
|
0xcb,
|
|
0x8d,
|
|
0x01,
|
|
0x02,
|
|
0x04,
|
|
0x08,
|
|
0x10,
|
|
0x20,
|
|
0x40,
|
|
0x80,
|
|
0x1b,
|
|
0x36,
|
|
0x6c,
|
|
0xd8,
|
|
0xab,
|
|
0x4d,
|
|
0x9a,
|
|
0x2f,
|
|
0x5e,
|
|
0xbc,
|
|
0x63,
|
|
0xc6,
|
|
0x97,
|
|
0x35,
|
|
0x6a,
|
|
0xd4,
|
|
0xb3,
|
|
0x7d,
|
|
0xfa,
|
|
0xef,
|
|
0xc5,
|
|
0x91,
|
|
0x39,
|
|
0x72,
|
|
0xe4,
|
|
0xd3,
|
|
0xbd,
|
|
0x61,
|
|
0xc2,
|
|
0x9f,
|
|
0x25,
|
|
0x4a,
|
|
0x94,
|
|
0x33,
|
|
0x66,
|
|
0xcc,
|
|
0x83,
|
|
0x1d,
|
|
0x3a,
|
|
0x74,
|
|
0xe8,
|
|
0xcb,
|
|
0x8d,
|
|
0x01,
|
|
0x02,
|
|
0x04,
|
|
0x08,
|
|
0x10,
|
|
0x20,
|
|
0x40,
|
|
0x80,
|
|
0x1b,
|
|
0x36,
|
|
0x6c,
|
|
0xd8,
|
|
0xab,
|
|
0x4d,
|
|
0x9a,
|
|
0x2f,
|
|
0x5e,
|
|
0xbc,
|
|
0x63,
|
|
0xc6,
|
|
0x97,
|
|
0x35,
|
|
0x6a,
|
|
0xd4,
|
|
0xb3,
|
|
0x7d,
|
|
0xfa,
|
|
0xef,
|
|
0xc5,
|
|
0x91,
|
|
0x39,
|
|
0x72,
|
|
0xe4,
|
|
0xd3,
|
|
0xbd,
|
|
0x61,
|
|
0xc2,
|
|
0x9f,
|
|
0x25,
|
|
0x4a,
|
|
0x94,
|
|
0x33,
|
|
0x66,
|
|
0xcc,
|
|
0x83,
|
|
0x1d,
|
|
0x3a,
|
|
0x74,
|
|
0xe8,
|
|
0xcb,
|
|
0x8d,
|
|
};
|
|
|
|
/**
|
|
* Rijndael S-box Substitution table used for encryption in the subBytes
|
|
* step, as well as the key expansion.
|
|
*/
|
|
private static final int[] SBOX = {
|
|
0x63,
|
|
0x7C,
|
|
0x77,
|
|
0x7B,
|
|
0xF2,
|
|
0x6B,
|
|
0x6F,
|
|
0xC5,
|
|
0x30,
|
|
0x01,
|
|
0x67,
|
|
0x2B,
|
|
0xFE,
|
|
0xD7,
|
|
0xAB,
|
|
0x76,
|
|
0xCA,
|
|
0x82,
|
|
0xC9,
|
|
0x7D,
|
|
0xFA,
|
|
0x59,
|
|
0x47,
|
|
0xF0,
|
|
0xAD,
|
|
0xD4,
|
|
0xA2,
|
|
0xAF,
|
|
0x9C,
|
|
0xA4,
|
|
0x72,
|
|
0xC0,
|
|
0xB7,
|
|
0xFD,
|
|
0x93,
|
|
0x26,
|
|
0x36,
|
|
0x3F,
|
|
0xF7,
|
|
0xCC,
|
|
0x34,
|
|
0xA5,
|
|
0xE5,
|
|
0xF1,
|
|
0x71,
|
|
0xD8,
|
|
0x31,
|
|
0x15,
|
|
0x04,
|
|
0xC7,
|
|
0x23,
|
|
0xC3,
|
|
0x18,
|
|
0x96,
|
|
0x05,
|
|
0x9A,
|
|
0x07,
|
|
0x12,
|
|
0x80,
|
|
0xE2,
|
|
0xEB,
|
|
0x27,
|
|
0xB2,
|
|
0x75,
|
|
0x09,
|
|
0x83,
|
|
0x2C,
|
|
0x1A,
|
|
0x1B,
|
|
0x6E,
|
|
0x5A,
|
|
0xA0,
|
|
0x52,
|
|
0x3B,
|
|
0xD6,
|
|
0xB3,
|
|
0x29,
|
|
0xE3,
|
|
0x2F,
|
|
0x84,
|
|
0x53,
|
|
0xD1,
|
|
0x00,
|
|
0xED,
|
|
0x20,
|
|
0xFC,
|
|
0xB1,
|
|
0x5B,
|
|
0x6A,
|
|
0xCB,
|
|
0xBE,
|
|
0x39,
|
|
0x4A,
|
|
0x4C,
|
|
0x58,
|
|
0xCF,
|
|
0xD0,
|
|
0xEF,
|
|
0xAA,
|
|
0xFB,
|
|
0x43,
|
|
0x4D,
|
|
0x33,
|
|
0x85,
|
|
0x45,
|
|
0xF9,
|
|
0x02,
|
|
0x7F,
|
|
0x50,
|
|
0x3C,
|
|
0x9F,
|
|
0xA8,
|
|
0x51,
|
|
0xA3,
|
|
0x40,
|
|
0x8F,
|
|
0x92,
|
|
0x9D,
|
|
0x38,
|
|
0xF5,
|
|
0xBC,
|
|
0xB6,
|
|
0xDA,
|
|
0x21,
|
|
0x10,
|
|
0xFF,
|
|
0xF3,
|
|
0xD2,
|
|
0xCD,
|
|
0x0C,
|
|
0x13,
|
|
0xEC,
|
|
0x5F,
|
|
0x97,
|
|
0x44,
|
|
0x17,
|
|
0xC4,
|
|
0xA7,
|
|
0x7E,
|
|
0x3D,
|
|
0x64,
|
|
0x5D,
|
|
0x19,
|
|
0x73,
|
|
0x60,
|
|
0x81,
|
|
0x4F,
|
|
0xDC,
|
|
0x22,
|
|
0x2A,
|
|
0x90,
|
|
0x88,
|
|
0x46,
|
|
0xEE,
|
|
0xB8,
|
|
0x14,
|
|
0xDE,
|
|
0x5E,
|
|
0x0B,
|
|
0xDB,
|
|
0xE0,
|
|
0x32,
|
|
0x3A,
|
|
0x0A,
|
|
0x49,
|
|
0x06,
|
|
0x24,
|
|
0x5C,
|
|
0xC2,
|
|
0xD3,
|
|
0xAC,
|
|
0x62,
|
|
0x91,
|
|
0x95,
|
|
0xE4,
|
|
0x79,
|
|
0xE7,
|
|
0xC8,
|
|
0x37,
|
|
0x6D,
|
|
0x8D,
|
|
0xD5,
|
|
0x4E,
|
|
0xA9,
|
|
0x6C,
|
|
0x56,
|
|
0xF4,
|
|
0xEA,
|
|
0x65,
|
|
0x7A,
|
|
0xAE,
|
|
0x08,
|
|
0xBA,
|
|
0x78,
|
|
0x25,
|
|
0x2E,
|
|
0x1C,
|
|
0xA6,
|
|
0xB4,
|
|
0xC6,
|
|
0xE8,
|
|
0xDD,
|
|
0x74,
|
|
0x1F,
|
|
0x4B,
|
|
0xBD,
|
|
0x8B,
|
|
0x8A,
|
|
0x70,
|
|
0x3E,
|
|
0xB5,
|
|
0x66,
|
|
0x48,
|
|
0x03,
|
|
0xF6,
|
|
0x0E,
|
|
0x61,
|
|
0x35,
|
|
0x57,
|
|
0xB9,
|
|
0x86,
|
|
0xC1,
|
|
0x1D,
|
|
0x9E,
|
|
0xE1,
|
|
0xF8,
|
|
0x98,
|
|
0x11,
|
|
0x69,
|
|
0xD9,
|
|
0x8E,
|
|
0x94,
|
|
0x9B,
|
|
0x1E,
|
|
0x87,
|
|
0xE9,
|
|
0xCE,
|
|
0x55,
|
|
0x28,
|
|
0xDF,
|
|
0x8C,
|
|
0xA1,
|
|
0x89,
|
|
0x0D,
|
|
0xBF,
|
|
0xE6,
|
|
0x42,
|
|
0x68,
|
|
0x41,
|
|
0x99,
|
|
0x2D,
|
|
0x0F,
|
|
0xB0,
|
|
0x54,
|
|
0xBB,
|
|
0x16,
|
|
};
|
|
|
|
/**
|
|
* Inverse Rijndael S-box Substitution table used for decryption in the
|
|
* subBytesDec step.
|
|
*/
|
|
private static final int[] INVERSE_SBOX = {
|
|
0x52,
|
|
0x09,
|
|
0x6A,
|
|
0xD5,
|
|
0x30,
|
|
0x36,
|
|
0xA5,
|
|
0x38,
|
|
0xBF,
|
|
0x40,
|
|
0xA3,
|
|
0x9E,
|
|
0x81,
|
|
0xF3,
|
|
0xD7,
|
|
0xFB,
|
|
0x7C,
|
|
0xE3,
|
|
0x39,
|
|
0x82,
|
|
0x9B,
|
|
0x2F,
|
|
0xFF,
|
|
0x87,
|
|
0x34,
|
|
0x8E,
|
|
0x43,
|
|
0x44,
|
|
0xC4,
|
|
0xDE,
|
|
0xE9,
|
|
0xCB,
|
|
0x54,
|
|
0x7B,
|
|
0x94,
|
|
0x32,
|
|
0xA6,
|
|
0xC2,
|
|
0x23,
|
|
0x3D,
|
|
0xEE,
|
|
0x4C,
|
|
0x95,
|
|
0x0B,
|
|
0x42,
|
|
0xFA,
|
|
0xC3,
|
|
0x4E,
|
|
0x08,
|
|
0x2E,
|
|
0xA1,
|
|
0x66,
|
|
0x28,
|
|
0xD9,
|
|
0x24,
|
|
0xB2,
|
|
0x76,
|
|
0x5B,
|
|
0xA2,
|
|
0x49,
|
|
0x6D,
|
|
0x8B,
|
|
0xD1,
|
|
0x25,
|
|
0x72,
|
|
0xF8,
|
|
0xF6,
|
|
0x64,
|
|
0x86,
|
|
0x68,
|
|
0x98,
|
|
0x16,
|
|
0xD4,
|
|
0xA4,
|
|
0x5C,
|
|
0xCC,
|
|
0x5D,
|
|
0x65,
|
|
0xB6,
|
|
0x92,
|
|
0x6C,
|
|
0x70,
|
|
0x48,
|
|
0x50,
|
|
0xFD,
|
|
0xED,
|
|
0xB9,
|
|
0xDA,
|
|
0x5E,
|
|
0x15,
|
|
0x46,
|
|
0x57,
|
|
0xA7,
|
|
0x8D,
|
|
0x9D,
|
|
0x84,
|
|
0x90,
|
|
0xD8,
|
|
0xAB,
|
|
0x00,
|
|
0x8C,
|
|
0xBC,
|
|
0xD3,
|
|
0x0A,
|
|
0xF7,
|
|
0xE4,
|
|
0x58,
|
|
0x05,
|
|
0xB8,
|
|
0xB3,
|
|
0x45,
|
|
0x06,
|
|
0xD0,
|
|
0x2C,
|
|
0x1E,
|
|
0x8F,
|
|
0xCA,
|
|
0x3F,
|
|
0x0F,
|
|
0x02,
|
|
0xC1,
|
|
0xAF,
|
|
0xBD,
|
|
0x03,
|
|
0x01,
|
|
0x13,
|
|
0x8A,
|
|
0x6B,
|
|
0x3A,
|
|
0x91,
|
|
0x11,
|
|
0x41,
|
|
0x4F,
|
|
0x67,
|
|
0xDC,
|
|
0xEA,
|
|
0x97,
|
|
0xF2,
|
|
0xCF,
|
|
0xCE,
|
|
0xF0,
|
|
0xB4,
|
|
0xE6,
|
|
0x73,
|
|
0x96,
|
|
0xAC,
|
|
0x74,
|
|
0x22,
|
|
0xE7,
|
|
0xAD,
|
|
0x35,
|
|
0x85,
|
|
0xE2,
|
|
0xF9,
|
|
0x37,
|
|
0xE8,
|
|
0x1C,
|
|
0x75,
|
|
0xDF,
|
|
0x6E,
|
|
0x47,
|
|
0xF1,
|
|
0x1A,
|
|
0x71,
|
|
0x1D,
|
|
0x29,
|
|
0xC5,
|
|
0x89,
|
|
0x6F,
|
|
0xB7,
|
|
0x62,
|
|
0x0E,
|
|
0xAA,
|
|
0x18,
|
|
0xBE,
|
|
0x1B,
|
|
0xFC,
|
|
0x56,
|
|
0x3E,
|
|
0x4B,
|
|
0xC6,
|
|
0xD2,
|
|
0x79,
|
|
0x20,
|
|
0x9A,
|
|
0xDB,
|
|
0xC0,
|
|
0xFE,
|
|
0x78,
|
|
0xCD,
|
|
0x5A,
|
|
0xF4,
|
|
0x1F,
|
|
0xDD,
|
|
0xA8,
|
|
0x33,
|
|
0x88,
|
|
0x07,
|
|
0xC7,
|
|
0x31,
|
|
0xB1,
|
|
0x12,
|
|
0x10,
|
|
0x59,
|
|
0x27,
|
|
0x80,
|
|
0xEC,
|
|
0x5F,
|
|
0x60,
|
|
0x51,
|
|
0x7F,
|
|
0xA9,
|
|
0x19,
|
|
0xB5,
|
|
0x4A,
|
|
0x0D,
|
|
0x2D,
|
|
0xE5,
|
|
0x7A,
|
|
0x9F,
|
|
0x93,
|
|
0xC9,
|
|
0x9C,
|
|
0xEF,
|
|
0xA0,
|
|
0xE0,
|
|
0x3B,
|
|
0x4D,
|
|
0xAE,
|
|
0x2A,
|
|
0xF5,
|
|
0xB0,
|
|
0xC8,
|
|
0xEB,
|
|
0xBB,
|
|
0x3C,
|
|
0x83,
|
|
0x53,
|
|
0x99,
|
|
0x61,
|
|
0x17,
|
|
0x2B,
|
|
0x04,
|
|
0x7E,
|
|
0xBA,
|
|
0x77,
|
|
0xD6,
|
|
0x26,
|
|
0xE1,
|
|
0x69,
|
|
0x14,
|
|
0x63,
|
|
0x55,
|
|
0x21,
|
|
0x0C,
|
|
0x7D,
|
|
};
|
|
|
|
/**
|
|
* Precalculated lookup table for galois field multiplication by 2 used in
|
|
* the MixColums step during encryption.
|
|
*/
|
|
private static final int[] MULT2 = {
|
|
0x00,
|
|
0x02,
|
|
0x04,
|
|
0x06,
|
|
0x08,
|
|
0x0a,
|
|
0x0c,
|
|
0x0e,
|
|
0x10,
|
|
0x12,
|
|
0x14,
|
|
0x16,
|
|
0x18,
|
|
0x1a,
|
|
0x1c,
|
|
0x1e,
|
|
0x20,
|
|
0x22,
|
|
0x24,
|
|
0x26,
|
|
0x28,
|
|
0x2a,
|
|
0x2c,
|
|
0x2e,
|
|
0x30,
|
|
0x32,
|
|
0x34,
|
|
0x36,
|
|
0x38,
|
|
0x3a,
|
|
0x3c,
|
|
0x3e,
|
|
0x40,
|
|
0x42,
|
|
0x44,
|
|
0x46,
|
|
0x48,
|
|
0x4a,
|
|
0x4c,
|
|
0x4e,
|
|
0x50,
|
|
0x52,
|
|
0x54,
|
|
0x56,
|
|
0x58,
|
|
0x5a,
|
|
0x5c,
|
|
0x5e,
|
|
0x60,
|
|
0x62,
|
|
0x64,
|
|
0x66,
|
|
0x68,
|
|
0x6a,
|
|
0x6c,
|
|
0x6e,
|
|
0x70,
|
|
0x72,
|
|
0x74,
|
|
0x76,
|
|
0x78,
|
|
0x7a,
|
|
0x7c,
|
|
0x7e,
|
|
0x80,
|
|
0x82,
|
|
0x84,
|
|
0x86,
|
|
0x88,
|
|
0x8a,
|
|
0x8c,
|
|
0x8e,
|
|
0x90,
|
|
0x92,
|
|
0x94,
|
|
0x96,
|
|
0x98,
|
|
0x9a,
|
|
0x9c,
|
|
0x9e,
|
|
0xa0,
|
|
0xa2,
|
|
0xa4,
|
|
0xa6,
|
|
0xa8,
|
|
0xaa,
|
|
0xac,
|
|
0xae,
|
|
0xb0,
|
|
0xb2,
|
|
0xb4,
|
|
0xb6,
|
|
0xb8,
|
|
0xba,
|
|
0xbc,
|
|
0xbe,
|
|
0xc0,
|
|
0xc2,
|
|
0xc4,
|
|
0xc6,
|
|
0xc8,
|
|
0xca,
|
|
0xcc,
|
|
0xce,
|
|
0xd0,
|
|
0xd2,
|
|
0xd4,
|
|
0xd6,
|
|
0xd8,
|
|
0xda,
|
|
0xdc,
|
|
0xde,
|
|
0xe0,
|
|
0xe2,
|
|
0xe4,
|
|
0xe6,
|
|
0xe8,
|
|
0xea,
|
|
0xec,
|
|
0xee,
|
|
0xf0,
|
|
0xf2,
|
|
0xf4,
|
|
0xf6,
|
|
0xf8,
|
|
0xfa,
|
|
0xfc,
|
|
0xfe,
|
|
0x1b,
|
|
0x19,
|
|
0x1f,
|
|
0x1d,
|
|
0x13,
|
|
0x11,
|
|
0x17,
|
|
0x15,
|
|
0x0b,
|
|
0x09,
|
|
0x0f,
|
|
0x0d,
|
|
0x03,
|
|
0x01,
|
|
0x07,
|
|
0x05,
|
|
0x3b,
|
|
0x39,
|
|
0x3f,
|
|
0x3d,
|
|
0x33,
|
|
0x31,
|
|
0x37,
|
|
0x35,
|
|
0x2b,
|
|
0x29,
|
|
0x2f,
|
|
0x2d,
|
|
0x23,
|
|
0x21,
|
|
0x27,
|
|
0x25,
|
|
0x5b,
|
|
0x59,
|
|
0x5f,
|
|
0x5d,
|
|
0x53,
|
|
0x51,
|
|
0x57,
|
|
0x55,
|
|
0x4b,
|
|
0x49,
|
|
0x4f,
|
|
0x4d,
|
|
0x43,
|
|
0x41,
|
|
0x47,
|
|
0x45,
|
|
0x7b,
|
|
0x79,
|
|
0x7f,
|
|
0x7d,
|
|
0x73,
|
|
0x71,
|
|
0x77,
|
|
0x75,
|
|
0x6b,
|
|
0x69,
|
|
0x6f,
|
|
0x6d,
|
|
0x63,
|
|
0x61,
|
|
0x67,
|
|
0x65,
|
|
0x9b,
|
|
0x99,
|
|
0x9f,
|
|
0x9d,
|
|
0x93,
|
|
0x91,
|
|
0x97,
|
|
0x95,
|
|
0x8b,
|
|
0x89,
|
|
0x8f,
|
|
0x8d,
|
|
0x83,
|
|
0x81,
|
|
0x87,
|
|
0x85,
|
|
0xbb,
|
|
0xb9,
|
|
0xbf,
|
|
0xbd,
|
|
0xb3,
|
|
0xb1,
|
|
0xb7,
|
|
0xb5,
|
|
0xab,
|
|
0xa9,
|
|
0xaf,
|
|
0xad,
|
|
0xa3,
|
|
0xa1,
|
|
0xa7,
|
|
0xa5,
|
|
0xdb,
|
|
0xd9,
|
|
0xdf,
|
|
0xdd,
|
|
0xd3,
|
|
0xd1,
|
|
0xd7,
|
|
0xd5,
|
|
0xcb,
|
|
0xc9,
|
|
0xcf,
|
|
0xcd,
|
|
0xc3,
|
|
0xc1,
|
|
0xc7,
|
|
0xc5,
|
|
0xfb,
|
|
0xf9,
|
|
0xff,
|
|
0xfd,
|
|
0xf3,
|
|
0xf1,
|
|
0xf7,
|
|
0xf5,
|
|
0xeb,
|
|
0xe9,
|
|
0xef,
|
|
0xed,
|
|
0xe3,
|
|
0xe1,
|
|
0xe7,
|
|
0xe5,
|
|
};
|
|
|
|
/**
|
|
* Precalculated lookup table for galois field multiplication by 3 used in
|
|
* the MixColums step during encryption.
|
|
*/
|
|
private static final int[] MULT3 = {
|
|
0x00,
|
|
0x03,
|
|
0x06,
|
|
0x05,
|
|
0x0c,
|
|
0x0f,
|
|
0x0a,
|
|
0x09,
|
|
0x18,
|
|
0x1b,
|
|
0x1e,
|
|
0x1d,
|
|
0x14,
|
|
0x17,
|
|
0x12,
|
|
0x11,
|
|
0x30,
|
|
0x33,
|
|
0x36,
|
|
0x35,
|
|
0x3c,
|
|
0x3f,
|
|
0x3a,
|
|
0x39,
|
|
0x28,
|
|
0x2b,
|
|
0x2e,
|
|
0x2d,
|
|
0x24,
|
|
0x27,
|
|
0x22,
|
|
0x21,
|
|
0x60,
|
|
0x63,
|
|
0x66,
|
|
0x65,
|
|
0x6c,
|
|
0x6f,
|
|
0x6a,
|
|
0x69,
|
|
0x78,
|
|
0x7b,
|
|
0x7e,
|
|
0x7d,
|
|
0x74,
|
|
0x77,
|
|
0x72,
|
|
0x71,
|
|
0x50,
|
|
0x53,
|
|
0x56,
|
|
0x55,
|
|
0x5c,
|
|
0x5f,
|
|
0x5a,
|
|
0x59,
|
|
0x48,
|
|
0x4b,
|
|
0x4e,
|
|
0x4d,
|
|
0x44,
|
|
0x47,
|
|
0x42,
|
|
0x41,
|
|
0xc0,
|
|
0xc3,
|
|
0xc6,
|
|
0xc5,
|
|
0xcc,
|
|
0xcf,
|
|
0xca,
|
|
0xc9,
|
|
0xd8,
|
|
0xdb,
|
|
0xde,
|
|
0xdd,
|
|
0xd4,
|
|
0xd7,
|
|
0xd2,
|
|
0xd1,
|
|
0xf0,
|
|
0xf3,
|
|
0xf6,
|
|
0xf5,
|
|
0xfc,
|
|
0xff,
|
|
0xfa,
|
|
0xf9,
|
|
0xe8,
|
|
0xeb,
|
|
0xee,
|
|
0xed,
|
|
0xe4,
|
|
0xe7,
|
|
0xe2,
|
|
0xe1,
|
|
0xa0,
|
|
0xa3,
|
|
0xa6,
|
|
0xa5,
|
|
0xac,
|
|
0xaf,
|
|
0xaa,
|
|
0xa9,
|
|
0xb8,
|
|
0xbb,
|
|
0xbe,
|
|
0xbd,
|
|
0xb4,
|
|
0xb7,
|
|
0xb2,
|
|
0xb1,
|
|
0x90,
|
|
0x93,
|
|
0x96,
|
|
0x95,
|
|
0x9c,
|
|
0x9f,
|
|
0x9a,
|
|
0x99,
|
|
0x88,
|
|
0x8b,
|
|
0x8e,
|
|
0x8d,
|
|
0x84,
|
|
0x87,
|
|
0x82,
|
|
0x81,
|
|
0x9b,
|
|
0x98,
|
|
0x9d,
|
|
0x9e,
|
|
0x97,
|
|
0x94,
|
|
0x91,
|
|
0x92,
|
|
0x83,
|
|
0x80,
|
|
0x85,
|
|
0x86,
|
|
0x8f,
|
|
0x8c,
|
|
0x89,
|
|
0x8a,
|
|
0xab,
|
|
0xa8,
|
|
0xad,
|
|
0xae,
|
|
0xa7,
|
|
0xa4,
|
|
0xa1,
|
|
0xa2,
|
|
0xb3,
|
|
0xb0,
|
|
0xb5,
|
|
0xb6,
|
|
0xbf,
|
|
0xbc,
|
|
0xb9,
|
|
0xba,
|
|
0xfb,
|
|
0xf8,
|
|
0xfd,
|
|
0xfe,
|
|
0xf7,
|
|
0xf4,
|
|
0xf1,
|
|
0xf2,
|
|
0xe3,
|
|
0xe0,
|
|
0xe5,
|
|
0xe6,
|
|
0xef,
|
|
0xec,
|
|
0xe9,
|
|
0xea,
|
|
0xcb,
|
|
0xc8,
|
|
0xcd,
|
|
0xce,
|
|
0xc7,
|
|
0xc4,
|
|
0xc1,
|
|
0xc2,
|
|
0xd3,
|
|
0xd0,
|
|
0xd5,
|
|
0xd6,
|
|
0xdf,
|
|
0xdc,
|
|
0xd9,
|
|
0xda,
|
|
0x5b,
|
|
0x58,
|
|
0x5d,
|
|
0x5e,
|
|
0x57,
|
|
0x54,
|
|
0x51,
|
|
0x52,
|
|
0x43,
|
|
0x40,
|
|
0x45,
|
|
0x46,
|
|
0x4f,
|
|
0x4c,
|
|
0x49,
|
|
0x4a,
|
|
0x6b,
|
|
0x68,
|
|
0x6d,
|
|
0x6e,
|
|
0x67,
|
|
0x64,
|
|
0x61,
|
|
0x62,
|
|
0x73,
|
|
0x70,
|
|
0x75,
|
|
0x76,
|
|
0x7f,
|
|
0x7c,
|
|
0x79,
|
|
0x7a,
|
|
0x3b,
|
|
0x38,
|
|
0x3d,
|
|
0x3e,
|
|
0x37,
|
|
0x34,
|
|
0x31,
|
|
0x32,
|
|
0x23,
|
|
0x20,
|
|
0x25,
|
|
0x26,
|
|
0x2f,
|
|
0x2c,
|
|
0x29,
|
|
0x2a,
|
|
0x0b,
|
|
0x08,
|
|
0x0d,
|
|
0x0e,
|
|
0x07,
|
|
0x04,
|
|
0x01,
|
|
0x02,
|
|
0x13,
|
|
0x10,
|
|
0x15,
|
|
0x16,
|
|
0x1f,
|
|
0x1c,
|
|
0x19,
|
|
0x1a,
|
|
};
|
|
|
|
/**
|
|
* Precalculated lookup table for galois field multiplication by 9 used in
|
|
* the MixColums step during decryption.
|
|
*/
|
|
private static final int[] MULT9 = {
|
|
0x00,
|
|
0x09,
|
|
0x12,
|
|
0x1b,
|
|
0x24,
|
|
0x2d,
|
|
0x36,
|
|
0x3f,
|
|
0x48,
|
|
0x41,
|
|
0x5a,
|
|
0x53,
|
|
0x6c,
|
|
0x65,
|
|
0x7e,
|
|
0x77,
|
|
0x90,
|
|
0x99,
|
|
0x82,
|
|
0x8b,
|
|
0xb4,
|
|
0xbd,
|
|
0xa6,
|
|
0xaf,
|
|
0xd8,
|
|
0xd1,
|
|
0xca,
|
|
0xc3,
|
|
0xfc,
|
|
0xf5,
|
|
0xee,
|
|
0xe7,
|
|
0x3b,
|
|
0x32,
|
|
0x29,
|
|
0x20,
|
|
0x1f,
|
|
0x16,
|
|
0x0d,
|
|
0x04,
|
|
0x73,
|
|
0x7a,
|
|
0x61,
|
|
0x68,
|
|
0x57,
|
|
0x5e,
|
|
0x45,
|
|
0x4c,
|
|
0xab,
|
|
0xa2,
|
|
0xb9,
|
|
0xb0,
|
|
0x8f,
|
|
0x86,
|
|
0x9d,
|
|
0x94,
|
|
0xe3,
|
|
0xea,
|
|
0xf1,
|
|
0xf8,
|
|
0xc7,
|
|
0xce,
|
|
0xd5,
|
|
0xdc,
|
|
0x76,
|
|
0x7f,
|
|
0x64,
|
|
0x6d,
|
|
0x52,
|
|
0x5b,
|
|
0x40,
|
|
0x49,
|
|
0x3e,
|
|
0x37,
|
|
0x2c,
|
|
0x25,
|
|
0x1a,
|
|
0x13,
|
|
0x08,
|
|
0x01,
|
|
0xe6,
|
|
0xef,
|
|
0xf4,
|
|
0xfd,
|
|
0xc2,
|
|
0xcb,
|
|
0xd0,
|
|
0xd9,
|
|
0xae,
|
|
0xa7,
|
|
0xbc,
|
|
0xb5,
|
|
0x8a,
|
|
0x83,
|
|
0x98,
|
|
0x91,
|
|
0x4d,
|
|
0x44,
|
|
0x5f,
|
|
0x56,
|
|
0x69,
|
|
0x60,
|
|
0x7b,
|
|
0x72,
|
|
0x05,
|
|
0x0c,
|
|
0x17,
|
|
0x1e,
|
|
0x21,
|
|
0x28,
|
|
0x33,
|
|
0x3a,
|
|
0xdd,
|
|
0xd4,
|
|
0xcf,
|
|
0xc6,
|
|
0xf9,
|
|
0xf0,
|
|
0xeb,
|
|
0xe2,
|
|
0x95,
|
|
0x9c,
|
|
0x87,
|
|
0x8e,
|
|
0xb1,
|
|
0xb8,
|
|
0xa3,
|
|
0xaa,
|
|
0xec,
|
|
0xe5,
|
|
0xfe,
|
|
0xf7,
|
|
0xc8,
|
|
0xc1,
|
|
0xda,
|
|
0xd3,
|
|
0xa4,
|
|
0xad,
|
|
0xb6,
|
|
0xbf,
|
|
0x80,
|
|
0x89,
|
|
0x92,
|
|
0x9b,
|
|
0x7c,
|
|
0x75,
|
|
0x6e,
|
|
0x67,
|
|
0x58,
|
|
0x51,
|
|
0x4a,
|
|
0x43,
|
|
0x34,
|
|
0x3d,
|
|
0x26,
|
|
0x2f,
|
|
0x10,
|
|
0x19,
|
|
0x02,
|
|
0x0b,
|
|
0xd7,
|
|
0xde,
|
|
0xc5,
|
|
0xcc,
|
|
0xf3,
|
|
0xfa,
|
|
0xe1,
|
|
0xe8,
|
|
0x9f,
|
|
0x96,
|
|
0x8d,
|
|
0x84,
|
|
0xbb,
|
|
0xb2,
|
|
0xa9,
|
|
0xa0,
|
|
0x47,
|
|
0x4e,
|
|
0x55,
|
|
0x5c,
|
|
0x63,
|
|
0x6a,
|
|
0x71,
|
|
0x78,
|
|
0x0f,
|
|
0x06,
|
|
0x1d,
|
|
0x14,
|
|
0x2b,
|
|
0x22,
|
|
0x39,
|
|
0x30,
|
|
0x9a,
|
|
0x93,
|
|
0x88,
|
|
0x81,
|
|
0xbe,
|
|
0xb7,
|
|
0xac,
|
|
0xa5,
|
|
0xd2,
|
|
0xdb,
|
|
0xc0,
|
|
0xc9,
|
|
0xf6,
|
|
0xff,
|
|
0xe4,
|
|
0xed,
|
|
0x0a,
|
|
0x03,
|
|
0x18,
|
|
0x11,
|
|
0x2e,
|
|
0x27,
|
|
0x3c,
|
|
0x35,
|
|
0x42,
|
|
0x4b,
|
|
0x50,
|
|
0x59,
|
|
0x66,
|
|
0x6f,
|
|
0x74,
|
|
0x7d,
|
|
0xa1,
|
|
0xa8,
|
|
0xb3,
|
|
0xba,
|
|
0x85,
|
|
0x8c,
|
|
0x97,
|
|
0x9e,
|
|
0xe9,
|
|
0xe0,
|
|
0xfb,
|
|
0xf2,
|
|
0xcd,
|
|
0xc4,
|
|
0xdf,
|
|
0xd6,
|
|
0x31,
|
|
0x38,
|
|
0x23,
|
|
0x2a,
|
|
0x15,
|
|
0x1c,
|
|
0x07,
|
|
0x0e,
|
|
0x79,
|
|
0x70,
|
|
0x6b,
|
|
0x62,
|
|
0x5d,
|
|
0x54,
|
|
0x4f,
|
|
0x46,
|
|
};
|
|
|
|
/**
|
|
* Precalculated lookup table for galois field multiplication by 11 used in
|
|
* the MixColums step during decryption.
|
|
*/
|
|
private static final int[] MULT11 = {
|
|
0x00,
|
|
0x0b,
|
|
0x16,
|
|
0x1d,
|
|
0x2c,
|
|
0x27,
|
|
0x3a,
|
|
0x31,
|
|
0x58,
|
|
0x53,
|
|
0x4e,
|
|
0x45,
|
|
0x74,
|
|
0x7f,
|
|
0x62,
|
|
0x69,
|
|
0xb0,
|
|
0xbb,
|
|
0xa6,
|
|
0xad,
|
|
0x9c,
|
|
0x97,
|
|
0x8a,
|
|
0x81,
|
|
0xe8,
|
|
0xe3,
|
|
0xfe,
|
|
0xf5,
|
|
0xc4,
|
|
0xcf,
|
|
0xd2,
|
|
0xd9,
|
|
0x7b,
|
|
0x70,
|
|
0x6d,
|
|
0x66,
|
|
0x57,
|
|
0x5c,
|
|
0x41,
|
|
0x4a,
|
|
0x23,
|
|
0x28,
|
|
0x35,
|
|
0x3e,
|
|
0x0f,
|
|
0x04,
|
|
0x19,
|
|
0x12,
|
|
0xcb,
|
|
0xc0,
|
|
0xdd,
|
|
0xd6,
|
|
0xe7,
|
|
0xec,
|
|
0xf1,
|
|
0xfa,
|
|
0x93,
|
|
0x98,
|
|
0x85,
|
|
0x8e,
|
|
0xbf,
|
|
0xb4,
|
|
0xa9,
|
|
0xa2,
|
|
0xf6,
|
|
0xfd,
|
|
0xe0,
|
|
0xeb,
|
|
0xda,
|
|
0xd1,
|
|
0xcc,
|
|
0xc7,
|
|
0xae,
|
|
0xa5,
|
|
0xb8,
|
|
0xb3,
|
|
0x82,
|
|
0x89,
|
|
0x94,
|
|
0x9f,
|
|
0x46,
|
|
0x4d,
|
|
0x50,
|
|
0x5b,
|
|
0x6a,
|
|
0x61,
|
|
0x7c,
|
|
0x77,
|
|
0x1e,
|
|
0x15,
|
|
0x08,
|
|
0x03,
|
|
0x32,
|
|
0x39,
|
|
0x24,
|
|
0x2f,
|
|
0x8d,
|
|
0x86,
|
|
0x9b,
|
|
0x90,
|
|
0xa1,
|
|
0xaa,
|
|
0xb7,
|
|
0xbc,
|
|
0xd5,
|
|
0xde,
|
|
0xc3,
|
|
0xc8,
|
|
0xf9,
|
|
0xf2,
|
|
0xef,
|
|
0xe4,
|
|
0x3d,
|
|
0x36,
|
|
0x2b,
|
|
0x20,
|
|
0x11,
|
|
0x1a,
|
|
0x07,
|
|
0x0c,
|
|
0x65,
|
|
0x6e,
|
|
0x73,
|
|
0x78,
|
|
0x49,
|
|
0x42,
|
|
0x5f,
|
|
0x54,
|
|
0xf7,
|
|
0xfc,
|
|
0xe1,
|
|
0xea,
|
|
0xdb,
|
|
0xd0,
|
|
0xcd,
|
|
0xc6,
|
|
0xaf,
|
|
0xa4,
|
|
0xb9,
|
|
0xb2,
|
|
0x83,
|
|
0x88,
|
|
0x95,
|
|
0x9e,
|
|
0x47,
|
|
0x4c,
|
|
0x51,
|
|
0x5a,
|
|
0x6b,
|
|
0x60,
|
|
0x7d,
|
|
0x76,
|
|
0x1f,
|
|
0x14,
|
|
0x09,
|
|
0x02,
|
|
0x33,
|
|
0x38,
|
|
0x25,
|
|
0x2e,
|
|
0x8c,
|
|
0x87,
|
|
0x9a,
|
|
0x91,
|
|
0xa0,
|
|
0xab,
|
|
0xb6,
|
|
0xbd,
|
|
0xd4,
|
|
0xdf,
|
|
0xc2,
|
|
0xc9,
|
|
0xf8,
|
|
0xf3,
|
|
0xee,
|
|
0xe5,
|
|
0x3c,
|
|
0x37,
|
|
0x2a,
|
|
0x21,
|
|
0x10,
|
|
0x1b,
|
|
0x06,
|
|
0x0d,
|
|
0x64,
|
|
0x6f,
|
|
0x72,
|
|
0x79,
|
|
0x48,
|
|
0x43,
|
|
0x5e,
|
|
0x55,
|
|
0x01,
|
|
0x0a,
|
|
0x17,
|
|
0x1c,
|
|
0x2d,
|
|
0x26,
|
|
0x3b,
|
|
0x30,
|
|
0x59,
|
|
0x52,
|
|
0x4f,
|
|
0x44,
|
|
0x75,
|
|
0x7e,
|
|
0x63,
|
|
0x68,
|
|
0xb1,
|
|
0xba,
|
|
0xa7,
|
|
0xac,
|
|
0x9d,
|
|
0x96,
|
|
0x8b,
|
|
0x80,
|
|
0xe9,
|
|
0xe2,
|
|
0xff,
|
|
0xf4,
|
|
0xc5,
|
|
0xce,
|
|
0xd3,
|
|
0xd8,
|
|
0x7a,
|
|
0x71,
|
|
0x6c,
|
|
0x67,
|
|
0x56,
|
|
0x5d,
|
|
0x40,
|
|
0x4b,
|
|
0x22,
|
|
0x29,
|
|
0x34,
|
|
0x3f,
|
|
0x0e,
|
|
0x05,
|
|
0x18,
|
|
0x13,
|
|
0xca,
|
|
0xc1,
|
|
0xdc,
|
|
0xd7,
|
|
0xe6,
|
|
0xed,
|
|
0xf0,
|
|
0xfb,
|
|
0x92,
|
|
0x99,
|
|
0x84,
|
|
0x8f,
|
|
0xbe,
|
|
0xb5,
|
|
0xa8,
|
|
0xa3,
|
|
};
|
|
|
|
/**
|
|
* Precalculated lookup table for galois field multiplication by 13 used in
|
|
* the MixColums step during decryption.
|
|
*/
|
|
private static final int[] MULT13 = {
|
|
0x00,
|
|
0x0d,
|
|
0x1a,
|
|
0x17,
|
|
0x34,
|
|
0x39,
|
|
0x2e,
|
|
0x23,
|
|
0x68,
|
|
0x65,
|
|
0x72,
|
|
0x7f,
|
|
0x5c,
|
|
0x51,
|
|
0x46,
|
|
0x4b,
|
|
0xd0,
|
|
0xdd,
|
|
0xca,
|
|
0xc7,
|
|
0xe4,
|
|
0xe9,
|
|
0xfe,
|
|
0xf3,
|
|
0xb8,
|
|
0xb5,
|
|
0xa2,
|
|
0xaf,
|
|
0x8c,
|
|
0x81,
|
|
0x96,
|
|
0x9b,
|
|
0xbb,
|
|
0xb6,
|
|
0xa1,
|
|
0xac,
|
|
0x8f,
|
|
0x82,
|
|
0x95,
|
|
0x98,
|
|
0xd3,
|
|
0xde,
|
|
0xc9,
|
|
0xc4,
|
|
0xe7,
|
|
0xea,
|
|
0xfd,
|
|
0xf0,
|
|
0x6b,
|
|
0x66,
|
|
0x71,
|
|
0x7c,
|
|
0x5f,
|
|
0x52,
|
|
0x45,
|
|
0x48,
|
|
0x03,
|
|
0x0e,
|
|
0x19,
|
|
0x14,
|
|
0x37,
|
|
0x3a,
|
|
0x2d,
|
|
0x20,
|
|
0x6d,
|
|
0x60,
|
|
0x77,
|
|
0x7a,
|
|
0x59,
|
|
0x54,
|
|
0x43,
|
|
0x4e,
|
|
0x05,
|
|
0x08,
|
|
0x1f,
|
|
0x12,
|
|
0x31,
|
|
0x3c,
|
|
0x2b,
|
|
0x26,
|
|
0xbd,
|
|
0xb0,
|
|
0xa7,
|
|
0xaa,
|
|
0x89,
|
|
0x84,
|
|
0x93,
|
|
0x9e,
|
|
0xd5,
|
|
0xd8,
|
|
0xcf,
|
|
0xc2,
|
|
0xe1,
|
|
0xec,
|
|
0xfb,
|
|
0xf6,
|
|
0xd6,
|
|
0xdb,
|
|
0xcc,
|
|
0xc1,
|
|
0xe2,
|
|
0xef,
|
|
0xf8,
|
|
0xf5,
|
|
0xbe,
|
|
0xb3,
|
|
0xa4,
|
|
0xa9,
|
|
0x8a,
|
|
0x87,
|
|
0x90,
|
|
0x9d,
|
|
0x06,
|
|
0x0b,
|
|
0x1c,
|
|
0x11,
|
|
0x32,
|
|
0x3f,
|
|
0x28,
|
|
0x25,
|
|
0x6e,
|
|
0x63,
|
|
0x74,
|
|
0x79,
|
|
0x5a,
|
|
0x57,
|
|
0x40,
|
|
0x4d,
|
|
0xda,
|
|
0xd7,
|
|
0xc0,
|
|
0xcd,
|
|
0xee,
|
|
0xe3,
|
|
0xf4,
|
|
0xf9,
|
|
0xb2,
|
|
0xbf,
|
|
0xa8,
|
|
0xa5,
|
|
0x86,
|
|
0x8b,
|
|
0x9c,
|
|
0x91,
|
|
0x0a,
|
|
0x07,
|
|
0x10,
|
|
0x1d,
|
|
0x3e,
|
|
0x33,
|
|
0x24,
|
|
0x29,
|
|
0x62,
|
|
0x6f,
|
|
0x78,
|
|
0x75,
|
|
0x56,
|
|
0x5b,
|
|
0x4c,
|
|
0x41,
|
|
0x61,
|
|
0x6c,
|
|
0x7b,
|
|
0x76,
|
|
0x55,
|
|
0x58,
|
|
0x4f,
|
|
0x42,
|
|
0x09,
|
|
0x04,
|
|
0x13,
|
|
0x1e,
|
|
0x3d,
|
|
0x30,
|
|
0x27,
|
|
0x2a,
|
|
0xb1,
|
|
0xbc,
|
|
0xab,
|
|
0xa6,
|
|
0x85,
|
|
0x88,
|
|
0x9f,
|
|
0x92,
|
|
0xd9,
|
|
0xd4,
|
|
0xc3,
|
|
0xce,
|
|
0xed,
|
|
0xe0,
|
|
0xf7,
|
|
0xfa,
|
|
0xb7,
|
|
0xba,
|
|
0xad,
|
|
0xa0,
|
|
0x83,
|
|
0x8e,
|
|
0x99,
|
|
0x94,
|
|
0xdf,
|
|
0xd2,
|
|
0xc5,
|
|
0xc8,
|
|
0xeb,
|
|
0xe6,
|
|
0xf1,
|
|
0xfc,
|
|
0x67,
|
|
0x6a,
|
|
0x7d,
|
|
0x70,
|
|
0x53,
|
|
0x5e,
|
|
0x49,
|
|
0x44,
|
|
0x0f,
|
|
0x02,
|
|
0x15,
|
|
0x18,
|
|
0x3b,
|
|
0x36,
|
|
0x21,
|
|
0x2c,
|
|
0x0c,
|
|
0x01,
|
|
0x16,
|
|
0x1b,
|
|
0x38,
|
|
0x35,
|
|
0x22,
|
|
0x2f,
|
|
0x64,
|
|
0x69,
|
|
0x7e,
|
|
0x73,
|
|
0x50,
|
|
0x5d,
|
|
0x4a,
|
|
0x47,
|
|
0xdc,
|
|
0xd1,
|
|
0xc6,
|
|
0xcb,
|
|
0xe8,
|
|
0xe5,
|
|
0xf2,
|
|
0xff,
|
|
0xb4,
|
|
0xb9,
|
|
0xae,
|
|
0xa3,
|
|
0x80,
|
|
0x8d,
|
|
0x9a,
|
|
0x97,
|
|
};
|
|
|
|
/**
|
|
* Precalculated lookup table for galois field multiplication by 14 used in
|
|
* the MixColums step during decryption.
|
|
*/
|
|
private static final int[] MULT14 = {
|
|
0x00,
|
|
0x0e,
|
|
0x1c,
|
|
0x12,
|
|
0x38,
|
|
0x36,
|
|
0x24,
|
|
0x2a,
|
|
0x70,
|
|
0x7e,
|
|
0x6c,
|
|
0x62,
|
|
0x48,
|
|
0x46,
|
|
0x54,
|
|
0x5a,
|
|
0xe0,
|
|
0xee,
|
|
0xfc,
|
|
0xf2,
|
|
0xd8,
|
|
0xd6,
|
|
0xc4,
|
|
0xca,
|
|
0x90,
|
|
0x9e,
|
|
0x8c,
|
|
0x82,
|
|
0xa8,
|
|
0xa6,
|
|
0xb4,
|
|
0xba,
|
|
0xdb,
|
|
0xd5,
|
|
0xc7,
|
|
0xc9,
|
|
0xe3,
|
|
0xed,
|
|
0xff,
|
|
0xf1,
|
|
0xab,
|
|
0xa5,
|
|
0xb7,
|
|
0xb9,
|
|
0x93,
|
|
0x9d,
|
|
0x8f,
|
|
0x81,
|
|
0x3b,
|
|
0x35,
|
|
0x27,
|
|
0x29,
|
|
0x03,
|
|
0x0d,
|
|
0x1f,
|
|
0x11,
|
|
0x4b,
|
|
0x45,
|
|
0x57,
|
|
0x59,
|
|
0x73,
|
|
0x7d,
|
|
0x6f,
|
|
0x61,
|
|
0xad,
|
|
0xa3,
|
|
0xb1,
|
|
0xbf,
|
|
0x95,
|
|
0x9b,
|
|
0x89,
|
|
0x87,
|
|
0xdd,
|
|
0xd3,
|
|
0xc1,
|
|
0xcf,
|
|
0xe5,
|
|
0xeb,
|
|
0xf9,
|
|
0xf7,
|
|
0x4d,
|
|
0x43,
|
|
0x51,
|
|
0x5f,
|
|
0x75,
|
|
0x7b,
|
|
0x69,
|
|
0x67,
|
|
0x3d,
|
|
0x33,
|
|
0x21,
|
|
0x2f,
|
|
0x05,
|
|
0x0b,
|
|
0x19,
|
|
0x17,
|
|
0x76,
|
|
0x78,
|
|
0x6a,
|
|
0x64,
|
|
0x4e,
|
|
0x40,
|
|
0x52,
|
|
0x5c,
|
|
0x06,
|
|
0x08,
|
|
0x1a,
|
|
0x14,
|
|
0x3e,
|
|
0x30,
|
|
0x22,
|
|
0x2c,
|
|
0x96,
|
|
0x98,
|
|
0x8a,
|
|
0x84,
|
|
0xae,
|
|
0xa0,
|
|
0xb2,
|
|
0xbc,
|
|
0xe6,
|
|
0xe8,
|
|
0xfa,
|
|
0xf4,
|
|
0xde,
|
|
0xd0,
|
|
0xc2,
|
|
0xcc,
|
|
0x41,
|
|
0x4f,
|
|
0x5d,
|
|
0x53,
|
|
0x79,
|
|
0x77,
|
|
0x65,
|
|
0x6b,
|
|
0x31,
|
|
0x3f,
|
|
0x2d,
|
|
0x23,
|
|
0x09,
|
|
0x07,
|
|
0x15,
|
|
0x1b,
|
|
0xa1,
|
|
0xaf,
|
|
0xbd,
|
|
0xb3,
|
|
0x99,
|
|
0x97,
|
|
0x85,
|
|
0x8b,
|
|
0xd1,
|
|
0xdf,
|
|
0xcd,
|
|
0xc3,
|
|
0xe9,
|
|
0xe7,
|
|
0xf5,
|
|
0xfb,
|
|
0x9a,
|
|
0x94,
|
|
0x86,
|
|
0x88,
|
|
0xa2,
|
|
0xac,
|
|
0xbe,
|
|
0xb0,
|
|
0xea,
|
|
0xe4,
|
|
0xf6,
|
|
0xf8,
|
|
0xd2,
|
|
0xdc,
|
|
0xce,
|
|
0xc0,
|
|
0x7a,
|
|
0x74,
|
|
0x66,
|
|
0x68,
|
|
0x42,
|
|
0x4c,
|
|
0x5e,
|
|
0x50,
|
|
0x0a,
|
|
0x04,
|
|
0x16,
|
|
0x18,
|
|
0x32,
|
|
0x3c,
|
|
0x2e,
|
|
0x20,
|
|
0xec,
|
|
0xe2,
|
|
0xf0,
|
|
0xfe,
|
|
0xd4,
|
|
0xda,
|
|
0xc8,
|
|
0xc6,
|
|
0x9c,
|
|
0x92,
|
|
0x80,
|
|
0x8e,
|
|
0xa4,
|
|
0xaa,
|
|
0xb8,
|
|
0xb6,
|
|
0x0c,
|
|
0x02,
|
|
0x10,
|
|
0x1e,
|
|
0x34,
|
|
0x3a,
|
|
0x28,
|
|
0x26,
|
|
0x7c,
|
|
0x72,
|
|
0x60,
|
|
0x6e,
|
|
0x44,
|
|
0x4a,
|
|
0x58,
|
|
0x56,
|
|
0x37,
|
|
0x39,
|
|
0x2b,
|
|
0x25,
|
|
0x0f,
|
|
0x01,
|
|
0x13,
|
|
0x1d,
|
|
0x47,
|
|
0x49,
|
|
0x5b,
|
|
0x55,
|
|
0x7f,
|
|
0x71,
|
|
0x63,
|
|
0x6d,
|
|
0xd7,
|
|
0xd9,
|
|
0xcb,
|
|
0xc5,
|
|
0xef,
|
|
0xe1,
|
|
0xf3,
|
|
0xfd,
|
|
0xa7,
|
|
0xa9,
|
|
0xbb,
|
|
0xb5,
|
|
0x9f,
|
|
0x91,
|
|
0x83,
|
|
0x8d,
|
|
};
|
|
|
|
/**
|
|
* Subroutine of the Rijndael key expansion.
|
|
*/
|
|
public static BigInteger scheduleCore(BigInteger t, int rconCounter) {
|
|
StringBuilder rBytes = new StringBuilder(t.toString(16));
|
|
|
|
// Add zero padding
|
|
while (rBytes.length() < 8) {
|
|
rBytes.insert(0, "0");
|
|
}
|
|
|
|
// rotate the first 16 bits to the back
|
|
String rotatingBytes = rBytes.substring(0, 2);
|
|
String fixedBytes = rBytes.substring(2);
|
|
|
|
rBytes = new StringBuilder(fixedBytes + rotatingBytes);
|
|
|
|
// apply S-Box to all 8-Bit Substrings
|
|
for (int i = 0; i < 4; i++) {
|
|
StringBuilder currentByteBits = new StringBuilder(rBytes.substring(i * 2, (i + 1) * 2));
|
|
|
|
int currentByte = Integer.parseInt(currentByteBits.toString(), 16);
|
|
currentByte = SBOX[currentByte];
|
|
|
|
// add the current RCON value to the first byte
|
|
if (i == 0) {
|
|
currentByte = currentByte ^ RCON[rconCounter];
|
|
}
|
|
|
|
currentByteBits = new StringBuilder(Integer.toHexString(currentByte));
|
|
|
|
// Add zero padding
|
|
while (currentByteBits.length() < 2) {
|
|
currentByteBits.insert(0, '0');
|
|
}
|
|
|
|
// replace bytes in original string
|
|
rBytes = new StringBuilder(
|
|
rBytes.substring(0, i * 2) + currentByteBits + rBytes.substring((i + 1) * 2));
|
|
}
|
|
|
|
// t = new BigInteger(rBytes, 16);
|
|
// return t;
|
|
return new BigInteger(rBytes.toString(), 16);
|
|
}
|
|
|
|
/**
|
|
* Returns an array of 10 + 1 round keys that are calculated by using
|
|
* Rijndael key schedule
|
|
*
|
|
* @return array of 10 + 1 round keys
|
|
*/
|
|
public static BigInteger[] keyExpansion(BigInteger initialKey) {
|
|
BigInteger[] roundKeys = {
|
|
initialKey,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
BigInteger.ZERO,
|
|
};
|
|
|
|
// initialize rcon iteration
|
|
int rconCounter = 1;
|
|
|
|
for (int i = 1; i < 11; i++) {
|
|
// get the previous 32 bits the key
|
|
BigInteger t = roundKeys[i - 1].remainder(new BigInteger("100000000", 16));
|
|
|
|
// split previous key into 8-bit segments
|
|
BigInteger[] prevKey = {
|
|
roundKeys[i - 1].remainder(new BigInteger("100000000", 16)),
|
|
roundKeys[i - 1]
|
|
.remainder(new BigInteger("10000000000000000", 16))
|
|
.divide(new BigInteger("100000000", 16)),
|
|
roundKeys[i - 1]
|
|
.remainder(new BigInteger("1000000000000000000000000", 16))
|
|
.divide(new BigInteger("10000000000000000", 16)),
|
|
roundKeys[i - 1].divide(new BigInteger("1000000000000000000000000", 16)),
|
|
};
|
|
|
|
// run schedule core
|
|
t = scheduleCore(t, rconCounter);
|
|
rconCounter += 1;
|
|
|
|
// Calculate partial round key
|
|
BigInteger t0 = t.xor(prevKey[3]);
|
|
BigInteger t1 = t0.xor(prevKey[2]);
|
|
BigInteger t2 = t1.xor(prevKey[1]);
|
|
BigInteger t3 = t2.xor(prevKey[0]);
|
|
|
|
// Join round key segments
|
|
t2 = t2.multiply(new BigInteger("100000000", 16));
|
|
t1 = t1.multiply(new BigInteger("10000000000000000", 16));
|
|
t0 = t0.multiply(new BigInteger("1000000000000000000000000", 16));
|
|
roundKeys[i] = t0.add(t1).add(t2).add(t3);
|
|
}
|
|
return roundKeys;
|
|
}
|
|
|
|
/**
|
|
* representation of the input 128-bit block as an array of 8-bit integers.
|
|
*
|
|
* @param block of 128-bit integers
|
|
* @return array of 8-bit integers
|
|
*/
|
|
public static int[] splitBlockIntoCells(BigInteger block) {
|
|
int[] cells = new int[16];
|
|
StringBuilder blockBits = new StringBuilder(block.toString(2));
|
|
|
|
// Append leading 0 for full "128-bit" string
|
|
while (blockBits.length() < 128) {
|
|
blockBits.insert(0, '0');
|
|
}
|
|
|
|
// split 128 to 8 bit cells
|
|
for (int i = 0; i < cells.length; i++) {
|
|
String cellBits = blockBits.substring(8 * i, 8 * (i + 1));
|
|
cells[i] = Integer.parseInt(cellBits, 2);
|
|
}
|
|
|
|
return cells;
|
|
}
|
|
|
|
/**
|
|
* Returns the 128-bit BigInteger representation of the input of an array of
|
|
* 8-bit integers.
|
|
*
|
|
* @param cells that we need to merge
|
|
* @return block of merged cells
|
|
*/
|
|
public static BigInteger mergeCellsIntoBlock(int[] cells) {
|
|
StringBuilder blockBits = new StringBuilder();
|
|
for (int i = 0; i < 16; i++) {
|
|
StringBuilder cellBits = new StringBuilder(Integer.toBinaryString(cells[i]));
|
|
|
|
// Append leading 0 for full "8-bit" strings
|
|
while (cellBits.length() < 8) {
|
|
cellBits.insert(0, '0');
|
|
}
|
|
|
|
blockBits.append(cellBits);
|
|
}
|
|
|
|
return new BigInteger(blockBits.toString(), 2);
|
|
}
|
|
|
|
/**
|
|
* @return ciphertext XOR key
|
|
*/
|
|
public static BigInteger addRoundKey(BigInteger ciphertext, BigInteger key) {
|
|
return ciphertext.xor(key);
|
|
}
|
|
|
|
/**
|
|
* substitutes 8-Bit long substrings of the input using the S-Box and
|
|
* returns the result.
|
|
*
|
|
* @return subtraction Output
|
|
*/
|
|
public static BigInteger subBytes(BigInteger ciphertext) {
|
|
int[] cells = splitBlockIntoCells(ciphertext);
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
cells[i] = SBOX[cells[i]];
|
|
}
|
|
|
|
return mergeCellsIntoBlock(cells);
|
|
}
|
|
|
|
/**
|
|
* substitutes 8-Bit long substrings of the input using the inverse S-Box
|
|
* for decryption and returns the result.
|
|
*
|
|
* @return subtraction Output
|
|
*/
|
|
public static BigInteger subBytesDec(BigInteger ciphertext) {
|
|
int[] cells = splitBlockIntoCells(ciphertext);
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
cells[i] = INVERSE_SBOX[cells[i]];
|
|
}
|
|
|
|
return mergeCellsIntoBlock(cells);
|
|
}
|
|
|
|
/**
|
|
* Cell permutation step. Shifts cells within the rows of the input and
|
|
* returns the result.
|
|
*/
|
|
public static BigInteger shiftRows(BigInteger ciphertext) {
|
|
int[] cells = splitBlockIntoCells(ciphertext);
|
|
int[] output = new int[16];
|
|
|
|
// do nothing in the first row
|
|
output[0] = cells[0];
|
|
output[4] = cells[4];
|
|
output[8] = cells[8];
|
|
output[12] = cells[12];
|
|
|
|
// shift the second row backwards by one cell
|
|
output[1] = cells[5];
|
|
output[5] = cells[9];
|
|
output[9] = cells[13];
|
|
output[13] = cells[1];
|
|
|
|
// shift the third row backwards by two cell
|
|
output[2] = cells[10];
|
|
output[6] = cells[14];
|
|
output[10] = cells[2];
|
|
output[14] = cells[6];
|
|
|
|
// shift the forth row backwards by tree cell
|
|
output[3] = cells[15];
|
|
output[7] = cells[3];
|
|
output[11] = cells[7];
|
|
output[15] = cells[11];
|
|
|
|
return mergeCellsIntoBlock(output);
|
|
}
|
|
|
|
/**
|
|
* Cell permutation step for decryption . Shifts cells within the rows of
|
|
* the input and returns the result.
|
|
*/
|
|
public static BigInteger shiftRowsDec(BigInteger ciphertext) {
|
|
int[] cells = splitBlockIntoCells(ciphertext);
|
|
int[] output = new int[16];
|
|
|
|
// do nothing in the first row
|
|
output[0] = cells[0];
|
|
output[4] = cells[4];
|
|
output[8] = cells[8];
|
|
output[12] = cells[12];
|
|
|
|
// shift the second row forwards by one cell
|
|
output[1] = cells[13];
|
|
output[5] = cells[1];
|
|
output[9] = cells[5];
|
|
output[13] = cells[9];
|
|
|
|
// shift the third row forwards by two cell
|
|
output[2] = cells[10];
|
|
output[6] = cells[14];
|
|
output[10] = cells[2];
|
|
output[14] = cells[6];
|
|
|
|
// shift the forth row forwards by tree cell
|
|
output[3] = cells[7];
|
|
output[7] = cells[11];
|
|
output[11] = cells[15];
|
|
output[15] = cells[3];
|
|
|
|
return mergeCellsIntoBlock(output);
|
|
}
|
|
|
|
/**
|
|
* Applies the Rijndael MixColumns to the input and returns the result.
|
|
*/
|
|
public static BigInteger mixColumns(BigInteger ciphertext) {
|
|
int[] cells = splitBlockIntoCells(ciphertext);
|
|
int[] outputCells = new int[16];
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
int[] row = {
|
|
cells[i * 4],
|
|
cells[i * 4 + 1],
|
|
cells[i * 4 + 2],
|
|
cells[i * 4 + 3],
|
|
};
|
|
|
|
outputCells[i * 4] = MULT2[row[0]] ^ MULT3[row[1]] ^ row[2] ^ row[3];
|
|
outputCells[i * 4 + 1] = row[0] ^ MULT2[row[1]] ^ MULT3[row[2]] ^ row[3];
|
|
outputCells[i * 4 + 2] = row[0] ^ row[1] ^ MULT2[row[2]] ^ MULT3[row[3]];
|
|
outputCells[i * 4 + 3] = MULT3[row[0]] ^ row[1] ^ row[2] ^ MULT2[row[3]];
|
|
}
|
|
return mergeCellsIntoBlock(outputCells);
|
|
}
|
|
|
|
/**
|
|
* Applies the inverse Rijndael MixColumns for decryption to the input and
|
|
* returns the result.
|
|
*/
|
|
public static BigInteger mixColumnsDec(BigInteger ciphertext) {
|
|
int[] cells = splitBlockIntoCells(ciphertext);
|
|
int[] outputCells = new int[16];
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
int[] row = {
|
|
cells[i * 4],
|
|
cells[i * 4 + 1],
|
|
cells[i * 4 + 2],
|
|
cells[i * 4 + 3],
|
|
};
|
|
|
|
outputCells[i * 4] = MULT14[row[0]] ^ MULT11[row[1]] ^ MULT13[row[2]] ^ MULT9[row[3]];
|
|
outputCells[i * 4 + 1]
|
|
= MULT9[row[0]] ^ MULT14[row[1]] ^ MULT11[row[2]] ^ MULT13[row[3]];
|
|
outputCells[i * 4 + 2]
|
|
= MULT13[row[0]] ^ MULT9[row[1]] ^ MULT14[row[2]] ^ MULT11[row[3]];
|
|
outputCells[i * 4 + 3]
|
|
= MULT11[row[0]] ^ MULT13[row[1]] ^ MULT9[row[2]] ^ MULT14[row[3]];
|
|
}
|
|
return mergeCellsIntoBlock(outputCells);
|
|
}
|
|
|
|
/**
|
|
* Encrypts the plaintext with the key and returns the result
|
|
*
|
|
* @param plainText which we want to encrypt
|
|
* @param key the key for encrypt
|
|
* @return EncryptedText
|
|
*/
|
|
public static BigInteger encrypt(BigInteger plainText, BigInteger key) {
|
|
BigInteger[] roundKeys = keyExpansion(key);
|
|
|
|
// Initial round
|
|
plainText = addRoundKey(plainText, roundKeys[0]);
|
|
|
|
// Main rounds
|
|
for (int i = 1; i < 10; i++) {
|
|
plainText = subBytes(plainText);
|
|
plainText = shiftRows(plainText);
|
|
plainText = mixColumns(plainText);
|
|
plainText = addRoundKey(plainText, roundKeys[i]);
|
|
}
|
|
|
|
// Final round
|
|
plainText = subBytes(plainText);
|
|
plainText = shiftRows(plainText);
|
|
plainText = addRoundKey(plainText, roundKeys[10]);
|
|
|
|
return plainText;
|
|
}
|
|
|
|
/**
|
|
* Decrypts the ciphertext with the key and returns the result
|
|
*
|
|
* @param cipherText The Encrypted text which we want to decrypt
|
|
* @return decryptedText
|
|
*/
|
|
public static BigInteger decrypt(BigInteger cipherText, BigInteger key) {
|
|
BigInteger[] roundKeys = keyExpansion(key);
|
|
|
|
// Invert final round
|
|
cipherText = addRoundKey(cipherText, roundKeys[10]);
|
|
cipherText = shiftRowsDec(cipherText);
|
|
cipherText = subBytesDec(cipherText);
|
|
|
|
// Invert main rounds
|
|
for (int i = 9; i > 0; i--) {
|
|
cipherText = addRoundKey(cipherText, roundKeys[i]);
|
|
cipherText = mixColumnsDec(cipherText);
|
|
cipherText = shiftRowsDec(cipherText);
|
|
cipherText = subBytesDec(cipherText);
|
|
}
|
|
|
|
// Invert initial round
|
|
cipherText = addRoundKey(cipherText, roundKeys[0]);
|
|
|
|
return cipherText;
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
try (Scanner input = new Scanner(System.in)) {
|
|
System.out.println("Enter (e) letter for encrpyt or (d) letter for decrypt :");
|
|
char choice = input.nextLine().charAt(0);
|
|
String in;
|
|
switch (choice) {
|
|
case 'E', 'e' -> {
|
|
System.out.println(
|
|
"Choose a plaintext block (128-Bit Integer in base 16):"
|
|
);
|
|
in = input.nextLine();
|
|
BigInteger plaintext = new BigInteger(in, 16);
|
|
System.out.println(
|
|
"Choose a Key (128-Bit Integer in base 16):"
|
|
);
|
|
in = input.nextLine();
|
|
BigInteger encryptionKey = new BigInteger(in, 16);
|
|
System.out.println(
|
|
"The encrypted message is: \n" +
|
|
encrypt(plaintext, encryptionKey).toString(16)
|
|
);
|
|
}
|
|
case 'D', 'd' -> {
|
|
System.out.println(
|
|
"Enter your ciphertext block (128-Bit Integer in base 16):"
|
|
);
|
|
in = input.nextLine();
|
|
BigInteger ciphertext = new BigInteger(in, 16);
|
|
System.out.println(
|
|
"Choose a Key (128-Bit Integer in base 16):"
|
|
);
|
|
in = input.nextLine();
|
|
BigInteger decryptionKey = new BigInteger(in, 16);
|
|
System.out.println(
|
|
"The deciphered message is:\n" +
|
|
decrypt(ciphertext, decryptionKey).toString(16)
|
|
);
|
|
}
|
|
default -> System.out.println("** End **");
|
|
}
|
|
}
|
|
}
|
|
}
|