0%

RSA非对称加密案例

文章字数:777,阅读全文大约需要3分钟

封装了一个小工具

环境

  1. jdk1.8

  2. maven依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>

思路

  1. 私钥和公钥这两个对象都有加密和解密的动作,于是定义一个接口 CryptographicProcessor。私钥和公钥都继承这个接口,并实现相应加密和解密动作。

  2. 工具类SecurityUtils有三个功能: 随机生成秘钥对、获取私钥处理类、获取公钥处理类。

  3. 具体流程就是:

1
2
3
1. 使用SecurityUtils的静态方法生成一个Map,里面是私钥加公钥。
2. 使用SecurityUtils的静态方法传入私钥获取私钥处理器,这个处理器可以使用私钥加密和解密。
3. 把密文和公钥发给其他人,再使用公钥处理器解密,使用公钥加密返回信息,再用私钥解密返回的信息。
  1. 无论是秘钥还是明文密文,都是byte[]类型。为了方便base64转换成了String,传入值是String的都是会自动Base64

代码

操作接口

公钥和秘钥处理器都有加密解密的方法

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
/**
* @author colin.cheng
* @date
*/
public interface CryptographicProcessor {
/**
* 加密
*
* @param str
* 原信息
* @return 密文
* @throws Exception
*/
String encode(String str) throws Exception;

byte[] encode(byte[] strs) throws Exception;

/**
* 解密
*
* @param str
* 密文
* @return 原信息
* @throws Exception
*/
String decode(String str) throws Exception;

byte[] decode(byte[] strs) throws Exception;
}

##工具类

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

import org.apache.commons.codec.binary.Base64;

/**
* @author colin.cheng
* @date
*/
public class SecurityUtils {

/**
* 随机生成的秘钥Map中公钥的key
*/
static final String RSA_KEY_PUBLIC = "public";

/**
* 随机生成的秘钥Map中私钥的key
*/
static final String RSA_KEY_PRIVATE = "private";

private SecurityUtils() {}

/**
* 获取公钥处理器
*
* @param rSAPublicKey
* base64公钥
* @return 处理器对象
* @throws Exception
*/
public static CryptographicProcessor getRSAPublicKeyProcessor(String rSAPublicKey) throws Exception {
return new RSAPublicKeyProcessor(rSAPublicKey);
}

/**
* 获取公钥处理器
*
* @param rSAPublicKeyBytes
* 公钥byte数组
* @return 处理器对象
* @throws Exception
*/
public static CryptographicProcessor getRSAPublicKeyProcessor(byte[] rSAPublicKeyBytes) throws Exception {
return new RSAPublicKeyProcessor(rSAPublicKeyBytes);
}

/**
* 获取私钥处理器
*
* @param rSAPrivateKey
* base64私钥
* @return 处理器对象
* @throws Exception
*/
public static CryptographicProcessor getRSAPrivateKeyProcessor(String rSAPrivateKey) throws Exception {
return new RSAPrivateKeyProcessor(rSAPrivateKey);
}

/**
* 获取私钥处理器
*
* @param rSAPrivateKeyBytes
* 私钥byte数组
* @return 处理器对象
* @throws Exception
*/
public static CryptographicProcessor getRSAPrivateKeyProcessor(byte[] rSAPrivateKeyBytes) throws Exception {
return new RSAPrivateKeyProcessor(rSAPrivateKeyBytes);
}

/**
* 生成生成base64秘钥秘钥 明文最大长度不能大于秘钥长度 默认大小512byte
*
* @return
* @throws NoSuchAlgorithmException
*/
public static Map<String, String> generateRSAKeyPair() throws NoSuchAlgorithmException {
return generateRSAKeyPair(512);
}

/**
* 生成base64秘钥 明文最大长度不能大于秘钥长度
*
* @param keySize
* 秘钥大小
* @return
* @throws NoSuchAlgorithmException
*/
public static Map<String, String> generateRSAKeyPair(int keySize) throws NoSuchAlgorithmException {
Map<String, String> keyPairMap = new HashMap<>();
KeyPair keyPair = getKeyPair(keySize);
keyPairMap.put(SecurityUtils.RSA_KEY_PUBLIC, Base64.encodeBase64String(keyPair.getPrivate().getEncoded()));
keyPairMap.put(SecurityUtils.RSA_KEY_PRIVATE, Base64.encodeBase64String(keyPair.getPrivate().getEncoded()));
return keyPairMap;
}

/**
* 生成秘钥 明文最大长度不能大于秘钥长度
*
* @param keySize
* 秘钥大小
* @return
* @throws NoSuchAlgorithmException
*/
public static Map<String, byte[]> generateRSAKeyBytePair(int keySize) throws NoSuchAlgorithmException {
Map<String, byte[]> keyPairMap = new HashMap<>();
KeyPair keyPair = getKeyPair(keySize);
keyPairMap.put(SecurityUtils.RSA_KEY_PUBLIC, keyPair.getPublic().getEncoded());
keyPairMap.put(SecurityUtils.RSA_KEY_PRIVATE, keyPair.getPrivate().getEncoded());
return keyPairMap;
}

private static KeyPair getKeyPair(int keySize) throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize);
return keyPairGenerator.generateKeyPair();
}

