hello,大家好久不见,继上次我们分析了AES算法的加密已经过去了近两个月,那么现在分享一下AES加密的密钥编排算法
详见https://blog.csdn.net/qq_31236027/article/details/129796471?spm=1001.2014.3001.5501
/**
* Aes常量
* @author zygswo
*
*/
public class AESConstant {
/**
* 字符串长度
*/
public static final int CHAR_LEN = 16;
/**
* 分组长度
*/
public static final int DIV_LEN = 128 / CHAR_LEN;
/**
* s-盒
*/
public static final 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","E4","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","BE","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"}
};
/**
* 密钥长度
*/
public static final int KEY_LENGTH = 128;
/**
* 加密轮数
*/
public static final int ENCRYPT_ROUND = 10;
/**
* 一行的位数
*/
public static final int INIT_MATRIX_COLUMNS = KEY_LENGTH / 32;
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import common.EncodeUtil;
import common.EncodeUtil.EncodeRadix;
import constant.AESConstant;
/**
* aes加解密密钥生成工具类
* @author zygswo
*
*/
public class KeyUtil {
/**
* 键list
*/
private List<String> keyList = Collections.synchronizedList(
new ArrayList<>()
);
/**
* 密钥初始矩阵(从上到下,从左到右)
*/
private String[][] initMatrix;
/**
* 轮系数RC
*/
private static final String[] RC_ROUND = {
"00000000",
"00000001",
"00000010",
"00000100",
"00001000",
"00010000",
"00100000",
"01000000",
"10000000",
"00011011",
"00110110"
};
/**
* 初始化
*/
public KeyUtil init() {
int size = AESConstant.KEY_LENGTH / 8;
//获取128位的密钥
String randomStr = UUID.randomUUID().toString().substring(0,size);
// String randomStr = "zygswozygswozygs";
// System.out.println(randomStr);
//初始化密钥初始矩阵(从上到下,从左到右)
initMatrix = new String[4][AESConstant.INIT_MATRIX_COLUMNS];
for(int i=0; i<size; i++) {
initMatrix[i%4][i/4] = EncodeUtil.strtoBinary(randomStr.charAt(i) + "", 8);
}
// for (int i=0; i<4;i++) {
// System.out.println(Arrays.toString(initMatrix[i]));
// }
return this;
}
/**
* 生成密钥
*/
public List<String> generateKeys() {
if (initMatrix == null || initMatrix.length == 0) {
throw new RuntimeException("请先进行密钥初始化");
}
String[] temp = new String[AESConstant.INIT_MATRIX_COLUMNS];
for (int i=0; i<temp.length;i++) {
temp[i] = "";
}
//按列获取
for (int i=0; i< AESConstant.KEY_LENGTH / 8; i++) {
temp[i/AESConstant.INIT_MATRIX_COLUMNS] += initMatrix[i%AESConstant.INIT_MATRIX_COLUMNS][i/AESConstant.INIT_MATRIX_COLUMNS];
}
return generateKeys(temp,0);
}
/**‘
* 生成密钥
* @param temp 每轮加密输入
* @param round 轮数
*/
private List<String> generateKeys(String[] temp, int round) {
//如果为第一轮就直接返回当前的值
if(round == 0) {
keyList.add(arrToStr(temp));
return generateKeys(temp, round+1);
}
//最后一轮
if(round == AESConstant.ENCRYPT_ROUND+1){
return keyList;
}
//中间几轮
temp[0] = xor(temp[0], g(temp[3],round));
for(int i = 1;i<temp.length;i++) {
temp[i] = xor(temp[i],temp[i-1]);
}
keyList.add(arrToStr(temp));
return generateKeys(temp, round + 1);
}
/**
* 数组转字符串
* @param arr
* @return
*/
private String arrToStr(String[] arr) {
String str = new String();
for (String strTemp: arr) {
str += strTemp;
}
return str.toString();
}
/**
* 异或运算
* @param param1
* @param param2
* @return
*/
private String xor(String param1, String param2) {
if (param1 == null || param2 == null || param1.length() != param2.length()) {
throw new IllegalArgumentException("参数有误!");
}
//异或运算
StringBuilder sb = new StringBuilder();
for(int i = 0; i< param1.length();i++) {
int i1 = (param1.charAt(i) - '0');
int i2 = (param2.charAt(i) - '0');
sb.append((i1 ^ i2) + "");
}
return sb.toString();
}
/**
* g函数
* @param string bit32Str 32位字符串
* @param round 轮数
* @return g函数结果
*/
private String g(String bit32Str, int round) {
//循环左移一位
String leftShiftTemp = bit32Str.substring(0,8);
bit32Str = bit32Str.substring(8) + leftShiftTemp;
StringBuilder result = new StringBuilder();
for (int i=0; i<4;i++) {
String str = bit32Str.substring(8*i, 8*(i+1));
//s-盒运算
int rowNb = Integer.parseInt(EncodeUtil.binaryToDec(str.substring(0,4)));
int colNb = Integer.parseInt(EncodeUtil.binaryToDec(str.substring(4)));
str = EncodeUtil.toBinary(AESConstant.SBOX[rowNb][colNb], EncodeRadix.HEX);
//与左边第一个字节进行轮系数相加(伽罗瓦域的异或)运算
if (i == 0) {
str = xor(str,RC_ROUND[round]);
}
result.append(str);
}
return result.toString();
}
}