1 import java.io.File;
2 import java.io.FileInputStream;
3 import java.math.BigInteger;
4 import java.security.KeyFactory;
5 import java.security.KeyPair;
6 import java.security.KeyPairGenerator;
7 import java.security.NoSuchAlgorithmException;
8 import java.security.NoSuchProviderException;
9 import java.security.Security;
10 import java.security.interfaces.RSAPrivateKey;
11 import java.security.interfaces.RSAPublicKey;
12 import java.security.spec.PKCS8EncodedKeySpec;
13 import java.security.spec.RSAPrivateKeySpec;
14 import java.security.spec.RSAPublicKeySpec;
15 import java.security.spec.X509EncodedKeySpec;
16 import java.util.HashMap;
17 import java.util.Map;
18
19 import javax.crypto.Cipher;
20
21 import org.apache.commons.codec.binary.Base64;
22 import org.apache.commons.lang.StringUtils;
23 import org.bouncycastle.jce.provider.BouncyCastleProvider;
24
27
28 /**
29 * 非对称加密工具
30 *
31 * @author lKF71480
32 */
33 public class RSAUtils { 36
37 /**
38 * PublicKey4UP:用户中心公钥匙
39 */
40 public static Map<String, Object> keyMap = new HashMap<String, Object>();
41
42 static {
43 try {
44 Security.addProvider(new BouncyCastleProvider());
45 } catch (Exception e) {
46 e.printStackTrace();
47 }
48 }
49
50 /**
51 * 生成公钥和私钥
52 *
53 * @throws NoSuchAlgorithmException
54 * @throws NoSuchProviderException
55 *
56 */
57 public static HashMap<String, Object> getKeys() throws NoSuchAlgorithmException, NoSuchProviderException {
58 HashMap<String, Object> map = new HashMap<String, Object>();
59 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA", "BC");
60 keyPairGen.initialize(1024);
61 KeyPair keyPair = keyPairGen.generateKeyPair();
62 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
63 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
64
65 map.put("public", publicKey);
66 map.put("private", privateKey);
67 return map;
68 }
69
70 /**
71 * 使用模和指数生成RSA公钥
72 * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
73 * /None/NoPadding】
74 *
75 * @param modulus
76 * 模
77 * @param exponent
78 * 指数
79 * @return
80 */
81 public static RSAPublicKey getPublicKey(String modulus, String exponent) {
82 try {
83 BigInteger b1 = new BigInteger(modulus);
84 BigInteger b2 = new BigInteger(exponent);
85 KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
86 RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
87 return (RSAPublicKey) keyFactory.generatePublic(keySpec);
88 } catch (Exception e) {
89 e.printStackTrace();
90 return null;
91 }
92 }
93
94 public static RSAPublicKey getPublicKey(X509EncodedKeySpec publicKey) {
95 try {
96 KeyFactory keyfactoryNew = KeyFactory.getInstance("RSA", "BC");
97 return (RSAPublicKey) keyfactoryNew.generatePublic(publicKey);
98 } catch (Exception e) {
99 e.printStackTrace();
100 return null;
101 }
102 }
103
104 /**
105 * 使用模和指数生成RSA私钥
106 * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
107 * /None/NoPadding】
108 * @param modulus 模
109 * @param exponent 指数
110 * @return
111 */
112 public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
113 try {
114 BigInteger b1 = new BigInteger(modulus);
115 BigInteger b2 = new BigInteger(exponent);
116 KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
117 RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
118 return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
119 } catch (Exception e) {
120 e.printStackTrace();
121 return null;
122 }
123 }
124
125 /**
126 * 公钥加密
127 *
128 * @param data
129 * @param publicKey
130 * @return
131 * @throws Exception
132 */
133 public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception {
134 Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
135 cipher.init(Cipher.ENCRYPT_MODE, publicKey);
136 // 模长
137 int key_len = publicKey.getModulus().bitLength() / 8;
138 // 加密数据长度 <= 模长-11
139 String[] datas = splitString(data, key_len - 11);
140 String mi = "";
141 // 如果明文长度大于模长-11则要分组加密
142 for (String s : datas) {
143 mi += bcd2Str(cipher.doFinal(s.getBytes()));
144 }
145 return mi;
146 }
147
148 /**
149 * 私钥解密
150 *
151 * @param data
152 * @param privateKey
153 * @return
154 * @throws Exception
155 */
156 public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception {
157 Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
158 cipher.init(Cipher.DECRYPT_MODE, privateKey);
159 // 模长
160 int key_len = privateKey.getModulus().bitLength() / 8;
161 byte[] bytes = data.getBytes();
162 byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
163 System.err.println(bcd.length);
164 // 如果密文长度大于模长则要分组解密
165 String ming = "";
166 byte[][] arrays = splitArray(bcd, key_len);
167 for (byte[] arr : arrays) {
168 ming += new String(cipher.doFinal(arr));
169 }
170 return ming;
171 }
172
173 /**
174 * 公钥解密
175 *
176 * @param data
177 * @param privateKey
178 * @return
179 * @throws Exception
180 */
181 public static String decryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception {
182 Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "BC");
183 cipher.init(Cipher.DECRYPT_MODE, publicKey);
184 // 模长
185 int key_len = publicKey.getModulus().bitLength() / 8;
186 byte[] bytes = data.getBytes();
187 byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
188 System.err.println(bcd.length);
189 // 如果密文长度大于模长则要分组解密
190 String ming = "";
191 byte[][] arrays = splitArray(bcd, key_len);
192 for (byte[] arr : arrays) {
193 ming += new String(cipher.doFinal(arr));
194 }
195 return ming;
196 }
197 /**
198 * <p>
199 * 解密
200 * </P>
201 * <功能详细描述>
202 *
203 * @return 解密后的明文
204 * @see [类、类#方法、类#成员]
205 */
206 public static String decrypt(String cryptStr) {
207 return null;
208 }
209
210 /**
211 * ASCII码转BCD码
212 *
213 */
214 public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
215 byte[] bcd = new byte[asc_len / 2];
216 int j = 0;
217 for (int i = 0; i < (asc_len + 1) / 2; i++) {
218 bcd[i] = asc_to_bcd(ascii[j++]);
219 bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
220 }
221 return bcd;
222 }
223
224 public static byte asc_to_bcd(byte asc) {
225 byte bcd;
226
227 if ((asc >= '0') && (asc <= '9'))
228 bcd = (byte) (asc - '0');
229 else if ((asc >= 'A') && (asc <= 'F'))
230 bcd = (byte) (asc - 'A' + 10);
231 else if ((asc >= 'a') && (asc <= 'f'))
232 bcd = (byte) (asc - 'a' + 10);
233 else
234 bcd = (byte) (asc - 48);
235 return bcd;
236 }
237
238 /**
239 * BCD转字符串
240 */
241 public static String bcd2Str(byte[] bytes) {
242 char temp[] = new char[bytes.length * 2], val;
243
244 for (int i = 0; i < bytes.length; i++) {
245 val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
246 temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
247
248 val = (char) (bytes[i] & 0x0f);
249 temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
250 }
251 return new String(temp);
252 }
253
254 /**
255 * 拆分字符串
256 */
257 public static String[] splitString(String string, int len) {
258 int x = string.length() / len;
259 int y = string.length() % len;
260 int z = 0;
261 if (y != 0) {
262 z = 1;
263 }
264 String[] strings = new String[x + z];
265 String str = "";
266 for (int i = 0; i < x + z; i++) {
267 if (i == x + z - 1 && y != 0) {
268 str = string.substring(i * len, i * len + y);
269 } else {
270 str = string.substring(i * len, i * len + len);
271 }
272 strings[i] = str;
273 }
274 return strings;
275 }
276
277 /**
278 * 拆分数组
279 */
280 public static byte[][] splitArray(byte[] data, int len) {
281 int x = data.length / len;
282 int y = data.length % len;
283 int z = 0;
284 if (y != 0) {
285 z = 1;
286 }
287 byte[][] arrays = new byte[x + z][];
288 byte[] arr;
289 for (int i = 0; i < x + z; i++) {
290 arr = new byte[len];
291 if (i == x + z - 1 && y != 0) {
292 System.arraycopy(data, i * len, arr, 0, y);
293 } else {
294 System.arraycopy(data, i * len, arr, 0, len);
295 }
296 arrays[i] = arr;
297 }
298 return arrays;
299 }
300
301 public static String getUpPrivateEncodeStr (String encodeStr) {
302 String result = "";
303 try {
304 RSAPrivateKey priKey = null;
305 if (keyMap.get("PrivateKey4UP") == null) {
306 String rootPath = StringUtils.remove(Thread.currentThread().getContextClassLoader().getResource("").getPath(), "classes/");
307 String localPath = rootPath + File.separator + "keystore";
308 File privateKeyFile = new File(localPath + File.separator + "private.key");
309 FileInputStream privateKeyInputStream = new FileInputStream(privateKeyFile);
310 byte[] privateKeyByte = new byte[(int) privateKeyFile.length()];
311 // 将私钥文件读入内存
312 privateKeyInputStream.read(privateKeyByte);
313 privateKeyInputStream.close();
314 // 生成私钥钥对象privateKey
315 PKCS8EncodedKeySpec priPKCS8new = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyByte));
316 KeyFactory keyfactoryNew = KeyFactory.getInstance("RSA", "BC");
317 priKey = (RSAPrivateKey) keyfactoryNew.generatePrivate(priPKCS8new);
318 keyMap.put("PrivateKey4UP", priKey);
319 } else {
320 priKey = (RSAPrivateKey) keyMap.get("PrivateKey4UP");
321 }
322 // 私钥解密
323 result = RSAUtils.decryptByPrivateKey(encodeStr, priKey);
324 } catch (Exception e) {
325 e.printStackTrace();
326 }
327 return result;
328 }
329
330 public static String getUpPublicEncodeStr(String str) {
331 // 公钥加密
332 String result = "";
333 try {
334 RSAPublicKey pubKey = null;
335 if (keyMap.get("PublicKey4UP") == null){
336 // 公钥文件
337 String rootPath = StringUtils.remove(Thread.currentThread().getContextClassLoader().getResource("").getPath(), "classes/");
338 String localPath = rootPath + File.separator + "keystore";
339 File publicKeyFile = new File(localPath + File.separator + "publicUp.key");
340 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
341 FileInputStream publicKeyInputStream = new FileInputStream(publicKeyFile);
342 byte[] publicKeyByte = new byte[(int) publicKeyFile.length()];
343 // 将公钥文件读入内存
344 publicKeyInputStream.read(publicKeyByte);
345 publicKeyInputStream.close();
346 // 生成公钥对象PublicKey
347 X509EncodedKeySpec pubX509new = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyByte));
348 KeyFactory keyfactoryNew = KeyFactory.getInstance("RSA", "BC");
349 pubKey = (RSAPublicKey) keyfactoryNew.generatePublic(pubX509new);
350 keyMap.put("PublicKey4UP", pubKey);
351 } else {
352 pubKey = (RSAPublicKey)keyMap.get("PublicKey4UP");
353 }
354 result = RSAUtils.encryptByPublicKey(str, pubKey);
355 } catch (Exception e) {
356 e.printStackTrace();
357 DEBUGGER.debug(e.getMessage());
358 }
359 return result;
360 }
361
362 /**
363 * 获取秘钥对文件
364 * @param args
365 * @throws Exception
366 */
367 public static void makeThePairFile(String[] args) throws Exception {
368
369 /*HashMap<String, Object> map = RSAUtils.getKeys();
370 // 生成公钥和私钥
371 RSAPublicKey publicKey = (RSAPublicKey) map.get("public");
372 RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");
373 // 生成公钥文件
374 File publicKeyFile = new File("D:" + File.separator + "public.key");
375 FileOutputStream publicKeyStream = new FileOutputStream(publicKeyFile);
376 // 获取公钥标准编码并进行base64加密
377 String publicKeyBase = new String(Base64.encodeBase64(publicKey.getEncoded()));
378 System.out.println("公钥为:" + new String(publicKey.getEncoded()));
379 System.out.println("BASE64公钥为:" + publicKeyBase);
380 publicKeyStream.write(publicKeyBase.getBytes());
381 publicKeyStream.close();
382 //
383 // // // 生成私钥文件
384 File privateKeyFile = new File("D:" + File.separator + "private.key");
385 FileOutputStream privateKeyStream = new FileOutputStream(privateKeyFile);
386 // 获取私钥标准编码并进行base64加密
387 String privateKeyBase = new String(Base64.encodeBase64(privateKey.getEncoded()));
388 System.out.println("私钥为:" + new String(privateKey.getEncoded()));
389 System.out.println("BASE64私钥为:" + privateKeyBase);
390 privateKeyStream.write(privateKeyBase.getBytes());
391 privateKeyStream.close();
392
393 X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyBase.getBytes()));
394 PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyBase.getBytes()));
395
396 KeyFactory keyfactory = KeyFactory.getInstance("RSA");
397 RSAPublicKey newPublicKey = (RSAPublicKey) keyfactory.generatePublic(pubX509);
398 RSAPrivateKey newPrivateKey = (RSAPrivateKey) keyfactory.generatePrivate(priPKCS8);
399 System.out.println(publicKey.equals(newPublicKey));
400 System.out.println(privateKey.equals(newPrivateKey));*/
401 }
402 }