1 import java.io.File;
2 import java.io.FileInputStream;
3 import java.io.FileOutputStream;
4 import java.io.ObjectInputStream;
5 import java.io.ObjectOutputStream;
6 import java.math.BigInteger;
7 import java.security.InvalidParameterException;
8 import java.security.KeyFactory;
9 import java.security.KeyPair;
10 import java.security.KeyPairGenerator;
11 import java.security.NoSuchAlgorithmException;
12 import java.security.PrivateKey;
13 import java.security.Provider;
14 import java.security.PublicKey;
15 import java.security.SecureRandom;
16 import java.security.interfaces.RSAPrivateKey;
17 import java.security.interfaces.RSAPublicKey;
18 import java.security.spec.InvalidKeySpecException;
19 import java.security.spec.RSAPrivateKeySpec;
20 import java.security.spec.RSAPublicKeySpec;
21 import java.util.Date;
22
23 import javax.crypto.Cipher;
24
25 import org.apache.commons.codec.DecoderException;
26 import org.apache.commons.codec.binary.Hex;
27 import org.apache.commons.io.FileUtils;
28 import org.apache.commons.io.IOUtils;
29 import org.apache.commons.lang.StringUtils;
30 import org.apache.commons.lang.time.DateFormatUtils;
31 import org.bouncycastle.jce.provider.BouncyCastleProvider;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36 * RSA算法加密/解密工具类。
37 *
38 */
39 public abstract class RSAUtils {
40
41 /** 算法名称 */
42 private static final String ALGORITHOM = "RSA";
43
44 /** 默认的安全服务提供者 */
45 private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider();
46
47 /** 密钥大小 */
48 private static final int KEY_SIZE = 1024;
49
50 private static KeyFactory keyFactory = null;
51
52 private static KeyPairGenerator keyPairGen = null;
53
54 private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);
55
56 /** 缓存的密钥对。 */
57 private static KeyPair oneKeyPair = null;
58
59 /** 保存生成的密钥对的文件名称。 */
60 private static final String RSA_PAIR_FILENAME = "/_RSA_PAIR.txt";
61
62 private static File rsaPairFile = null;
63
64 static {
65 try {
66 RSAUtils.keyPairGen = KeyPairGenerator.getInstance(RSAUtils.ALGORITHOM,
67 RSAUtils.DEFAULT_PROVIDER);
68 RSAUtils.keyFactory = KeyFactory.getInstance(RSAUtils.ALGORITHOM,
69 RSAUtils.DEFAULT_PROVIDER);
70 }
71 catch (NoSuchAlgorithmException ex) {
72 RSAUtils.LOGGER.error(ex.getMessage());
73 }
74 RSAUtils.rsaPairFile = new File(RSAUtils.getRSAPairFilePath());
75 }
76
77 private RSAUtils() {
78 }
79
80 /**
81 * 使用指定的私钥解密数据。
82 *
83 * @param privateKey 给定的私钥。
84 * @param data 要解密的数据。
85 * @return 原数据。
86 */
87 public static byte[] decrypt(PrivateKey privateKey, byte[] data)
88 throws Exception {
89 Cipher ci =
90 Cipher.getInstance(RSAUtils.ALGORITHOM, RSAUtils.DEFAULT_PROVIDER);
91 ci.init(Cipher.DECRYPT_MODE, privateKey);
92 return ci.doFinal(data);
93 }
94
95 /**
96 * 使用给定的私钥解密给定的字符串。
97 * <p />
98 * 若私钥为 {@code null},或者 {@code encrypttext} 为 {@code null}或空字符串则返回
99 * {@code null}。
100 * 私钥不匹配时,返回 {@code null}。
101 *
102 * @param privateKey 给定的私钥。
103 * @param encrypttext 密文。
104 * @return 原文字符串。
105 */
106 public static String decryptString(PrivateKey privateKey,
107 String encrypttext) {
108 if (privateKey == null || StringUtils.isBlank(encrypttext)) {
109 return null;
110 }
111 try {
112 byte[] en_data = Hex.decodeHex(encrypttext.toCharArray());
113 byte[] data = RSAUtils.decrypt(privateKey, en_data);
114 return new String(data);
115 }
116 catch (Exception ex) {
117 RSAUtils.LOGGER.error(String.format("\"%s\" Decryption failed. Cause: %s",
118 encrypttext, ex.getCause().getMessage()));
119 }
120 return null;
121 }
122
123 /**
124 * 使用默认的私钥解密给定的字符串。
125 * <p />
126 * 若{@code encrypttext} 为 {@code null}或空字符串则返回 {@code null}。
127 * 私钥不匹配时,返回 {@code null}。
128 *
129 * @param encrypttext 密文。
130 * @return 原文字符串。
131 */
132 public static String decryptString(String encrypttext) {
133 if (StringUtils.isBlank(encrypttext)) {
134 return null;
135 }
136 KeyPair keyPair = RSAUtils.getKeyPair();
137 try {
138 byte[] en_data = Hex.decodeHex(encrypttext.toCharArray());
139 byte[] data = RSAUtils.decrypt(keyPair.getPrivate(), en_data);
140 return new String(data);
141 }
142 catch (NullPointerException ex) {
143 RSAUtils.LOGGER.error("keyPair cannot be null.");
144 }
145 catch (Exception ex) {
146 RSAUtils.LOGGER.error(String.format("\"%s\" Decryption failed. Cause: %s",
147 encrypttext, ex.getMessage()));
148 }
149 return null;
150 }
151
152 /**
153 * 使用默认的私钥解密由JS加密(使用此类提供的公钥加密)的字符串。
154 *
155 * @param encrypttext 密文。
156 * @return {@code encrypttext} 的原文字符串。
157 */
158 public static String decryptStringByJs(String encrypttext) {
159 String text = RSAUtils.decryptString(encrypttext);
160 if (text == null) {
161 return null;
162 }
163 return StringUtils.reverse(text);
164 }
165
166 /**
167 * 使用指定的公钥加密数据。
168 *
169 * @param publicKey 给定的公钥。
170 * @param data 要加密的数据。
171 * @return 加密后的数据。
172 */
173 public static byte[] encrypt(PublicKey publicKey, byte[] data)
174 throws Exception {
175 Cipher ci =
176 Cipher.getInstance(RSAUtils.ALGORITHOM, RSAUtils.DEFAULT_PROVIDER);
177 ci.init(Cipher.ENCRYPT_MODE, publicKey);
178 return ci.doFinal(data);
179 }
180
181 /**
182 * 使用给定的公钥加密给定的字符串。
183 * <p />
184 * 若 {@code publicKey} 为 {@code null},或者 {@code plaintext} 为 {@code null} 则返回
185 * {@code
186 * null}。
187 *
188 * @param publicKey 给定的公钥。
189 * @param plaintext 字符串。
190 * @return 给定字符串的密文。
191 */
192 public static String encryptString(PublicKey publicKey, String plaintext) {
193 if (publicKey == null || plaintext == null) {
194 return null;
195 }
196 byte[] data = plaintext.getBytes();
197 try {
198 byte[] en_data = RSAUtils.encrypt(publicKey, data);
199 return new String(Hex.encodeHex(en_data));
200 }
201 catch (Exception ex) {
202 RSAUtils.LOGGER.error(ex.getCause().getMessage());
203 }
204 return null;
205 }
206
207 /**
208 * 使用默认的公钥加密给定的字符串。
209 * <p />
210 * 若{@code plaintext} 为 {@code null} 则返回 {@code null}。
211 *
212 * @param plaintext 字符串。
213 * @return 给定字符串的密文。
214 */
215 public static String encryptString(String plaintext) {
216 if (plaintext == null) {
217 return null;
218 }
219 byte[] data = plaintext.getBytes();
220 KeyPair keyPair = RSAUtils.getKeyPair();
221 try {
222 byte[] en_data = RSAUtils.encrypt(keyPair.getPublic(), data);
223 return new String(Hex.encodeHex(en_data));
224 }
225 catch (NullPointerException ex) {
226 RSAUtils.LOGGER.error("keyPair cannot be null.");
227 }
228 catch (Exception ex) {
229 RSAUtils.LOGGER.error(ex.getCause().getMessage());
230 }
231 return null;
232 }
233
234 /**
235 * 根据给定的系数和专用指数构造一个RSA专用的私钥对象。
236 *
237 * @param modulus 系数。
238 * @param privateExponent 专用指数。
239 * @return RSA专用私钥对象。
240 */
241 public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,
242 byte[] privateExponent) {
243 RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(
244 new BigInteger(modulus), new BigInteger(privateExponent));
245 try {
246 return (RSAPrivateKey) RSAUtils.keyFactory
247 .generatePrivate(privateKeySpec);
248 }
249 catch (InvalidKeySpecException ex) {
250 RSAUtils.LOGGER.error("RSAPrivateKeySpec is unavailable.", ex);
251 }
252 catch (NullPointerException ex) {
253 RSAUtils.LOGGER.error(
254 "RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance.",
255 ex);
256 }
257 return null;
258 }
259
260 /**
261 * 根据给定的系数和专用指数构造一个RSA专用的公钥对象。
262 *
263 * @param modulus 系数。
264 * @param publicExponent 专用指数。
265 * @return RSA专用公钥对象。
266 */
267 public static RSAPublicKey generateRSAPublicKey(byte[] modulus,
268 byte[] publicExponent) {
269 RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(
270 new BigInteger(modulus), new BigInteger(publicExponent));
271 try {
272 return (RSAPublicKey) RSAUtils.keyFactory.generatePublic(publicKeySpec);
273 }
274 catch (InvalidKeySpecException ex) {
275 RSAUtils.LOGGER.error("RSAPublicKeySpec is unavailable.", ex);
276 }
277 catch (NullPointerException ex) {
278 RSAUtils.LOGGER.error(
279 "RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance.",
280 ex);
281 }
282 return null;
283 }
284
285 /** 返回已初始化的默认的私钥。 */
286 public static RSAPrivateKey getDefaultPrivateKey() {
287 KeyPair keyPair = RSAUtils.getKeyPair();
288 if (keyPair != null) {
289 return (RSAPrivateKey) keyPair.getPrivate();
290 }
291 return null;
292 }
293
294 /** 返回已初始化的默认的公钥。 */
295 public static RSAPublicKey getDefaultPublicKey() {
296 KeyPair keyPair = RSAUtils.getKeyPair();
297 if (keyPair != null) {
298 return (RSAPublicKey) keyPair.getPublic();
299 }
300 return null;
301 }
302
303 /**
304 * 返回RSA密钥对。
305 */
306 public static KeyPair getKeyPair() {
307 // 首先判断是否需要重新生成新的密钥对文件
308 if (RSAUtils.isCreateKeyPairFile()) {
309 // 直接强制生成密钥对文件,并存入缓存。
310 return RSAUtils.generateKeyPair();
311 }
312 if (RSAUtils.oneKeyPair != null) {
313 return RSAUtils.oneKeyPair;
314 }
315 return RSAUtils.readKeyPair();
316 }
317
318 public static PublicKeyMap getPublicKeyMap() {
319 PublicKeyMap publicKeyMap = new PublicKeyMap();
320 RSAPublicKey rsaPublicKey = RSAUtils.getDefaultPublicKey();
321 publicKeyMap.setModulus(
322 new String(Hex.encodeHex(rsaPublicKey.getModulus().toByteArray())));
323 publicKeyMap.setExponent(new String(
324 Hex.encodeHex(rsaPublicKey.getPublicExponent().toByteArray())));
325 return publicKeyMap;
326 }
327
328 /**
329 * 根据给定的16进制系数和专用指数字符串构造一个RSA专用的私钥对象。
330 *
331 * @param modulus 系数。
332 * @param privateExponent 专用指数。
333 * @return RSA专用私钥对象。
334 */
335 public static RSAPrivateKey getRSAPrivateKey(String hexModulus,
336 String hexPrivateExponent) {
337 if (StringUtils.isBlank(hexModulus)
338 || StringUtils.isBlank(hexPrivateExponent)) {
339 if (RSAUtils.LOGGER.isDebugEnabled()) {
340 RSAUtils.LOGGER.debug(
341 "hexModulus and hexPrivateExponent cannot be empty. RSAPrivateKey value is null to return.");
342 }
343 return null;
344 }
345 byte[] modulus = null;
346 byte[] privateExponent = null;
347 try {
348 modulus = Hex.decodeHex(hexModulus.toCharArray());
349 privateExponent = Hex.decodeHex(hexPrivateExponent.toCharArray());
350 }
351 catch (DecoderException ex) {
352 RSAUtils.LOGGER.error(
353 "hexModulus or hexPrivateExponent value is invalid. return null(RSAPrivateKey).");
354 }
355 if (modulus != null && privateExponent != null) {
356 return RSAUtils.generateRSAPrivateKey(modulus, privateExponent);
357 }
358 return null;
359 }
360
361 /**
362 * 根据给定的16进制系数和专用指数字符串构造一个RSA专用的公钥对象。
363 *
364 * @param modulus 系数。
365 * @param publicExponent 专用指数。
366 * @return RSA专用公钥对象。
367 */
368 public static RSAPublicKey getRSAPublidKey(String hexModulus,
369 String hexPublicExponent) {
370 if (StringUtils.isBlank(hexModulus)
371 || StringUtils.isBlank(hexPublicExponent)) {
372 if (RSAUtils.LOGGER.isDebugEnabled()) {
373 RSAUtils.LOGGER.debug(
374 "hexModulus and hexPublicExponent cannot be empty. return null(RSAPublicKey).");
375 }
376 return null;
377 }
378 byte[] modulus = null;
379 byte[] publicExponent = null;
380 try {
381 modulus = Hex.decodeHex(hexModulus.toCharArray());
382 publicExponent = Hex.decodeHex(hexPublicExponent.toCharArray());
383 }
384 catch (DecoderException ex) {
385 RSAUtils.LOGGER.error(
386 "hexModulus or hexPublicExponent value is invalid. return null(RSAPublicKey).");
387 }
388 if (modulus != null && publicExponent != null) {
389 return RSAUtils.generateRSAPublicKey(modulus, publicExponent);
390 }
391 return null;
392 }
393
394 /**
395 * 生成并返回RSA密钥对。
396 */
397 private static synchronized KeyPair generateKeyPair() {
398 try {
399 RSAUtils.keyPairGen.initialize(RSAUtils.KEY_SIZE, new SecureRandom(
400 DateFormatUtils.format(new Date(), "yyyyMMdd").getBytes()));
401 RSAUtils.oneKeyPair = RSAUtils.keyPairGen.generateKeyPair();
402 RSAUtils.saveKeyPair(RSAUtils.oneKeyPair);
403 return RSAUtils.oneKeyPair;
404 }
405 catch (InvalidParameterException ex) {
406 RSAUtils.LOGGER.error("KeyPairGenerator does not support a key length of "
407 + RSAUtils.KEY_SIZE + ".", ex);
408 }
409 catch (NullPointerException ex) {
410 RSAUtils.LOGGER.error(
411 "RSAUtils#KEY_PAIR_GEN is null, can not generate KeyPairGenerator instance.",
412 ex);
413 }
414 return null;
415 }
416
417 /**
418 * 返回生成/读取的密钥对文件的路径。
419 */
420 private static String getRSAPairFilePath() {
421 String urlPath = RSAUtils.class.getResource("/").getPath();
422 return new File(urlPath).getParent() + RSAUtils.RSA_PAIR_FILENAME;
423 }
424
425 /**
426 * 若需要创建新的密钥对文件,则返回 {@code true},否则 {@code false}。
427 */
428 private static boolean isCreateKeyPairFile() {
429 // 是否创建新的密钥对文件
430 boolean createNewKeyPair = false;
431 if (!RSAUtils.rsaPairFile.exists() || RSAUtils.rsaPairFile.isDirectory()) {
432 createNewKeyPair = true;
433 }
434 return createNewKeyPair;
435 }
436
437 // 同步读出保存的密钥对
438 private static KeyPair readKeyPair() {
439 FileInputStream fis = null;
440 ObjectInputStream ois = null;
441 try {
442 fis = FileUtils.openInputStream(RSAUtils.rsaPairFile);
443 ois = new ObjectInputStream(fis);
444 RSAUtils.oneKeyPair = (KeyPair) ois.readObject();
445 return RSAUtils.oneKeyPair;
446 }
447 catch (Exception ex) {
448 ex.printStackTrace();
449 }
450 finally {
451 IOUtils.closeQuietly(ois);
452 IOUtils.closeQuietly(fis);
453 }
454 return null;
455 }
456
457 /**
458 * 将指定的RSA密钥对以文件形式保存。
459 *
460 * @param keyPair 要保存的密钥对。
461 */
462 private static void saveKeyPair(KeyPair keyPair) {
463 FileOutputStream fos = null;
464 ObjectOutputStream oos = null;
465 try {
466 fos = FileUtils.openOutputStream(RSAUtils.rsaPairFile);
467 oos = new ObjectOutputStream(fos);
468 oos.writeObject(keyPair);
469 }
470 catch (Exception ex) {
471 ex.printStackTrace();
472 }
473 finally {
474 IOUtils.closeQuietly(oos);
475 IOUtils.closeQuietly(fos);
476 }
477 }
478 }
1 /**
2 * 存系数指数
3 *
4 */
5 public class PublicKeyMap {
6
7 private String exponent;
8
9 private String modulus;
10
11 public String getExponent() {
12 return this.exponent;
13 }
14
15 public String getModulus() {
16 return this.modulus;
17 }
18
19 public void setExponent(String exponent) {
20 this.exponent = exponent;
21 }
22
23 public void setModulus(String modulus) {
24 this.modulus = modulus;
25 }
26
27 @Override
28 public String toString() {
29 return "PublicKeyMap [modulus=" + this.modulus + ", exponent="
30 + this.exponent + "]";
31 }
32 }