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 ...
随机推荐
- C语言中宏的相关知识
2019/04/27 16:02 1.宏的定义:宏定义就是预处理命令的一种,它允许用一个标识符来表示一个字符串.格式如下: #define name(宏名) stuff(字符串) 本质就是使用宏名去替 ...
- 二分类问题F-score评判指标(转载)
分类模型的评价指标Fscore 小书匠深度学习 分类方法常用的评估模型好坏的方法. 0.预设问题 假设我现在有一个二分类任务,是分析100封邮件是否是垃圾邮件,其中不是垃圾邮件有65封,是垃圾邮件有3 ...
- springboot2.x自定义拦截把static静态文件给拦截的坑
新人新帖,喷后请指正,谢谢 1.王中王,坑中坑 和很多人一样,我在springboo自定义配置登录拦截的时候,写一个WebConfig类继承WebMvcConfigureAdapter,重写AddRe ...
- nginx负载均衡+keepalived高可用
nginx负载均衡+keepalived高可用 环境准备 192.168.88.111:nginx + keepalived MASTER 192.168.88.112:nginx + keepa ...
- [转帖]算法精解:DAG有向无环图
算法精解:DAG有向无环图 https://www.cnblogs.com/Evsward/p/dag.html DAG是公认的下一代区块链的标志.本文从算法基础去研究分析DAG算法,以及它是如何运用 ...
- Nginx官方文档翻译(转)
add by zhj: 由并发网组织翻译,赞 <Nginx官方文档>WebSocket代理 <Nginx官方文档>配置文件中的单位 <Nginx官方文档>控制ngi ...
- CSP2019-S游记
目录 CSP2019-S游记 Day -2(UPDATE:2019-11-14) Day -1(UPDATE:2019-11-15) Day 1(UPDATE:2019-11-16) Day 2(UP ...
- webUI框架miniUI,easyUI,extJS,Bootstrap简介及简单部署
本文为大家讲解的是webUI框架miniUI,easyUI,extJS,Bootstrap简介及简单部属,感兴趣的同学参考下 ExtJS是一种主要用于创建前端用户界面,是一个基本与后台技术无关的前端a ...
- 当Windows操作系统关机时,不会执行Windows Service的OnStop方法(转载)
Windows Service OnStop when computer shutdown 问: I'm writing a Windows Service in C#. I want to take ...
- vs2019 netocore项目本地程序ip地址访问需修改的配置文件
IISPress启动项目后,打开IISPress托盘可以看到当前项目 根据图中标识出来的applicationhost.config文件路径,一般为你的项目解决方案目录下的.vs\解决方案文件夹\co ...