AES结构流程图如下
既然是来查代码的,各个步骤的具体步骤大家应该都知道,我就不细说了,放图在下面
明文/密文放入顺序:
S盒:
轮密钥生成:
字节旋转:每个字中的字节循环左移一个字节
字节代替:S盒代替
废话少说,直接上代码:
package AES;
import java.util.Arrays;
import java.util.Random;
public class AES {
private final static int[] rC = new int[]{0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000};//轮常数
private final static byte[] cx = new byte[]{0x02, 0x01, 0x01, 0x03};
private final static byte[] c_x = new byte[]{0x0e, 0x09, 0x0d, 0x0b};//列混合的c(x)与逆
private final static int irreduciblePolynomial = 0b100011011;//28域上的不可约多项式
private final static byte[][] sBox = new byte[][]{
{(byte) 0x63, (byte) 0x7c, (byte) 0x77, (byte) 0x7b, (byte) 0xf2, (byte) 0x6b, (byte) 0x6f, (byte) 0xc5, (byte) 0x30, (byte) 0x01, (byte) 0x67, (byte) 0x2b, (byte) 0xfe, (byte) 0xd7, (byte) 0xab, (byte) 0x76},
{(byte) 0xca, (byte) 0x82, (byte) 0xc9, (byte) 0x7d, (byte) 0xfa, (byte) 0x59, (byte) 0x47, (byte) 0xf0, (byte) 0xad, (byte) 0xd4, (byte) 0xa2, (byte) 0xaf, (byte) 0x9c, (byte) 0xa4, (byte) 0x72, (byte) 0xc0},
{(byte) 0xb7, (byte) 0xfd, (byte) 0x93, (byte) 0x26, (byte) 0x36, (byte) 0x3f, (byte) 0xf7, (byte) 0xcc, (byte) 0x34, (byte) 0xa5, (byte) 0xe5, (byte) 0xf1, (byte) 0x71, (byte) 0xd8, (byte) 0x31, (byte) 0x15},
{(byte) 0x04, (byte) 0xc7, (byte) 0x23, (byte) 0xc3, (byte) 0x18, (byte) 0x96, (byte) 0x05, (byte) 0x9a, (byte) 0x07, (byte) 0x12, (byte) 0x80, (byte) 0xe2, (byte) 0xeb, (byte) 0x27, (byte) 0xb2, (byte) 0x75},
{(byte) 0x09, (byte) 0x83, (byte) 0x2c, (byte) 0x1a, (byte) 0x1b, (byte) 0x6e, (byte) 0x5a, (byte) 0xa0, (byte) 0x52, (byte) 0x3b, (byte) 0xd6, (byte) 0xb3, (byte) 0x29, (byte) 0xe3, (byte) 0x2f, (byte) 0x84},
{(byte) 0x53, (byte) 0xd1, (byte) 0x00, (byte) 0xed, (byte) 0x20, (byte) 0xfc, (byte) 0xb1, (byte) 0x5b, (byte) 0x6a, (byte) 0xcb, (byte) 0xbe, (byte) 0x39, (byte) 0x4a, (byte) 0x4c, (byte) 0x58, (byte) 0xcf},
{(byte) 0xd0, (byte) 0xef, (byte) 0xaa, (byte) 0xfb, (byte) 0x43, (byte) 0x4d, (byte) 0x33, (byte) 0x85, (byte) 0x45, (byte) 0xf9, (byte) 0x02, (byte) 0x7f, (byte) 0x50, (byte) 0x3c, (byte) 0x9f, (byte) 0xa8},
{(byte) 0x51, (byte) 0xa3, (byte) 0x40, (byte) 0x8f, (byte) 0x92, (byte) 0x9d, (byte) 0x38, (byte) 0xf5, (byte) 0xbc, (byte) 0xb6, (byte) 0xda, (byte) 0x21, (byte) 0x10, (byte) 0xff, (byte) 0xf3, (byte) 0xd2},
{(byte) 0xcd, (byte) 0x0c, (byte) 0x13, (byte) 0xec, (byte) 0x5f, (byte) 0x97, (byte) 0x44, (byte) 0x17, (byte) 0xc4, (byte) 0xa7, (byte) 0x7e, (byte) 0x3d, (byte) 0x64, (byte) 0x5d, (byte) 0x19, (byte) 0x73},
{(byte) 0x60, (byte) 0x81, (byte) 0x4f, (byte) 0xdc, (byte) 0x22, (byte) 0x2a, (byte) 0x90, (byte) 0x88, (byte) 0x46, (byte) 0xee, (byte) 0xb8, (byte) 0x14, (byte) 0xde, (byte) 0x5e, (byte) 0x0b, (byte) 0xdb},
{(byte) 0xe0, (byte) 0x32, (byte) 0x3a, (byte) 0x0a, (byte) 0x49, (byte) 0x06, (byte) 0x24, (byte) 0x5c, (byte) 0xc2, (byte) 0xd3, (byte) 0xac, (byte) 0x62, (byte) 0x91, (byte) 0x95, (byte) 0xe4, (byte) 0x79},
{(byte) 0xe7, (byte) 0xc8, (byte) 0x37, (byte) 0x6d, (byte) 0x8d, (byte) 0xd5, (byte) 0x4e, (byte) 0xa9, (byte) 0x6c, (byte) 0x56, (byte) 0xf4, (byte) 0xea, (byte) 0x65, (byte) 0x7a, (byte) 0xae, (byte) 0x08},
{(byte) 0xba, (byte) 0x78, (byte) 0x25, (byte) 0x2e, (byte) 0x1c, (byte) 0xa6, (byte) 0xb4, (byte) 0xc6, (byte) 0xe8, (byte) 0xdd, (byte) 0x74, (byte) 0x1f, (byte) 0x4b, (byte) 0xbd, (byte) 0x8b, (byte) 0x8a},
{(byte) 0x70, (byte) 0x3e, (byte) 0xb5, (byte) 0x66, (byte) 0x48, (byte) 0x03, (byte) 0xf6, (byte) 0x0e, (byte) 0x61, (byte) 0x35, (byte) 0x57, (byte) 0xb9, (byte) 0x86, (byte) 0xc1, (byte) 0x1d, (byte) 0x9e},
{(byte) 0xe1, (byte) 0xf8, (byte) 0x98, (byte) 0x11, (byte) 0x69, (byte) 0xd9, (byte) 0x8e, (byte) 0x94, (byte) 0x9b, (byte) 0x1e, (byte) 0x87, (byte) 0xe9, (byte) 0xce, (byte) 0x55, (byte) 0x28, (byte) 0xdf},
{(byte) 0x8c, (byte) 0xa1, (byte) 0x89, (byte) 0x0d, (byte) 0xbf, (byte) 0xe6, (byte) 0x42, (byte) 0x68, (byte) 0x41, (byte) 0x99, (byte) 0x2d, (byte) 0x0f, (byte) 0xb0, (byte) 0x54, (byte) 0xbb, (byte) 0x16}
};//S盒
private final static byte[][] s_Box = new byte[16][16];//逆S盒的声明
static {
int k;//由于Java不支持无符号数,所以自行转换,k用于存储数组对应的无符号数
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
k = sBox[i][j] & 0xff;//将有符号数转化成无符号数
s_Box[k / 16][k % 16] = (byte) (i * 16 + j);
}
}
}//根据S盒生成逆S盒
private final byte[][] mMatrix = new byte[4][4];//明文状态矩阵
private final byte[][] keys = new byte[11][16];//轮密钥,由密钥生成
public AES(byte[] key) {
if (key.length != 16) {
throw new IllegalArgumentException("密钥长度应为128比特");
}//合法检验
{
int[] w = new int[44];//存储字为单位的轮密钥
int[] t = new int[10];//以字为单位的每轮的t
byte[] x = new byte[4];//转换用到的数组
for (int i = 0; i < 4; i++) {
w[i] = (key[i * 4] << 24) | (key[i * 4 + 1] << 16 & 0xffffff) | (key[i * 4 + 2] << 8 & 0xffff) | (key[i * 4 + 3] & 0xff);
}//将密钥字节转换为字存储在w中
for (int i = 1; i <= 10; i++) {
t[i - 1] = w[4 * i - 1] << 8 | (w[4 * i - 1] >> 24 & 0xff);//将w4n-1进行字节旋转,暂时存储在t[i-1]中
x[0] = (byte) (t[i - 1] >> 24 & 0xff);
x[1] = (byte) (t[i - 1] >> 16 & 0xff);
x[2] = (byte) (t[i - 1] >> 8 & 0xff);
x[3] = (byte) (t[i - 1] & 0xff);//将旋转后的w4n-1存储到byte数组中
for (int k = 0; k < 4; k++) {
x[k] = sBox[(x[k] & 0xff) / 16][(x[k] & 0xff) % 16];
}//进行字节代替
t[i - 1] = (x[0] << 24) | (x[1] << 16 & 0xffffff) | (x[2] << 8 & 0xffff) | (x[3] & 0xff);//转换到字,暂时存储在t[i-1]中
t[i - 1] = t[i - 1] ^ rC[i - 1];//与轮常数亦或,得到结果
//计算每轮的t
w[4 * i] = w[4 * i - 4] ^ t[i - 1];
w[4 * i + 1] = w[4 * i - 3] ^ w[4 * i];
w[4 * i + 2] = w[4 * i - 2] ^ w[4 * i + 1];
w[4 * i + 3] = w[4 * i - 1] ^ w[4 * i + 2];
//得到t后计算w4~w43
for (int q = 0; q < 11; q++) {
for (int r = 0; r < 4; r++) {
keys[q][r * 4] = (byte) (w[q * 4 + r] >> 24 & 0xff);
keys[q][r * 4 + 1] = (byte) (w[q * 4 + r] >> 16 & 0xff);
keys[q][r * 4 + 2] = (byte) (w[q * 4 + r] >> 8 & 0xff);
keys[q][r * 4 + 3] = (byte) (w[q * 4 + r] & 0xff);
}
}
//将w中以字为单位存储的轮密钥转换到以字节为单位存储的轮密钥数组keys中
}//计算10轮密钥
}//生成轮密钥
}//构造函数,生成指定密钥的AES对象,并根据密钥生成轮密钥
public byte[] encryption(byte[] m) {
int r = m.length % 16 == 0 ? m.length / 16 : m.length / 16 + 1;//需要将消息分r次进行加密,电码本模式
byte[] c = new byte[r * 16];//返回的密文
for (int p = 0; p < r; p++) {
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
try {
mMatrix[i][j] = m[p * 16 + j * 4 + i];
} catch (ArrayIndexOutOfBoundsException e) {
}
}
}//将明文装进明文矩阵
encryption();//对明文矩阵进行AES加密
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
c[p * 16 + j * 4 + i] = mMatrix[i][j];
}
}//从明文矩阵取回结果放在c的对应位置中
for (int i = 0; i < 4; i++) {
Arrays.fill(mMatrix[i], (byte) 0);
}//清空明文矩阵
}//进行r次加密,并将密文存储在数组c中
return c;
}
public byte[] decryption(byte[] c) {
int r = c.length % 16 == 0 ? c.length / 16 : c.length / 16 + 1;//需要将消息分r次进行解密
byte[] m = new byte[r * 16];//返回的明文
for (int p = 0; p < r; p++) {
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
try {
mMatrix[i][j] = c[p * 16 + j * 4 + i];
} catch (ArrayIndexOutOfBoundsException e) {
}
}
}//将密文装进明文矩阵
decryption();//对明文矩阵进行AES解密
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
m[p * 16 + j * 4 + i] = mMatrix[i][j];
}
}//从明文矩阵取回结果放在c的对应位置中
for (int i = 0; i < 4; i++) {
Arrays.fill(mMatrix[i], (byte) 0);
}//清空明文矩阵
}//进行r次解密,并将明文存储在数组m中
return m;
}
private void encryption() {
byte b;//用于行位移存放数据
byte[] m = new byte[4];//用于列混合存放数据
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
mMatrix[i][j] = (byte) ((mMatrix[i][j] & 0xff) ^ (keys[0][j * 4 + i] & 0xff));
}
}//进行一次轮密钥加
for (int r = 1; r <= 10; r++) {
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
mMatrix[i][j] = sBox[(mMatrix[i][j] & 0xff) / 16][(mMatrix[i][j] & 0xff) % 16];
}
}//字节替换
b = mMatrix[1][0];
System.arraycopy(mMatrix[1], 1, mMatrix[1], 0, 3);
mMatrix[1][3] = b;
b = mMatrix[2][0];
mMatrix[2][0] = mMatrix[2][2];
mMatrix[2][2] = b;
b = mMatrix[2][1];
mMatrix[2][1] = mMatrix[2][3];
mMatrix[2][3] = b;
b = mMatrix[3][3];
System.arraycopy(mMatrix[3], 0, mMatrix[3], 1, 3);
mMatrix[3][0] = b;
//行移位
if (r != 10) {
for (int j = 0; j < 4; j++) {
m[0] = (byte) ((multi(mMatrix[0][j], cx[0]) & 0xff) ^ (multi(mMatrix[1][j], cx[3]) & 0xff) ^ (multi(mMatrix[2][j], cx[2]) & 0xff) ^ (multi(mMatrix[3][j], cx[1]) & 0xff));
m[1] = (byte) ((multi(mMatrix[0][j], cx[1]) & 0xff) ^ (multi(mMatrix[1][j], cx[0]) & 0xff) ^ (multi(mMatrix[2][j], cx[3]) & 0xff) ^ (multi(mMatrix[3][j], cx[2]) & 0xff));
m[2] = (byte) ((multi(mMatrix[0][j], cx[2]) & 0xff) ^ (multi(mMatrix[1][j], cx[1]) & 0xff) ^ (multi(mMatrix[2][j], cx[0]) & 0xff) ^ (multi(mMatrix[3][j], cx[3]) & 0xff));
m[3] = (byte) ((multi(mMatrix[0][j], cx[3]) & 0xff) ^ (multi(mMatrix[1][j], cx[2]) & 0xff) ^ (multi(mMatrix[2][j], cx[1]) & 0xff) ^ (multi(mMatrix[3][j], cx[0]) & 0xff));
mMatrix[0][j] = m[0];
mMatrix[1][j] = m[1];
mMatrix[2][j] = m[2];
mMatrix[3][j] = m[3];
}
}//1~9轮进行列混合
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
mMatrix[i][j] = (byte) ((mMatrix[i][j] & 0xff) ^ (keys[r][j * 4 + i] & 0xff));
}
}//轮密钥加
}//进行十轮加密
}
private void decryption() {
byte b;//用于逆行位移存放数据
byte[] m = new byte[4];//用于列混合存放数据
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
mMatrix[i][j] = (byte) ((mMatrix[i][j] & 0xff) ^ (keys[10][j * 4 + i] & 0xff));
}
}//轮密钥加
for (int r = 9; r >= 0; r--) {
b = mMatrix[1][3];
System.arraycopy(mMatrix[1], 0, mMatrix[1], 1, 3);
mMatrix[1][0] = b;
b = mMatrix[2][0];
mMatrix[2][0] = mMatrix[2][2];
mMatrix[2][2] = b;
b = mMatrix[2][1];
mMatrix[2][1] = mMatrix[2][3];
mMatrix[2][3] = b;
b = mMatrix[3][0];
System.arraycopy(mMatrix[3], 1, mMatrix[3], 0, 3);
mMatrix[3][3] = b;
//逆行移位
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
mMatrix[i][j] = s_Box[(mMatrix[i][j] & 0xff) / 16][(mMatrix[i][j] & 0xff) % 16];
}
}//逆字节替换
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
mMatrix[i][j] = (byte) ((mMatrix[i][j] & 0xff) ^ (keys[r][j * 4 + i] & 0xff));
}
}//轮密钥加
if (r != 0) {
for (int j = 0; j < 4; j++) {
m[0] = (byte) ((multi(mMatrix[0][j], c_x[0]) & 0xff) ^ (multi(mMatrix[1][j], c_x[3]) & 0xff) ^ (multi(mMatrix[2][j], c_x[2]) & 0xff) ^ (multi(mMatrix[3][j], c_x[1]) & 0xff));
m[1] = (byte) ((multi(mMatrix[0][j], c_x[1]) & 0xff) ^ (multi(mMatrix[1][j], c_x[0]) & 0xff) ^ (multi(mMatrix[2][j], c_x[3]) & 0xff) ^ (multi(mMatrix[3][j], c_x[2]) & 0xff));
m[2] = (byte) ((multi(mMatrix[0][j], c_x[2]) & 0xff) ^ (multi(mMatrix[1][j], c_x[1]) & 0xff) ^ (multi(mMatrix[2][j], c_x[0]) & 0xff) ^ (multi(mMatrix[3][j], c_x[3]) & 0xff));
m[3] = (byte) ((multi(mMatrix[0][j], c_x[3]) & 0xff) ^ (multi(mMatrix[1][j], c_x[2]) & 0xff) ^ (multi(mMatrix[2][j], c_x[1]) & 0xff) ^ (multi(mMatrix[3][j], c_x[0]) & 0xff));
mMatrix[0][j] = m[0];
mMatrix[1][j] = m[1];
mMatrix[2][j] = m[2];
mMatrix[3][j] = m[3];
}
}//进行9轮逆列混合
}//进行10轮解密
}
private byte multi(byte a, byte b) {
int n = 0b11111111111111;//用于进行模运算
int m = 0;
for (int i = 0; i < 8; i++) {
m = (b >> i & 0b1) == 1 ? m ^ ((a & 0xff) << i) : m;
}//得到a与b相乘的结果存放在int m中
for (int i = 0; i < 7; i++) {
m = m > n >> i ? m ^ irreduciblePolynomial << 6 - i : m;
}//将结果模掉8次不可约多项式irreduciblePolynomial
return (byte) m;
}//8比特多项式模乘运算
static byte[] createKey() {
byte[] key = new byte[16];
new Random().nextBytes(key);
return key;
}//随机生成密钥
}
密码学课程实验,代码拿走不谢
package AES;
import java.nio.charset.StandardCharsets;
public class run1 {
public static void main(String[] args) {
byte[] key=AES.createKey();
System.out.print("密钥:");
for(int i=0;i<16;i++) {
System.out.print(Integer.toHexString(key[i] & 0xff) + '\t');
}
System.out.println("");//获取密钥
byte[] m="Hello,world!".getBytes(StandardCharsets.UTF_8);//明文内容
byte[] c;//获取密文
AES aes=new AES(key);
System.out.print("明文字符:");
for(int i=0;i<m.length;i++) {
System.out.print(Integer.toHexString(m[i] & 0xff) + '\t');
}
System.out.println("");
long startTime = System.nanoTime();
c=aes.encryption(m);
long endTime = System.nanoTime();
System.out.print("密文字符:");
for(int i=0;i<c.length;i++) {
System.out.print(Integer.toHexString(c[i] & 0xff) + '\t');
}
System.out.println("");
System.out.println("密文内容:"+new String(c,StandardCharsets.UTF_8));
m=aes.decryption(c);
System.out.println("解密内容:"+new String(m,StandardCharsets.UTF_8));
System.out.println("加密时间:"+(endTime-startTime)+"ns");
}
}
运行截图:
里面的编码格式可以在run1里面自己改的,只是参数问题