程序猿成长之路之密码学篇-AES算法密钥编排介绍

hello,大家好久不见,继上次我们分析了AES算法的加密已经过去了近两个月,那么现在分享一下AES加密的密钥编排算法

AES密钥编排算法原理

详见https://blog.csdn.net/qq_31236027/article/details/129796471?spm=1001.2014.3001.5501

AES密钥编排算法代码(128位)

/**
 * 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();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zygswo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值