您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

如何在Java中进行AES加密和解密操作

2024/4/15 20:13:12发布32次查看
1.背景知识
在密码学中,加密算法分为单向加密和双向加密。
对称加密是指加密和解密使用相同的密钥,包括aes加密、des加密等。
非对称加密是指加密和解密使用不同的密钥,包括rsa加密等。
单向加密包括md5、sha等摘要算法,它们是不可逆的。
双向加密包括对称加密和非对称加密。双向加密是可逆的,存在密文的密钥。
2.aes简介aes: 高级加密标准(advanced encryption standard)是美国联邦政府采用的一种区块加密标准,是目前最流行的一种对称加密算法。
是用来替代des的新一代分组加密算法。
aes支持三种长度的密钥:128位、192位、256位。
3.aes的加密过程(aes处理单位:字节)aes的加解密过程和des一样,都是通过分组加密、分组解密。所谓分组加密,就是将待加解密的内容按照128位进行分组,将密钥按照128位、192位、256位进行分组,分别将分组后的明文与相应分组后的密钥进行加解密。
加密: 明文与密钥分组后,对每组:明文组与密钥组处理 -> 轮密钥加 -> 10轮加密 -> 密文组
解密: 对每组:密文组 -> 轮密钥加 -> 10轮解密 -> 明文组
明文分组: 每组长度相等,都是128位(16字节);
密钥分组: 有128位、192位、256位,推荐加密轮数分别为 10、12、14
密钥组处理: 以密钥分组每组128位为例(则推荐加密轮数为10,前9次执行操作一样,第十次有所不同) 类似地,128位密钥也是用字节为单位的矩阵表示,通过密钥编排函数,形成具有44个元素的序列w[0],w[1], … ,w[43](每个元素4个字节);其中,w[0],w[1],w[2],w[3]为原始密钥,其余40个元素分为10组,每组4个元素(4*4=16字节),分别用于10轮加密。
aes加密算法涉及4种操作: 字节替代(subbytes)、行移位(shiftrows)、列混淆(mixcolumns)和轮密钥加(addroundkey)。
下图给出了aes加解密的流程:
addroundkey (轮密钥加)— 矩阵中的每一个字节都与该次轮密钥(round key)做xor运算;每个子密钥由密钥生成方案产生。
subbytes(字节替代) — 通过非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
shiftrows(行移位) — 将矩阵中的每个横列进行循环式移位。
mixcolumns (列混淆)— 为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每列的四个字节。
假如一段明文长度是192bit,如果按每128bit一个明文块来拆分的话,第二个明文块只有64bit,不足128bit。这时候怎么办呢?就需要对明文块进行填充(padding)。
填充涉及以下三种填充模式:
nopadding:不做任何填充,但是要求明文必须是16字节的整数倍。
pkcs5padding(默认):如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。
比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6}
iso10126padding:如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字节,最后一个字符值等于缺少的字符数,其他字符填充随机数。
比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则可能补全为{1,2,3,4,5,a,b,c,d,e,5,c,3,g,$,6}
4.java实现注意:aes加密包含base64加密
加密: aes加密 -> base64加密 -> 密文
解密: base64解密 -> aes解密 -> 明文
测试地址:点击此处
4.1 生成密钥和偏移量生成16个大小写字母和数字的随机数即可:
private static final string symbols = "0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; // 数字和26个字母组成private static final random random = new securerandom();/** * 获取长度为 6 的随机字母+数字 * @return 随机数字 */public static string getrandomnumber() { char[] noncechars = new char[16]; //指定长度为6位/自己可以要求设置 for (int index = 0; index < noncechars.length; ++index) { noncechars[index] = symbols.charat(random.nextint(symbols.length())); } return new string(noncechars);}
4.2 aesutil.java 源码import org.apache.commons.lang3.randomstringutils;import org.apache.commons.lang3.stringutils;import org.slf4j.logger;import org.slf4j.loggerfactory;import org.springframework.util.base64utils;import javax.crypto.cipher;import javax.crypto.spec.ivparameterspec;import javax.crypto.spec.secretkeyspec;/** * aes加密工具类 * * @author acgkaka * @since 2021-06-18 19:11:03 */public class aesutil { /** * 日志相关 */ private static final logger logger = loggerfactory.getlogger(aesutil.class); /** * 编码 */ private static final string encoding = "utf-8"; /** * 算法定义 */ private static final string aes_algorithm = "aes"; /** * 指定填充方式 */ private static final string cipher_padding = "aes/ecb/pkcs5padding"; private static final string cipher_cbc_padding = "aes/cbc/pkcs5padding"; /** * 偏移量(cbc中使用,增强加密算法强度) */ private static final string iv_seed = "1234567812345678"; /** * aes加密 * @param content 待加密内容 * @param aeskey 密码 * @return */ public static string encrypt(string content, string aeskey){ if(stringutils.isblank(content)){ logger.info("aes encrypt: the content is null!"); return null; } //判断秘钥是否为16位 if(stringutils.isnotblank(aeskey) && aeskey.length() == 16){ try { //对密码进行编码 byte[] bytes = aeskey.getbytes(encoding); //设置加密算法,生成秘钥 secretkeyspec skeyspec = new secretkeyspec(bytes, aes_algorithm); // "算法/模式/补码方式" cipher cipher = cipher.getinstance(cipher_padding); //选择加密 cipher.init(cipher.encrypt_mode, skeyspec); //根据待加密内容生成字节数组 byte[] encrypted = cipher.dofinal(content.getbytes(encoding)); //返回base64字符串 return base64utils.encodetostring(encrypted); } catch (exception e) { logger.info("aes encrypt exception:" + e.getmessage()); throw new runtimeexception(e); } }else { logger.info("aes encrypt: the aeskey is null or error!"); return null; } } /** * 解密 * * @param content 待解密内容 * @param aeskey 密码 * @return */ public static string decrypt(string content, string aeskey){ if(stringutils.isblank(content)){ logger.info("aes decrypt: the content is null!"); return null; } //判断秘钥是否为16位 if(stringutils.isnotblank(aeskey) && aeskey.length() == 16){ try { //对密码进行编码 byte[] bytes = aeskey.getbytes(encoding); //设置解密算法,生成秘钥 secretkeyspec skeyspec = new secretkeyspec(bytes, aes_algorithm); // "算法/模式/补码方式" cipher cipher = cipher.getinstance(cipher_padding); //选择解密 cipher.init(cipher.decrypt_mode, skeyspec); //先进行base64解码 byte[] decodebase64 = base64utils.decodefromstring(content); //根据待解密内容进行解密 byte[] decrypted = cipher.dofinal(decodebase64); //将字节数组转成字符串 return new string(decrypted, encoding); } catch (exception e) { logger.info("aes decrypt exception:" + e.getmessage()); throw new runtimeexception(e); } }else { logger.info("aes decrypt: the aeskey is null or error!"); return null; } } /** * aes_cbc加密 * * @param content 待加密内容 * @param aeskey 密码 * @return */ public static string encryptcbc(string content, string aeskey){ if(stringutils.isblank(content)){ logger.info("aes_cbc encrypt: the content is null!"); return null; } //判断秘钥是否为16位 if(stringutils.isnotblank(aeskey) && aeskey.length() == 16){ try { //对密码进行编码 byte[] bytes = aeskey.getbytes(encoding); //设置加密算法,生成秘钥 secretkeyspec skeyspec = new secretkeyspec(bytes, aes_algorithm); // "算法/模式/补码方式" cipher cipher = cipher.getinstance(cipher_cbc_padding); //偏移 ivparameterspec iv = new ivparameterspec(iv_seed.getbytes(encoding)); //选择加密 cipher.init(cipher.encrypt_mode, skeyspec, iv); //根据待加密内容生成字节数组 byte[] encrypted = cipher.dofinal(content.getbytes(encoding)); //返回base64字符串 return base64utils.encodetostring(encrypted); } catch (exception e) { logger.info("aes_cbc encrypt exception:" + e.getmessage()); throw new runtimeexception(e); } }else { logger.info("aes_cbc encrypt: the aeskey is null or error!"); return null; } } /** * aes_cbc解密 * * @param content 待解密内容 * @param aeskey 密码 * @return */ public static string decryptcbc(string content, string aeskey){ if(stringutils.isblank(content)){ logger.info("aes_cbc decrypt: the content is null!"); return null; } //判断秘钥是否为16位 if(stringutils.isnotblank(aeskey) && aeskey.length() == 16){ try { //对密码进行编码 byte[] bytes = aeskey.getbytes(encoding); //设置解密算法,生成秘钥 secretkeyspec skeyspec = new secretkeyspec(bytes, aes_algorithm); //偏移 ivparameterspec iv = new ivparameterspec(iv_seed.getbytes(encoding)); // "算法/模式/补码方式" cipher cipher = cipher.getinstance(cipher_cbc_padding); //选择解密 cipher.init(cipher.decrypt_mode, skeyspec, iv); //先进行base64解码 byte[] decodebase64 = base64utils.decodefromstring(content); //根据待解密内容进行解密 byte[] decrypted = cipher.dofinal(decodebase64); //将字节数组转成字符串 return new string(decrypted, encoding); } catch (exception e) { logger.info("aes_cbc decrypt exception:" + e.getmessage()); throw new runtimeexception(e); } }else { logger.info("aes_cbc decrypt: the aeskey is null or error!"); return null; } } public static void main(string[] args) { // aes支持三种长度的密钥:128位、192位、256位。 // 代码中这种就是128位的加密密钥,16字节 * 8位/字节 = 128位。 string random = randomstringutils.random(16, "abcdefghijklmnopqrstuvwxyz1234567890"); system.out.println("随机key:" + random); system.out.println(); system.out.println("---------加密---------"); string aesresult = encrypt("测试aes加密12", random); system.out.println("aes加密结果:" + aesresult); system.out.println(); system.out.println("---------解密---------"); string decrypt = decrypt(aesresult, random); system.out.println("aes解密结果:" + decrypt); system.out.println(); system.out.println("--------aes_cbc加密解密---------"); string cbcresult = encryptcbc("测试aes加密12456", random); system.out.println("aes_cbc加密结果:" + cbcresult); system.out.println(); system.out.println("---------解密cbc---------"); string cbcdecrypt = decryptcbc(cbcresult, random); system.out.println("aes解密结果:" + cbcdecrypt); system.out.println(); }}
4.3 执行结果随机key:golrtt58318fx7ol---------加密---------aes加密结果:xy8w9lcevue9ao36z+dum7d7wes5tdbihimb1q9kpng=---------解密---------aes解密结果:测试aes加密12--------aes_cbc加密解密---------aes_cbc加密结果:xs3ypqxyd62p9jb0+rvoqxfnhihbilvdqozluqynblw=---------解密cbc---------aes解密结果:测试aes加密12456
4.4 线上验证
以上就是如何在java中进行aes加密和解密操作的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product