非对称加密RSA工具类-RSAUtil.class

非对称加密RSA工具类-RSAUtil.class

RSA加解密工具类,如果使用模数的指数来生成公钥和私钥时,建议重新生成自己的模数和公钥指数、私钥指数。可取消 main 方法注释运行生成。

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
import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

/**
* @name: RSAUtil
* @desc: RSA 加解密工具类
**/
public class RSAUtil {

public static final String RSA = "RSA";
public static final int KEY_SIZE = 1024;
/*模数*/
public static String MODULUS = "";
/*公钥指数*/
public static String PUBLIC_EXPONENT = "";
/*私钥指数*/
public static String PRIVATE_EXPONENT = "";

/**
* 公钥加密
*
* @param data 明文
* @return String 密文
* @throws Exception Exception
*/
public static String encryptByPublicKey(String data) throws Exception {
RSAPublicKey publicKey = getPublicKey(MODULUS, PUBLIC_EXPONENT);
return encryptByPublicKey(data, publicKey);
}

/**
* 公钥加密
*
* @param data 明文
* @param publicKey 公钥
* @return String 密文
* @throws Exception Exception
*/
public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 模长
int key_len = publicKey.getModulus().bitLength() / 8;
// 加密数据长度 <= 模长-11
String[] datas = splitString(data, key_len - 11);
StringBuilder sb = new StringBuilder();
// 如果明文长度大于模长-11则要分组加密
for (String s : datas) {
sb.append(bcd2Str(cipher.doFinal(s.getBytes())));
}
return sb.toString();
}

/**
* 私钥解密
*
* @param data 密文
* @return String 明文
* @throws Exception Exception
*/
public static String decryptByPrivateKey(String data) throws Exception {
RSAPrivateKey privateKey = getPrivateKey(MODULUS, PRIVATE_EXPONENT);
return decryptByPrivateKey(data, privateKey);
}

/**
* 私钥解密
*
* @param data 密文
* @param privateKey 私钥
* @return String 明文
* @throws Exception Exception
*/
public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// 模长
int key_len = privateKey.getModulus().bitLength() / 8;
byte[] bytes = data.getBytes();
byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
// 如果密文长度大于模长则要分组解密
StringBuilder sb = new StringBuilder();
byte[][] arrays = splitArray(bcd, key_len);
for (byte[] arr : arrays) {
sb.append(new String(cipher.doFinal(arr)));
}
return sb.toString();
}


/**
* 生成公钥和私钥对
*
* @return KeyPair
* @throws Exception Exception
*/
public static RSAKeyPair genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
keyPairGen.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
return new RSAKeyPair(publicKey, privateKey);
}

/**
* 使用模和指数生成RSA公钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @return RSAPublicKey
* @throws Exception Exception
*/
public static RSAPublicKey getPublicKey() throws Exception {
return getPublicKey(MODULUS, PUBLIC_EXPONENT);
}

/**
* 使用模和指数生成RSA公钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus 模
* @param exponent 指数
* @return RSAPublicKey
* @throws Exception Exception
*/
public static RSAPublicKey getPublicKey(String modulus, String exponent) throws Exception {
BigInteger b1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
}

/**
* 使用模和指数生成RSA私钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @return RSAPrivateKey
* @throws Exception Exception
*/
public static RSAPrivateKey getPrivateKey() throws Exception {
return getPrivateKey(MODULUS, PRIVATE_EXPONENT);
}

/**
* 使用模和指数生成RSA私钥
* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
* /None/NoPadding】
*
* @param modulus 模
* @param exponent 指数
* @return RSAPrivateKey
* @throws Exception Exception
*/
public static RSAPrivateKey getPrivateKey(String modulus, String exponent) throws Exception {
BigInteger b1 = new BigInteger(modulus);
BigInteger b2 = new BigInteger(exponent);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
}

/**
* ASCII码转BCD码
*/
public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
byte[] bcd = new byte[asc_len / 2];
int j = 0;
for (int i = 0; i < (asc_len + 1) / 2; i++) {
bcd[i] = asc_to_bcd(ascii[j++]);
bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
}
return bcd;
}

public static byte asc_to_bcd(byte asc) {
byte bcd;

if ((asc >= '0') && (asc <= '9'))
bcd = (byte) (asc - '0');
else if ((asc >= 'A') && (asc <= 'F'))
bcd = (byte) (asc - 'A' + 10);
else if ((asc >= 'a') && (asc <= 'f'))
bcd = (byte) (asc - 'a' + 10);
else
bcd = (byte) (asc - 48);
return bcd;
}

