码迷,mamicode.com
首页 > 编程语言 > 详细

RSA加密算法

时间:2017-09-20 11:59:15      阅读:300      评论:0      收藏:0      [点我收藏+]

标签:for   生成密钥   big   false   name   void   密钥   creat   cto   

  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 }

 

RSA加密算法

标签:for   生成密钥   big   false   name   void   密钥   creat   cto   

原文地址:http://www.cnblogs.com/zanderblogs/p/7560378.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!