Fork me on GitHub
0%

Linux 系统下 AES 解密报错问题

前两天在开发中遇到一个问题,就是一个服务部署在 Window 系统上的,而另一个服务部署在 Linux 系统上,Linux 系统上的服务需要通过 WebService 向 Window 系统上的服务获取数据,而这个数据是经过 AES 加密的,获取到密文之后需要进行解密,然后拿到解密之后的数据进行处理,但是在 Linux 系统服务上进行解密时却报错了,下面就是报错信息。

解密时报错信息

遇到错误第一时间找度娘 ( 其实应该找 Google ),结果发现原来是操作系统的原因,Linux 系统下在进行 AES 加解密时生成 key 时是有问题的,key 值的生成方式如下:

1
2
3
4
KeyGenerator generator = KeyGenerator.getInstance("AES");
//password 为加解密使用的密钥
generator.init(128, new SecureRandom(password.getBytes()));
Key key = generator.generateKey();

SecureRandom 的实现尝试完全随机化生成器本身的内部状态,因此随操作系统本身的內部状态而定,该实现在 windows 上每次生成的 key 都相同,但是在 linux 系统上则不同,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法,将上述生成 key 值的方式改为如下:

1
2
3
4
5
6
7
KeyGenerator generator = KeyGenerator.getInstance("AES");
//generator.init(128, new SecureRandom(password.getBytes()));
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
//password 为加解密使用的密钥
secureRandom.setSeed(password.getBytes());
generator.init(128, secureRandom);
Key key = generator.generateKey();

上面只是修改了 key 值的生成方式,这样就能够避免在 Linux 系统上加解密失败的错误了。完整的 AES 加解密工具类如下:

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
100
101
102
package com.ecjtu.common.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
* @author zhouxh
*/
public class AesEncodeUtil {

public static void main(String[] args) {

String content = "www.baidu.com";
String pwd = "ecjtu";

System.out.println("加密前content:" + content);
// 加密
String enContent = encodeByAes(content, pwd);
System.out.println("加密后content:" + enContent);

// 解密
String deContent = decodeByAes(enContent, pwd);
System.out.println("解密后content:" + deContent);
}

/**
* 加密
*
* @param content 待加密内容
* @param password 加密密钥
* @return
*/
public static String encodeByAes(String content, String password) {
Key key = generateKey(password);
BASE64Encoder base64en = new BASE64Encoder();
try {
// 创建密码器
Cipher cipher = Cipher.getInstance("AES");
byte[] byteContent = content.getBytes("utf-8");
// 初始化
cipher.init(Cipher.ENCRYPT_MODE, key);
// 加密
content = base64en.encode(cipher.doFinal(byteContent));
} catch (Exception e) {
e.printStackTrace();
}
return content;
}

/**
* 解密
*
* @param content 待解密内容
* @param password 解密密钥
* @return
*/
public static String decodeByAes(String content, String password) {
Key key = generateKey(password);
BASE64Decoder base64de = new BASE64Decoder();
try {
byte[] byteContent = base64de.decodeBuffer(content);
// 创建密码器
Cipher cipher = Cipher.getInstance("AES");
// 初始化
cipher.init(Cipher.DECRYPT_MODE, key);
// 解密
content = new String(cipher.doFinal(byteContent), "UTF8");
} catch (Exception e) {
e.printStackTrace();
}
return content;
}

/**
* 根据密钥生成加解密使用的 key 值
*
* @param password 加解密密钥
* @return
*/
public static Key generateKey(String password) {
Key key = null;
try {
KeyGenerator generator = KeyGenerator.getInstance("AES");
//下面这种方式在 Linux 系统下会报错
//generator.init(128, new SecureRandom(password.getBytes()));
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes());
generator.init(128, secureRandom);
key = generator.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return key;
}
}

 wechat
扫描上面图中二维码关注微信公众号