AES对称加密
其他博客讲的底层原理算法,确实看不懂,自己会使用就行了,以后再来研究。
一、AES重要参数
①密钥:
- aes密钥:支持三种密钥长度:128位,192位,256位。不同长度意味加密的轮数不同,128位加密10轮,192加密12轮,256加密14轮。轮数越高约安全,但是效率也随之降低。
- JAVA对秘钥的位数有限制,默认你只能使用128位的秘钥,也就是16个字节字符串。要想突破此限制需要替换jdk下的2个jar文件。详细可参看文章:http://www.mamicode.com/info-detail-1879825.html
②填充:
AES会将文明分成长度相等的块,每块128bit,再对每一块进行加密。如果某些块的长度不足128bit,就会自动填充。
填充的方式有几种:NoPadding、PKCS5Padding、PKCS7Padding
NoPadding:不进行填充,要求原始加密串大小必须是128bit的整数倍;
PKCS5Padding:块大小位8,还差m个才补齐为8个。那个块的后面,就补齐m个m.
PKCS7Padding:跟PKCS5Padding的填充方式一样,不同的是,PKCS5Padding只是对8字节的进行填充,PKCS7Padding
可以对1~256字节大小的block进行填充
③模式:AES有多种加密模式,包括:ECB,CBC,CTR,OCF,CFB,最常见的还是ECB和CBC模式。
ECB模式:最简单的一种加密模式,每个块进行独立加密,块与块之间加密互不影响,这样就能并行,效率高。
虽然这样加密很简单,但是不安全,如果两个块的明文一模一样,那么加密出来的东西也一模一样。
CBC模式:引入初始向量iv。iv的作用就是为了防止同样的明文块被加密成同样的内容。原理是第一个明文块跟初始向量做异或后加密,第二个块跟第一个密文块做异或再加密,依次类推,避免了同样的块被加密成同样的内容。
重点:在合作开发的时候,一定问清楚几个问题?
①aes用的什么模式?
②aes的填充方式是什么?有的第三方不用标准的填充方式,令人费解,所以一定要问清楚。
③如果模式为CBC,要问设置的初始向量iv是什么?
④密钥是多少?
二、代码演示
案例选择CBC模式,所以偏移向量,填充选择PKCS5Padding。如下:
代码举例:
package com.yy.springbootdemo.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESUtil{
//算法
private static final String ALGORITHM = "AES";
//填充 下面字符串分别是算法,模式,填充方式
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
// 编码
private static final String ENCODING = "UTF-8";
// 密匙 必须位16位
private static final String KEY = "210648d869328yyy";
// 偏移量 必须位16位
private static final String OFFSET = "1124440405060701";
/**
* TODO AES加密
**/
public static String encrypt(String data) throws Exception {
// 初始化cipher
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//转化成JAVA的密钥格式
SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("ASCII"), ALGORITHM);
//使用CBC模式,需要一个向量iv,可增加加密算法的强度
IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(data.getBytes(ENCODING));
//此处使用BASE64做转码。
String result = new BASE64Encoder().encode(encrypted);
return result;
}
/**
* //TODO AES解密
**/
public static String decrypt(String data) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("ASCII"), ALGORITHM);
//使用CBC模式,需要一个向量iv,可增加加密算法的强度
IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] buffer = new BASE64Decoder().decodeBuffer(data);
byte[] encrypted = cipher.doFinal(buffer);
//此处使用BASE64做转码。
String result = new String(encrypted, ENCODING);
return result;
}
}