-
Notifications
You must be signed in to change notification settings - Fork 1
/
RSAUtil.java
353 lines (332 loc) · 11.9 KB
/
RSAUtil.java
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
package cn.xanderye.util;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Cipher;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.*;
/**
* Created on 2020/5/19.
*
* @author XanderYe
*/
public class RSAUtil {
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
* 密钥算法
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 加解密算法/工作模式/填充方式
*/
public static final String KEY_ALGORITHM_STR = "RSA/ECB/PKCS1Padding";
/**
* 随机生成密钥对
*
* @param filePath
* @return void
* @author XanderYe
* @date 2020/5/19
*/
public static void genKeyPair(String filePath) throws IOException {
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
if (keyPairGen != null) {
// 初始化密钥对生成器,密钥大小为96-1024位
keyPairGen.initialize(1024, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 得到公钥字符串
String publicKeyString = CodecUtil.base64Encode(publicKey.getEncoded());
// 得到私钥字符串
String privateKeyString = CodecUtil.base64Encode(privateKey.getEncoded());
// 将密钥对写入到文件
FileWriter pubFw = new FileWriter(filePath + "/publicKey.keystore");
FileWriter priFw = new FileWriter(filePath + "/privateKey.keystore");
BufferedWriter pubBw = new BufferedWriter(pubFw);
BufferedWriter priBw = new BufferedWriter(priFw);
pubBw.write(publicKeyString);
priBw.write(privateKeyString);
pubBw.flush();
pubBw.close();
pubFw.close();
priBw.flush();
priBw.close();
priFw.close();
}
}
/**
* 从文件中加载公钥
*
* @param path
* @return java.security.interfaces.RSAPrivateKey
* @author XanderYe
* @date 2020/5/19
*/
public static RSAPublicKey loadPublicKeyByFile(String path) throws Exception {
BufferedReader br = new BufferedReader(new FileReader(path));
String readLine;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.charAt(0) != '-') {
sb.append(readLine);
}
}
br.close();
return loadPublicKeyByStr(sb.toString());
}
/**
* 从字符串中加载公钥
*
* @param publicKeyStr
* @return java.security.interfaces.RSAPublicKey
* @author XanderYe
* @date 2020/5/19
*/
public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
if (publicKeyStr != null) {
byte[] buffer = CodecUtil.base64DecodeToByteArray(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
}
return null;
}
/**
* 根据给定的16进制系数和专用指数字符串构造一个RSA专用的公钥
*
* @param hexModulus 十六进制系数
* @param hexPublicExponent 十六进制专用指数
* @return java.security.interfaces.RSAPublicKey
* @author XanderYe
* @date 2022/3/29
*/
public static RSAPublicKey generatePublicKey(String hexModulus, String hexPublicExponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
if(StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPublicExponent)) {
return null;
}
byte[] modulus = CodecUtil.hexStringToByteArray(hexModulus);
byte[] publicExponent = CodecUtil.hexStringToByteArray(hexPublicExponent);
return generatePublicKey(modulus, publicExponent);
}
/**
* 根据给定的系数和专用指数字符串构造一个RSA专用的公钥
*
* @param modulus 系数
* @param publicExponent 专用指数
* @return java.security.interfaces.RSAPublicKey
* @author XanderYe
* @date 2022/3/29
*/
public static RSAPublicKey generatePublicKey(byte[] modulus, byte[] publicExponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(modulus),
new BigInteger(publicExponent));
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
return (RSAPublicKey) keyFactory.generatePublic(publicKeySpec);
}
/**
* 从文件中加载私钥
*
* @param path
* @return java.security.interfaces.RSAPrivateKey
* @author XanderYe
* @date 2020/5/19
*/
public static RSAPrivateKey loadPrivateKeyByFile(String path) throws Exception {
BufferedReader br = new BufferedReader(new FileReader(path));
String readLine;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.charAt(0) != '-') {
sb.append(readLine);
}
}
br.close();
return loadPrivateKeyByStr(sb.toString());
}
/**
* 从字符串中加载私钥
*
* @param privateKeyStr
* @return java.security.interfaces.RSAPrivateKey
* @author XanderYe
* @date 2020/5/19
*/
public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException {
if (privateKeyStr != null) {
byte[] buffer = CodecUtil.base64DecodeToByteArray(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
}
return null;
}
/**
* 根据给定的16进制系数和专用指数字符串构造一个RSA专用的私钥
*
* @param hexModulus 十六进制系数
* @param hexPrivateExponent 十六进制专用指数
* @return java.security.interfaces.RSAPrivateKey
* @author XanderYe
* @date 2022/3/29
*/
public static RSAPrivateKey generatePrivateKey(String hexModulus, String hexPrivateExponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
if(StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPrivateExponent)) {
return null;
}
byte[] modulus = CodecUtil.hexStringToByteArray(hexModulus);
byte[] publicExponent = CodecUtil.hexStringToByteArray(hexPrivateExponent);
return generatePrivateKey(modulus, publicExponent);
}
/**
* 根据给定的系数和专用指数字符串构造一个RSA专用的私钥
*
* @param modulus 系数
* @param privateExponent 专用指数
* @return java.security.interfaces.RSAPrivateKey
* @author XanderYe
* @date 2022/3/29
*/
public static RSAPrivateKey generatePrivateKey(byte[] modulus, byte[] privateExponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus),
new BigInteger(privateExponent));
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
return (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);
}
/**
* 使用公钥加密
* @param plainTextData
* @param publicKey
* @return byte[]
* @author XanderYe
* @date 2020/5/19
*/
public static byte[] encrypt(String plainTextData, RSAPublicKey publicKey) throws Exception {
return encrypt(plainTextData.getBytes(StandardCharsets.UTF_8), publicKey);
}
/**
* 使用公钥加密
* @param plainTextData
* @param publicKey
* @return byte[]
* @author XanderYe
* @date 2020/5/19
*/
public static byte[] encrypt(byte[] plainTextData, RSAPublicKey publicKey) throws Exception {
if (publicKey == null) {
return null;
}
// 使用默认RSA
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_STR);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(plainTextData);
}
/**
* 使用私钥加密
* @param plainTextData
* @param privateKey
* @return byte[]
* @author XanderYe
* @date 2020/5/19
*/
public static byte[] encrypt(byte[] plainTextData, RSAPrivateKey privateKey) throws Exception {
if (privateKey == null) {
return null;
}
// 使用默认RSA
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_STR);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(plainTextData);
}
/**
* 使用私钥加密
* @param plainTextData
* @param privateKey
* @return byte[]
* @author XanderYe
* @date 2020/5/19
*/
public static byte[] encrypt(String plainTextData, RSAPrivateKey privateKey) throws Exception {
return encrypt(plainTextData.getBytes(StandardCharsets.UTF_8), privateKey);
}
/**
* 使用私钥解密
* @param cipherData
* @param privateKey
* @return byte[]
* @author XanderYe
* @date 2020/5/19
*/
public static byte[] decrypt(byte[] cipherData, RSAPrivateKey privateKey) throws Exception {
if (privateKey == null) {
return null;
}
// 使用默认RSA
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_STR);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(cipherData);
}
/**
* 使用公钥解密
* @param cipherData
* @param publicKey
* @return byte[]
* @author XanderYe
* @date 2020/5/19
*/
public static byte[] decrypt(byte[] cipherData, RSAPublicKey publicKey) throws Exception {
if (publicKey == null) {
return null;
}
// 使用默认RSA
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM_STR);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(cipherData);
}
/**
* 私钥签名
* @param data
* @param privateKey
* @return java.lang.String
* @author XanderYe
* @date 2021/12/21
*/
public static String sign(byte[] data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey);
signature.update(data);
return CodecUtil.base64Encode(signature.sign());
}
/**
* 公钥校验
* @param data
* @param publicKey
* @param sign
* @return boolean
* @author XanderYe
* @date 2021/12/21
*/
public static boolean verify(byte[] data, PublicKey publicKey, String sign) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(CodecUtil.base64DecodeToByteArray(sign));
}
}