java AES使用
java提供AES算法支持。支持的密钥长度为:128, 192, 或256位
。由于美国进出口限制,默认的jre只支持128
位,也就是16个字节的密钥。
支持的工作模式:
- NONE
- CBC
- CCM
- CFB, CFBx
- CTR
- CTS
- ECB
- GCM
- OFB, OFBx
- PCBC
支持的填充方式:
- NoPadding
- ISO10126Padding
- OAEPPadding
- PKCS1Padding
- PKCS5Padding
- SSL3Padding
当使用Cipher.getInstance("AES")
时,默认获取的是AES/ECB/PKCS5Padding
对应的实例。实际使用中这里一定要注意一下,建议实际应用中一定要显示指定工作模式和填充方式。若不显示指定,在跨语言、跨类库或跨系统调用时,容易踩坑。
java aes示例
java 版本 : 1.8。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100package com.cloudin.commons.security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/**
* Created by YFHan on 2017/4/4 0004.
*/
public class AESHelper {
/**
* 算法名称
*/
public static final String ALGORITHM_NAME ="AES";
/**
* java aes 算法默认工作模式
*/
public static final String DEFAULT_MODE = "ECB";
/**
* java aes 算法默认填充方式
*/
public static final String DEFAULT_PADDING = "PKCS5Padding";
/**
* java aes 算法默认的密码实例
*/
public static final String DEFAULT_CHIPHER_INSTANCE = "AES/ECB/PKCS5Padding";
/**
* 对指定内容使用指定秘钥进行AES(128)加密,并返回加密后的字节数组
*
* @param content 待加密的内容
* @param password 加密秘钥
* @return
*/
public static byte[] encrypt(byte[] content, byte[] password) {
Cipher cp = null;
try {
SecretKeySpec skeySpec = new SecretKeySpec(password, ALGORITHM_NAME);
cp = Cipher.getInstance(DEFAULT_CHIPHER_INSTANCE); // 算法/模式/填充
cp.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
return cp.doFinal(content);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
/**
* 对指定内容使用指定秘钥进行AES(128)解密,并返回解密后的字节数组
*
* @param content 待解密的内容
* @param password 解密秘钥
* @return
*/
public static byte[] decrypt(byte[] content, byte[] password) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(password, ALGORITHM_NAME);
Cipher cp = Cipher.getInstance(DEFAULT_CHIPHER_INSTANCE); // 算法/模式/填充
cp.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
return cp.doFinal(content);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
}
常见问题
java aes密钥长度限制
由于美国进出口限制,jre自带的aes算法限制了密钥长度为16字节。这时需要使用JCE无限制权限策略的jar包覆盖jvm自带的jar包。
下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
java 和 js互相加解密问题
java和js互相加解密时,如果不指定工作模式和填充方式,会失败。在js中,一般使用crypto-js库来加解密。但是该类库默认的工作模式是CBC
,默认填充方式PKCS7
,与java的默认方式不一致。
很多同学在使用AES算法时,不显示指定工作模式和填充方式,在这里就会屡屡出错。问题就出在java和js(crypto-js)默认的工作模式和填充方式不一致。这里只要将两者的工作模式和填充指定一样即可。
推荐一种方式:
js采用AES/CBC/ZeroPadding
方式加密。由于java没有提供ZeroPadding
填充方式,可以使用AES/CBC/NoPadding
方式解密,解密后从后往前依次剔除0x00
的字节,遇到非0x00
的字节时停止。剩下的字节就是解密后的结果。不过,这种方式需要注意,原始文本转byte数组后,最后一个字节不能是0x00
。如果是java加密,js解密,将过程反过来即可。