0%

Windows和Linux进行AES结果不同

前言

项目使用到了AES加解密,本地Windows环境测试没有问题,放到生产Linux(Centos7)环境后加解密结果不一致导致程序错误的问题

解决方案

经过检查之后,发现有一点比较奇怪的是linux下每次加密同一字符串出来的结果都不同,于是就怀疑应该是加密的Key这里出了问题,导致每次的加密结果不同,代码如下:

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
/**
* 生成加密秘钥
*
* @return
*/
private static SecretKeySpec getSecretKey(final String password)
{
//返回生成指定算法密钥生成器的 KeyGenerator 对象
KeyGenerator kg = null;
try
{
kg = KeyGenerator.getInstance(KEY_ALGORITHM);
//AES 要求密钥长度为 128
kg.init(128, new SecureRandom(password.getBytes()));
//生成一个密钥
SecretKey secretKey = kg.generateKey();
return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
}
catch (NoSuchAlgorithmException ex)
{
Logger.getLogger(AesEncryptUtils.class.getName()).log(Level.SEVERE, null, ex);
}

return null;
}

修改为如下方式即可解决问题:

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
/**
* 生成加密秘钥
*
* @return
*/
private static SecretKeySpec getSecretKey(final String password)
{
//返回生成指定算法密钥生成器的 KeyGenerator 对象
KeyGenerator kg = null;
try
{
kg = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes());
//AES 要求密钥长度为 128
kg.init(128, secureRandom);
//生成一个密钥
SecretKey secretKey = kg.generateKey();
return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
}
catch (NoSuchAlgorithmException ex)
{
Logger.getLogger(AesEncryptUtils.class.getName()).log(Level.SEVERE, null, ex);
}

return null;
}

原因分析

查询资料后发现是:kg.init(128, new SecureRandom(password.getBytes())); 这一段代码有问题。

SecureRandom 实现完全随操作系统本身的内部状态,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法;改实现在Windows上每次生成的Key都相同,但是在 Solaris 或部分 Linux系统上则不同;


最后附上AesEncryptUtils工具类

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
103
104
105
106
107
108
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AesEncryptUtils
{
private static final String KEY_ALGORITHM = "AES";
private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算法

/**
* 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(StandardCharsets.UTF_8);
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化为加密模式的密码器
byte[] result = cipher.doFinal(byteContent);// 加密
return Base64.encodeBase64String(result);//通过Base64转码返回
}
catch (Exception ex)
{
Logger.getLogger(AesEncryptUtils.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(Base64.decodeBase64(content));
return new String(result, StandardCharsets.UTF_8);
}
catch (Exception ex)
{
Logger.getLogger(AesEncryptUtils.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}

/**
* 生成加密秘钥
*
* @return
*/
private static SecretKeySpec getSecretKey(final String password)
{
//返回生成指定算法密钥生成器的 KeyGenerator 对象
KeyGenerator kg = null;
try
{
kg = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(password.getBytes());
//AES 要求密钥长度为 128
kg.init(128, secureRandom);
//生成一个密钥
SecretKey secretKey = kg.generateKey();
return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
}
catch (NoSuchAlgorithmException ex)
{
Logger.getLogger(AesEncryptUtils.class.getName()).log(Level.SEVERE, null, ex);
}

return null;
}

public static void main(String[] args)
{
String s = "20191127120752-833";

System.out.println("s:" + s);

String s1 = AesEncryptUtils.encrypt(s, "b8e7f17e785f450e");
System.out.println("s1:" + s1);

System.out.println("s2:" + AesEncryptUtils.decrypt(s1, "b8e7f17e785f450e"));
}
}
-------------The End-------------
坚持原创技术分享,您的支持将鼓励我继续创作!