/**
* BCD转字符串
*/
public static String bcd2Str(byte[] bytes) {
char temp[] = new char[bytes.length * 2], val;

for (int i = 0; i < bytes.length; i++) {
val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');

val = (char) (bytes[i] & 0x0f);
temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
}
return new String(temp);
}

/**
* 拆分字符串
*/
public static String[] splitString(String string, int len) {
int x = string.length() / len;
int y = string.length() % len;
int z = 0;
if (y != 0) {
z = 1;
}
String[] strings = new String[x + z];
String str = "";
for (int i = 0; i < x + z; i++) {
if (i == x + z - 1 && y != 0) {
str = string.substring(i * len, i * len + y);
} else {
str = string.substring(i * len, i * len + len);
}
strings[i] = str;
}
return strings;
}

/**
* 拆分数组
*/
public static byte[][] splitArray(byte[] data, int len) {
int x = data.length / len;
int y = data.length % len;
int z = 0;
if (y != 0) {
z = 1;
}
byte[][] arrays = new byte[x + z][];
byte[] arr;
for (int i = 0; i < x + z; i++) {
arr = new byte[len];
if (i == x + z - 1 && y != 0) {
System.arraycopy(data, i * len, arr, 0, y);
} else {
System.arraycopy(data, i * len, arr, 0, len);
}
arrays[i] = arr;
}
return arrays;
}

/**
* @desc RSA公钥私钥对
* @date 2021/12/29 17:08
*/
public static class RSAKeyPair {
/**
* 公钥
*/
private RSAPublicKey publicKey;
/**
* 私钥
*/
private RSAPrivateKey privateKey;

public RSAKeyPair() {
}

public RSAKeyPair(RSAPublicKey publicKey, RSAPrivateKey privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
}

public RSAPublicKey getPublicKey() {
return publicKey;
}

public void setPublicKey(RSAPublicKey publicKey) {
this.publicKey = publicKey;
}

public RSAPrivateKey getPrivateKey() {
return privateKey;
}

public void setPrivateKey(RSAPrivateKey privateKey) {
this.privateKey = privateKey;
}
}

public static void main(String[] args) throws Exception {

// KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
// generator.initialize(1024);
// KeyPair pair = generator.generateKeyPair();
// RSAPrivateKey privateKey = (RSAPrivateKey) pair.getPrivate();
// RSAPublicKey publicKey = (RSAPublicKey) pair.getPublic();
// System.out.println("publicKey exponent:" + publicKey.getPublicExponent());
// System.out.println("publicKey modules:" + publicKey.getModulus());
// System.out.println("publicKey format:" + publicKey.getFormat());
// System.out.println("---------------------分割线-------------------------");
// System.out.println("privateKey exponent:" + privateKey.getPrivateExponent());
// System.out.println("privateKey modules:" + privateKey.getModulus());
// System.out.println("privateKey format:" + privateKey.getFormat());

// RSAKeyPair rsaKeyPair = genKeyPair();
// RSAPublicKey publicKey = rsaKeyPair.getPublicKey();
// RSAPrivateKey privateKey = rsaKeyPair.getPrivateKey();
// //模
// String MODULUS = publicKey.getModulus().toString();
// System.err.println("模数:" + MODULUS);
// //公钥指数
// String PUBLIC_EXPONENT = publicKey.getPublicExponent().toString();
// System.err.println("公钥指数:" + PUBLIC_EXPONENT);
// //私钥指数
// String PRIVATE_EXPONENT = privateKey.getPrivateExponent().toString();
// System.err.println("私钥指数:" + PRIVATE_EXPONENT);
// //明文
// String ming = "Hello World";
// //使用模和指数生成公钥和私钥
// RSAPublicKey pubKey = RSAUtil.getPublicKey(MODULUS, PUBLIC_EXPONENT);
// RSAPrivateKey priKey = RSAUtil.getPrivateKey(MODULUS, PRIVATE_EXPONENT);
//
// //加密后的密文
// String mi = RSAUtil.encryptByPublicKey(ming, pubKey);
// System.err.println("加密后:" + mi);
// //解密后的明文
// ming = RSAUtil.decryptByPrivateKey(mi, priKey);
// System.err.println("解密后:" + ming);

}
}

非对称加密RSA工具类-RSAUtil.class

http://blog.gxitsky.com/2019/05/28/Utils-RSAUtil/

作者

光星

发布于

2019-05-28

更新于

2022-06-17

许可协议

评论