Created
December 2, 2012 01:53
-
-
Save codelance/4186512 to your computer and use it in GitHub Desktop.
AES
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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