package com.zs.util;
import java.io.UnsupportedEncodingException;
public class AES{
private int Nb;// 以32位为单位的字长
private int Nk;// 以32位为单位的密钥长度
private int Nr;// 轮数
private byte[] key;// 密钥
private byte[][] Sbox;// S盒矩阵w
private byte[][] iSbox;// s盒逆矩阵
private int[][] w;// 密钥调度表
private int[][] State;// 状态矩阵
private byte[][] Rcon=// 轮常数表
{
{0x00, 0x00, 0x00, 0x00},
{0x01, 0x00, 0x00, 0x00},
{0x02, 0x00, 0x00, 0x00},
{0x04, 0x00, 0x00, 0x00},
{0x08, 0x00, 0x00, 0x00},
{0x10, 0x00, 0x00, 0x00},
{0x20, 0x00, 0x00, 0x00},
{0x40, 0x00, 0x00, 0x00},
{(byte) 0x80, 0x00, 0x00, 0x00},
{0x1b, 0x00, 0x00, 0x00},
{0x36, 0x00, 0x00, 0x00}
};
public int UByte (byte data){ //将data字节型数据转换为0~255 (0xFF 即BYTE)。
return data&0x0FF ;
}
public AES(int keySize, byte[] keyBytes, int Nb)
{
SetNbNkNr(keySize, Nb);
this.key = new byte[this.Nk * 4];
this.key = keyBytes;
BuildSbox();
BuildInvSbox();
KeyExpansion();
}
/**
* 设置Nb,Nk,Nr
*
* @param keysize
*/
private void SetNbNkNr(int keysize, int Nb)
{
this.Nb = Nb;
switch (keysize)
{
case 128:
this.Nk = 4;
this.Nr = 10;
break;
case 192:
this.Nk = 6;
this.Nr = 12;
break;
case 256:
this.Nk = 8;
this.Nr = 14;
break;
}
}
/**
* 生成S盒矩阵
*/
private void BuildSbox()
{
this.Sbox = new byte[][] {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/* 0 */{ 0x63, 0x7c, 0x77, 0x7b, (byte) 0xf2, 0x6b, 0x6f,
(byte) 0xc5, 0x30, 0x01, 0x67, 0x2b, (byte) 0xfe,
(byte) 0xd7, (byte) 0xab, 0x76 },
/* 1 */{ (byte) 0xca, (byte) 0x82, (byte) 0xc9, 0x7d,
(byte) 0xfa, 0x59, 0x47, (byte) 0xf0, (byte) 0xad,
(byte) 0xd4, (byte) 0xa2, (byte) 0xaf, (byte) 0x9c,
(byte) 0xa4, 0x72, (byte) 0xc0 },
/* 2 */{ (byte) 0xb7, (byte) 0xfd, (byte) 0x93, 0x26, 0x36,
0x3f, (byte) 0xf7, (byte) 0xcc, 0x34, (byte) 0xa5,
(byte) 0xe5, (byte) 0xf1, 0x71, (byte) 0xd8, 0x31, 0x15 },
/* 3 */{ 0x04, (byte) 0xc7, 0x23, (byte) 0xc3, 0x18,
(byte) 0x96, 0x05, (byte) 0x9a, 0x07, 0x12,
(byte) 0x80, (byte) 0xe2, (byte) 0xeb, 0x27,
(byte) 0xb2, 0x75 },
/* 4 */{ 0x09, (byte) 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a,
(byte) 0xa0, 0x52, 0x3b, (byte) 0xd6, (byte) 0xb3,
0x29, (byte) 0xe3, 0x2f, (byte) 0x84 },
/* 5 */{ 0x53, (byte) 0xd1, 0x00, (byte) 0xed, 0x20,
(byte) 0xfc, (byte) 0xb1, 0x5b, 0x6a, (byte) 0xcb,
(byte) 0xbe, 0x39, 0x4a, 0x4c, 0x58, (byte) 0xcf },
/* 6 */{ (byte) 0xd0, (byte) 0xef, (byte) 0xaa, (byte) 0xfb,
0x43, 0x4d, 0x33, (byte) 0x85, 0x45, (byte) 0xf9, 0x02,
0x7f, 0x50, 0x3c, (byte) 0x9f, (byte) 0xa8 },
/* 7 */{ 0x51, (byte) 0xa3, 0x40, (byte) 0x8f, (byte) 0x92,
(byte) 0x9d, 0x38, (byte) 0xf5, (byte) 0xbc,
(byte) 0xb6, (byte) 0xda, 0x21, 0x10, (byte) 0xff,
(byte) 0xf3, (byte) 0xd2 },
/* 8 */{ (byte) 0xcd, 0x0c, 0x13, (byte) 0xec, 0x5f,
(byte) 0x97, 0x44, 0x17, (byte) 0xc4, (byte) 0xa7,
0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 },
/* 9 */{ 0x60, (byte) 0x81, 0x4f, (byte) 0xdc, 0x22, 0x2a,
(byte) 0x90, (byte) 0x88, 0x46, (byte) 0xee,
(byte) 0xb8, 0x14, (byte) 0xde, 0x5e, 0x0b, (byte) 0xdb },
/* a */{ (byte) 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
(byte) 0xc2, (byte) 0xd3, (byte) 0xac, 0x62,
(byte) 0x91, (byte) 0x95, (byte) 0xe4, 0x79 },
/* b */{ (byte) 0xe7, (byte) 0xc8, 0x37, 0x6d, (byte) 0x8d,
(byte) 0xd5, 0x4e, (byte) 0xa9, 0x6c, 0x56,
(byte) 0xf4, (byte) 0xea, 0x65, 0x7a, (byte) 0xae, 0x08 },
/* c */{ (byte) 0xba, 0x78, 0x25, 0x2e, 0x1c, (byte) 0xa6,
(byte) 0xb4, (byte) 0xc6, (byte) 0xe8, (byte) 0xdd,
0x74, 0x1f, 0x4b, (byte) 0xbd, (byte) 0x8b, (byte) 0x8a },
/* d */{ 0x70, 0x3e, (byte) 0xb5, 0x66, 0x48, 0x03,
(byte) 0xf6, 0x0e, 0x61, 0x35, 0x57, (byte) 0xb9,
(byte) 0x86, (byte) 0xc1, 0x1d, (byte) 0x9e },
/* e */{ (byte) 0xe1, (byte) 0xf8, (byte) 0x98, 0x11, 0x69,
(byte) 0xd9, (byte) 0x8e, (byte) 0x94, (byte) 0x9b,
0x1e, (byte) 0x87, (byte) 0xe9, (byte) 0xce, 0x55,
0x28, (byte) 0xdf },
/* f */{ (byte) 0x8c, (byte) 0xa1, (byte) 0x89, 0x0d,
(byte) 0xbf, (byte) 0xe6, 0x42, 0x68, 0x41,
(byte) 0x99, 0x2d, 0x0f, (byte) 0xb0, 0x54,
(byte) 0xbb, 0x16 } };
}
/**
* 生成逆s盒矩阵
*/
private void BuildInvSbox()
{
// 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,
int x, y;
this.iSbox = new byte[16][16];
for (int i = 0; i < 16; i++)
{
// System.out.println("i="+i);
for (int j = 0; j < 16; j++)
{
x = (int) ((this.Sbox[i][j] >> 4) & 0x0f);
y = (int) (this.Sbox[i][j] & 0x0f);
// System.out.println("x="+x+" y="+y);
this.iSbox[x][y] = (byte) (16 * i + j);
}
}
}
/**
* 扩展密钥
*/
private void KeyExpansion()
{
this.w = new int[Nb * (Nr + 1)][4];
for (int row = 0; row < Nk; ++row)
{
this.w[row][0] = this.key[4 * row]&0x0ff;
this.w[row][1] = this.key[4 * row + 1]&0x0ff;
this.w[row][2] = this.key[4 * row + 2]&0x0ff;
this.w[row][3] = this.key[4 * row + 3]&0x0ff;
}
byte[] temp = new byte[Nb];
for (int row = Nk; row < Nb * (Nr + 1); ++row)
{
temp[0] = (byte)(this.w[row - 1][0]&0x0ff);
temp[1] = (byte)(this.w[row - 1][1]&0x0ff);
temp[2] = (byte)(this.w[row - 1][2]&0x0ff);
temp[3] = (byte)(this.w[row - 1][3]&0x0ff);
if (row % Nk == 0)
{
RotWord(temp);
SubWord(temp);
for (int i=0;i<4;i++)
temp[i]=(byte)(temp[i]^Rcon[row / Nk][i]);
} else if (Nk > 6 && (row % Nk == 4))
{
SubWord(temp);
}
for (int i=0;i<4;i++)
this.w[row][i]=(this.w[row-Nk][i]) ^ (temp[i]&0x0ff)&0x0ff;
}
}
/**
* SubWord方法
*
* @param subWord
* @return
*/
private void RotWord(byte[] wd)
{
byte[] temp=new byte[4];
temp[0] = wd[1];
temp[1] = wd[2];
temp[2] = wd[3];
temp[3] = wd[0];
System.arraycopy(temp,0, wd,0,wd.length);
}
private void SubWord(byte[] wd)
{
byte[] temp=new byte[4] ;
temp[3]=this.Sbox[UByte(wd[3])/16][UByte(wd[3])& 0x0f];
temp[2]=this.Sbox[UByte(wd[2])/16][UByte(wd[2])& 0x0f];
temp[1]=this.Sbox[UByte(wd[1])/16][UByte(wd[1])& 0x0f];
temp[0]=this.Sbox[UByte