// -------------class----------------

static class RSAPublicKeyProcessor implements CryptographicProcessor {

private X509EncodedKeySpec x509EncodedKeySpec;
private KeyFactory keyFactory;
private PublicKey publicKey;
private Cipher cipher;

private RSAPublicKeyProcessor(String rSAPublicKey) throws Exception {
this(Base64.decodeBase64(rSAPublicKey));
}

private RSAPublicKeyProcessor(byte[] rSAPublicKeyBytes) throws Exception {
this.x509EncodedKeySpec = new X509EncodedKeySpec(rSAPublicKeyBytes);
this.keyFactory = KeyFactory.getInstance("RSA");
this.cipher = Cipher.getInstance("RSA");
this.publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
}

@Override
public String encode(String str) throws Exception {
byte[] result = encode(str.getBytes());
return Base64.encodeBase64String(result);
}

@Override
public byte[] encode(byte[] strs) throws Exception {
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(strs);
}

@Override
public String decode(String str) throws Exception {
byte[] result = decode(Base64.decodeBase64(str));
return new String(result);
}

@Override
public byte[] decode(byte[] strs) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(strs);
}
}

static class RSAPrivateKeyProcessor implements CryptographicProcessor {

private PKCS8EncodedKeySpec pkcs8EncodedKeySpec;
private KeyFactory keyFactory;
private PrivateKey privateKey;
private Cipher cipher;

private RSAPrivateKeyProcessor(String rSAPrivate)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException {
this(Base64.decodeBase64(rSAPrivate));
}

private RSAPrivateKeyProcessor(byte[] rSAPrivateBytes)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException {
this.pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rSAPrivateBytes);
this.keyFactory = KeyFactory.getInstance("RSA");
this.privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
this.cipher = Cipher.getInstance("RSA");
}

@Override
public byte[] encode(byte[] strs) throws Exception {
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(strs);
return result;
}

@Override
public String encode(String str) throws Exception {
byte[] result = encode(str.getBytes());
return Base64.encodeBase64String(result);
}

@Override
public byte[] decode(byte[] strs) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(strs);
return result;
}

@Override
public String decode(String str) throws Exception {
byte[] result = decode(Base64.decodeBase64(str));
return new String(result);
}
}
}

测试

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
/**
* @author colin.cheng
* @date
*/
import java.util.Map;

public class security {

public static void main(String[] args) {
try {
String mess = "哈哈哈";
//秘钥对
Map<String, byte[]> keyPair = SecurityUtils.generateRSAKeyBytePair(512);
//私钥处理器
CryptographicProcessor privateProcessor =
SecurityUtils.getRSAPrivateKeyProcessor(keyPair.get(SecurityUtils.RSA_KEY_PRIVATE));
//加密的到密文
String cipherText = privateProcessor.encode(mess);
//假装发给别人
String res = sendMess(cipherText, keyPair.get(SecurityUtils.RSA_KEY_PUBLIC));
//私钥解密公钥加密的密文
System.out.println("客户端收到回复:"+privateProcessor.decode(res));
} catch (Exception e) {
// 创建失败
e.printStackTrace();
}
}

public static String sendMess(String mess, byte[] publicKey) throws Exception {
//根据拿到的公钥生成公钥处理器,网络传输可以生成string类型的秘钥。
CryptographicProcessor publicProce = SecurityUtils.getRSAPublicKeyProcessor(publicKey);
//解密
System.out.println("服务端收到:" + publicProce.decode(mess));
//加密一个返回值
return publicProce.encode("200");
}
}

结果

1
2
服务端收到:哈哈哈
客户端收到回复:200