AES加密解密工具类封装(AESUtil)
package club.codeapes.common.utils; import org.springframework.util.Base64Utils; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger; /**
* @version V1.0
* @desc AES 加密工具类
*/
public class AESUtil { private static final String KEY_ALGORITHM = "AES";
private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算法
//自定义密码
private static final String ASSETS_DEV_PWD_FIELD = "xxxx"; public static String getAssetsDevPwdField() {
return ASSETS_DEV_PWD_FIELD;
} /**
* AES 加密操作
*
* @param content 待加密内容
* @param password 加密密码
* @return 返回Base64转码后的加密数据
*/
public static String encrypt(String content, String password) {
try {
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器 byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化为加密模式的密码器 byte[] result = cipher.doFinal(byteContent);// 加密 return Base64Utils.encodeToString(result);//通过Base64转码返回
} catch (Exception ex) {
Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
} return null;
} /**
* AES 解密操作
*
* @param content
* @param password
* @return
*/
public static String decrypt(String content, String password) { try {
//实例化
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); //使用密钥初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password)); //执行操作
byte[] result = cipher.doFinal(Base64Utils.decodeFromString(content));
String s = new String(result, "utf-8");
return s;
} catch (Exception ex) {
ex.printStackTrace();
Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
} return null;
} /**
* 生成加密秘钥
*
* @return
*/
private static SecretKeySpec getSecretKey(String password) {
//返回生成指定算法密钥生成器的 KeyGenerator 对象
KeyGenerator kg = null;
try {
kg = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(password.getBytes());
//AES 要求密钥长度为 128
kg.init(128, random);
//生成一个密钥
SecretKey secretKey = kg.generateKey();
return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
} public static void main(String[] args) {
String origin = "my test string";
String encrypt = AESUtil.encrypt(origin, AESUtil.ASSETS_DEV_PWD_FIELD);
String decrypt = AESUtil.decrypt(encrypt, AESUtil.ASSETS_DEV_PWD_FIELD);
System.out.println(origin);
System.out.println(encrypt);
System.out.println(decrypt);
} }
关于过程中,为什么可以用base64对产生的数组进行编码,以及解码。使用的时候可能产生异常:解密的字节数组必须是16的倍数
发现当把字节数组转为字符串后,在把字符串.getBytes()获得数组,发现两个字节数组前后不一样了
强调一下:new String(byte[]),和"str".getBytes(),两个方法使用的编码一样,然后换成其他编码也出现这样情况
原因:
1. 为什么数组转字符串,字符串然后转数组会出现,前后两个字节数组的值会不同,因为并不是每个字节数和编码集上的字符都有对应关系,如果一个字节数在编码集上没有对应,编码new String(byte[]) 后,往往解出来的会是一些乱码无意义的符号:例如:��,
但是解码的时候,�这个字符也是一个字符在编码表中也有固定的字节数用来表示,所有解码出来的值必定是编码表中对应的值,除非你的字节数组中的字节数正好在编码表中有对应的值,否则编码,解码后的字节数组会不一样
误区: 误以为所有的字节数组都可以new String(),然后在通过String.getBytes()还原
2.再说这个异常报:解密的字节数组必须是16的倍数,这得从AES的原理说起,AES是把数据按16字节分组加密的,所有如果数组长度不是16的倍数会报错
AES原理:AES是对数据按128位,也就是16个字节进行分组进行加密的,每次对一组数据加密需要运行多轮。而输入密钥的长度可以为128、192和256位,也就是16个字节、24个字节和32个字节,如果用户输入的密钥长度不是这几种长度,也会补成这几种长度。无论输入密钥是多少字节,加密还是以16字节的数据一组来进行的,密钥长度的不同仅仅影响加密运行的轮数。
可以用base64对参生的数组进行编码,然后在解码,这样不会像new String(byte[]),getBytes()那样造成数组前后不一致,一开始,我看到大部分人都是用base64,我也只是以为多一层编码看起来安全一些而已,没想到base64对数组的处理是不会造成误差的
AES加密解密工具类封装(AESUtil)的更多相关文章
- 自写AES加密解密工具类
此类主要用于加密与解密,采用128位ECB模式,PKCS5Padding填充补位. 可使用方法为加密返回二进制encryptBin(content, key).加密返回十六进制encryptHex(c ...
- Java中的AES加解密工具类:AESUtils
本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.constants.SysConsta ...
- AES加密解密 助手类 CBC加密模式
"; string result1 = AESHelper.AesEncrypt(str); string result2 = AESHelper.AesDecrypt(result1); ...
- Base64加密解密工具类
使用Apache commons codec类Base64进行加密解密 maven依赖 <dependency> <groupId>commons-codec</grou ...
- Java AES加密解密工具 -- GUI 、在线传输文件
原理 对于任意长度的明文,AES首先对其进行分组,每组的长度为128位.分组之后将分别对每个128位的明文分组进行加密. 对于每个128位长度的明文分组的加密过程如下: (1)将128位AES ...
- .Net(c#)加密解密工具类:
/// <summary> /// .Net加密解密帮助类 /// </summary> public class NetCryptoHelper { #region des实 ...
- java加密解密工具类
package com.founder.mrp.util; import java.nio.charset.StandardCharsets; import java.security.Key; im ...
- 加密解密工具类(Java,DES)
一个Java版的DES加密工具类,能够用来进行网络传输数据加密,保存password的时候进行加密. import java.security.Key; import java.security.sp ...
- java 加密解密工具类(实用!!!)
最近发现了一个加密解密的好例子,很方便使用,可以作为平时开发的工具集,记录一下. package com.sh.springboottdemo2.util; import com.sun.org.ap ...
随机推荐
- 出现 sudo: unable to resolve host XXX 信息解决办法
Ubuntu环境, 每次执行sudo 就出现这个警告讯息:sudo: unable to resolve host XXX虽然sudo 还是可以正常执行,是机器在反解上的问题, 所以就直接从/etc ...
- JS的ES7支持
1.指数运算符(幂): ** 2.Array.prototype.includes(value) : 判断数组中是否包含指定value console.log(2**4); let arr = [2, ...
- LOJ2778 [BOI2018]基因工程 随机化
题面 不想写了...留坑吧... 基本思想可参照随机化解决判同问题的总结 代码: #include<bits/stdc++.h> using namespace std; #define ...
- haproxy 配置文件详解 之 defaults
配置示例: defaults mode http retries timeout connect 10s timeout client 20s timeout server 30s timeout c ...
- SUSE12.2 编译usbutils
折腾了两天,终于交叉编译出来lsusb命令可以在单板上跑起来,记录一下 1:编译eudev下载地址:https://dev.gentoo.org/~blueness/eudev/,版本eudev-3. ...
- 简单说说JavaScript的Generator 实现(ES6)
Generator 是 ES6 中新增的语法,和 Promise 一样,都可以用来异步编程 // 使用 * 表示这是一个 Generator 函数 // 内部可以通过 yield 暂停代码 // 通过 ...
- 透彻的掌握 Spring 中@transactional 的使用
事务管理是应用系统开发中必不可少的一部分.Spring 为事务管理提供了丰富的功能支持.Spring 事务管理分为编码式和声明式的两种方式.编程式事务指的是通过编码方式实现事务:声明式事务基于 AOP ...
- Jenkins工具学习(一)
Jenkins的下载及安装 Jenkins下载地址:https://jenkins.io/download/ 下载后的直接解压安装 根据自己的喜好选择一种方式安装: 如果选择推荐安装,会自动下载一些插 ...
- 039 RabbitMq及数据同步01
1.RabbitMq (1)问题引出 目前我们已经完成了商品详情和搜索系统的开发.我们思考一下,是否存在问题? 商品的原始数据保存在数据库中,增删改查都在数据库中完成. 搜索服务数据来源是索引库,如果 ...
- Springboot Actuator之十:actuator中的audit包
前言这篇文章我们来分析一下org.springframework.boot.actuate.security,org.springframework.boot.actuate.audit中的代码,这2 ...