Skip to content

Instantly share code, notes, and snippets.

@codelance
Created December 2, 2012 01:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codelance/4186512 to your computer and use it in GitHub Desktop.
Save codelance/4186512 to your computer and use it in GitHub Desktop.
AES
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class AES {
/**************************************************
* HELPER/UTILITY AES FUNCTIONS
*/
public String[] splitStringToArray(String input)
{
String[] array = new String[ input.length()/2];
for(int i = 0; i< array.length; i++ )
{
array[i] = input.substring(2*i, 2*i + 2);
}
return array;
}
public String mergeStringFromArray(String[] input)
{
String str = "";
for(int i=0; i< input.length; i++)
{
str += input[i];
}
return str;
}
private void PrintStateArray(int i )
{
System.out.print(" Round "+i+" Encryption: ");
for(int r = 0; r < 4; r++)
{
for(int c = 0; c < 4; c++)
{
System.out.print(state[ r ][ c ]);
}
}
System.out.print("\n");
}
//Number to String Byte
private String hString(int num )
{
String fmt = String.format("%02X",num);
if( fmt.length() > 2 )
{
fmt = fmt.substring(1);
}
return fmt;
}
/**************************************************
* CORE AES FUNCTIONS
*/
int Nk = 4;
int Nr = 10;
int Nb = 4;
String state[][];
String[] keyExpansion;
public AES()
{
state = new String[4][4];
}
private void AddRoundKey( int round )
{
for(int r = 0; r < 4; r++)
{
for(int c = 0; c < 4; c++)
{
int word = Integer.parseInt(keyExpansion[round*4+c].substring(2*r, 2*r +2),16);
int st = Integer.parseInt(state[r][c],16);
int res = st ^ word;
state[r][c] = String.format("%02X", res);
}
}
}
private void SubBytes()
{
for(int r = 0; r < 4 ; r++)
{
for(int c = 0; c < 4 ; c++)
{
state[r][c] = sBox[ Integer.parseInt( state[r][c], 16 ) ];
}
}
}
private void ShiftRows()
{
for(int r = 1; r < 4 ; r++)
{
String[] temp = new String[4];
for(int c = 0; c < 4 ; c++)
{
temp[c] = state[r][(c+r)%4];
}
System.arraycopy(temp, 0, state[r], 0, 4);
}
}
private void MixColumns()
{
for(int c = 0; c < 4; c++) {
int[] a = new int[4];
int[] b = new int[4];
int h;
for(int r = 0; r < 4; r++)
{
a[r] = Integer.parseInt(state[r][c], 16);
h = Integer.parseInt(state[r][c],16) & 0x80; /* hi bit */
b[r] = Integer.parseInt(state[r][c],16) << 1;
if( h == 0x80)
b[r] ^= 0x1B; /* Rijndael's Galois field */
}
state[0][c] = hString(b[0] ^ a[3] ^ a[2] ^ b[1] ^ a[1]);
state[1][c] = hString(b[1] ^ a[0] ^ a[3] ^ b[2] ^ a[2]);
state[2][c] = hString(b[2] ^ a[1] ^ a[0] ^ b[3] ^ a[3]);
state[3][c] = hString(b[3] ^ a[2] ^ a[1] ^ b[0] ^ a[0]);
}
}
private String SubWord(String input)
{
String[] arrayinput = splitStringToArray(input);
for(int i = 0; i < 4; i++ )
{
arrayinput[i] = sBox[Integer.parseInt(arrayinput[i], 16)];
}
return mergeStringFromArray(arrayinput);
}
private String RotWord(String input)
{
String[] arrayinput = splitStringToArray(input);
String temp = arrayinput[0];
for(int i = 0; i < 3; i++)
{
arrayinput[i] = arrayinput[i+1];
}
arrayinput[3] = temp;
return mergeStringFromArray(arrayinput);
}
private void KeyExpansion(String Key)
{
keyExpansion = new String[4 * Nb *(Nr + 1)]; //176 bytes
for(int i = 0; i < Nk ; i++ )
{
keyExpansion[i] = Key.substring(8*i, 8*i + 2) + Key.substring(8*i + 2, (8*i+2) + 2) +
Key.substring(8*i +4, (8*i+4) + 2) + Key.substring(8*i+6, (8*i+6) + 2);
System.out.println("i="+i+" | expandedKey[i] = Key[4i] + Key [4i+1] + Key[4i+2] + Key[4i+3] = "+keyExpansion[i]);
}
for(int i = Nk; i < Nb *(Nr + 1); i++)
{
String temp = keyExpansion[i - 1];
if( i % Nk == 0)
{
BigInteger RconValue = new BigInteger(Rcon[i/Nk],16);
//System.out.println("Rcon["+i/Nk+"] = "+ String.format("%0" + (4 << 1) + "X", RconValue));
String rotword = RotWord(temp);
String subword = SubWord(rotword);
temp = String.format("%0" + (4 << 1) + "X", new BigInteger( subword ,16).xor( RconValue ) );
System.out.print("i="+i+" | expandedKey[i] = SubWord(RotWord(w[i-1])) ^ Rcon[i/Nk] ");
}
else if ( Nk > 6 && i % Nk == 4)
{
temp = SubWord(temp);
System.out.print("i="+i+" | expandedKey[i] = SubWord(w[i-Nk]) ");
}
else
{
System.out.print("i="+i+" | expandedKey[i] = w[i-1] ");
}
keyExpansion[i] = String.format("%0" + (4 << 1) + "X", new BigInteger(keyExpansion[i-Nk], 16).xor( new BigInteger(temp,16)) );
System.out.print("^ w[i-Nk] = "+keyExpansion[i] +"\n");
}
}
public void encrypt( String PlainText, String Key)
{
for(int i = 0; i < 16; i++)
{
state[i % 4 ][ i / 4] = PlainText.substring(2 * i, 2*i + 2);
}
//Do Key Shedule
KeyExpansion(Key);
int i = 0;
System.out.println("***************************************");
System.out.println("Starting Encyrption: ");
System.out.println("***************************************");
AddRoundKey( 0 );
PrintStateArray( i );
for(i = 1; i < 16; i++)
{
SubBytes();
ShiftRows();
MixColumns();
AddRoundKey( 1 );
PrintStateArray( 1 );
}
}
/**
* @param args
*/
public static void main(String[] args) {
//String PT = "3243f6a8885a308d313198a2e0370734";
//String Key = "2B7E151628AED2A6ABF7158809CF4F3C";
String PT = "00112233445566778899aabbccddeeff";
String Key = "000102030405060708090a0b0c0d0e0f";
AES Impl = new AES();
Impl.encrypt(PT, Key);
}
private String[] Rcon ={"8D000000", "01000000", "02000000", "04000000" ,"08000000" , "10000000", "20000000", "40000000" ,"80000000" , "1B000000", "36000000"};
private String[] sBox =
{
"63", "7C", "77", "7B", "F2", "6B", "6F", "C5", "30", "01", "67", "2B", "FE", "D7", "AB", "76",
"CA", "82", "C9", "7D", "FA", "59", "47", "F0", "AD", "D4", "A2", "AF", "9C", "A4", "72", "C0",
"B7", "FD", "93", "26", "36", "3F", "F7", "CC", "34", "A5", "E5", "F1", "71", "D8", "31", "15",
"04", "C7", "23", "C3", "18", "96", "05", "9A", "07", "12", "80", "E2", "EB", "27", "B2", "75",
"09", "83", "2C", "1A", "1B", "6E", "5A", "A0", "52", "3B", "D6", "B3", "29", "E3", "2F", "84",
"53", "D1", "00", "ED", "20", "FC", "B1", "5B", "6A", "CB", "BE", "39", "4A", "4C", "58", "CF",
"D0", "EF", "AA", "FB", "43", "4D", "33", "85", "45", "F9", "02", "7F", "50", "3C", "9F", "A8",
"51", "A3", "40", "8F", "92", "9D", "38", "F5", "BC", "B6", "DA", "21", "10", "FF", "F3", "D2",
"CD", "0C", "13", "EC", "5F", "97", "44", "17", "C4", "A7", "7E", "3D", "64", "5D", "19", "73",
"60", "81", "4F", "DC", "22", "2A", "90", "88", "46", "EE", "B8", "14", "DE", "5E", "0B", "DB",
"E0", "32", "3A", "0A", "49", "06", "24", "5C", "C2", "D3", "AC", "62", "91", "95", "E4", "79",
"E7", "C8", "37", "6D", "8D", "D5", "4E", "A9", "6C", "56", "F4", "EA", "65", "7A", "AE", "08",
"BA", "78", "25", "2E", "1C", "A6", "B4", "C6", "E8", "DD", "74", "1F", "4B", "BD", "8B", "8A",
"70", "3E", "B5", "66", "48", "03", "F6", "0E", "61", "35", "57", "B9", "86", "C1", "1D", "9E",
"E1", "F8", "98", "11", "69", "D9", "8E", "94", "9B", "1E", "87", "E9", "CE", "55", "28", "DF",
"8C", "A1", "89", "0D", "BF", "E6", "42", "68", "41", "99", "2D", "0F", "B0", "54", "BB", "16"
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment