Java使用RSA加密解密及签名校验

转载原文地址:http://www.cnblogs.com/linjiqin/p/6005626.html

根据原文的Base64工具包,自己做了修改:

1.导包:import it.sauronsoftware.base64.Base64;         自己没导这个包

2.工具包里报错的base64   一个是byte类型,修改成:  return Base64.getDecoder().decode(base64.getBytes());

            一个是String类型,修改成:return new String(Base64.getEncoder().encodeToString(bytes));

3.测试方法里面的 公钥加密 私钥解密   原文测试输出的加密文字是图片式的文字  传不了url里  所以自己改了下  可以去跟原文对比。

注意:
RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。
RSA加密对明文的长度是有限制的,如果加密数据过大会抛出如下异常:

1 Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes
2     at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
3     at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
4     at javax.crypto.Cipher.doFinal(DashoA13*..)

RSA.java--RSA公钥/私钥/签名工具包

  1 package com.rjs.util;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.security.Key;
  5 import java.security.KeyFactory;
  6 import java.security.KeyPair;
  7 import java.security.KeyPairGenerator;
  8 import java.security.PrivateKey;
  9 import java.security.PublicKey;
 10 import java.security.Signature;
 11 import java.security.interfaces.RSAPrivateKey;
 12 import java.security.interfaces.RSAPublicKey;
 13 import java.security.spec.PKCS8EncodedKeySpec;
 14 import java.security.spec.X509EncodedKeySpec;
 15 import java.util.HashMap;
 16 import java.util.Map;
 17 
 18 import javax.crypto.Cipher;
 19 
 20 /**
 21  * <p>
 22  * RSA公钥/私钥/签名工具包
 23  * </p>
 24  * <p>
 25  * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)
 26  * </p>
 27  * <p>
 28  * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
 29  * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
 30  * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
 31  * </p>
 32  * 
 33  * @author IceWee
 34  * @date 2012-4-26
 35  * @version 1.0
 36  */
 37 public class RSA {
 38 
 39     /**
 40      * 加密算法RSA
 41      */
 42     public static final String KEY_ALGORITHM = "RSA";
 43     
 44     /**
 45      * 签名算法
 46      */
 47     public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
 48 
 49     /**
 50      * 获取公钥的key
 51      */
 52     private static final String PUBLIC_KEY = "RSAPublicKey";
 53     
 54     /**
 55      * 获取私钥的key
 56      */
 57     private static final String PRIVATE_KEY = "RSAPrivateKey";
 58     
 59     /**
 60      * RSA最大加密明文大小
 61      */
 62     private static final int MAX_ENCRYPT_BLOCK = 117;
 63     
 64     /**
 65      * RSA最大解密密文大小
 66      */
 67     private static final int MAX_DECRYPT_BLOCK = 128;
 68 
 69     /**
 70      * <p>
 71      * 生成密钥对(公钥和私钥)
 72      * </p>
 73      * 
 74      * @return
 75      * @throws Exception
 76      */
 77     public static Map<String, Object> genKeyPair() throws Exception {
 78         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
 79         keyPairGen.initialize(1024);
 80         KeyPair keyPair = keyPairGen.generateKeyPair();
 81         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 82         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 83         Map<String, Object> keyMap = new HashMap<String, Object>(2);
 84         keyMap.put(PUBLIC_KEY, publicKey);
 85         keyMap.put(PRIVATE_KEY, privateKey);
 86         return keyMap;
 87     }
 88     
 89     /**
 90      * <p>
 91      * 用私钥对信息生成数字签名
 92      * </p>
 93      * 
 94      * @param data 已加密数据
 95      * @param privateKey 私钥(BASE64编码)
 96      * 
 97      * @return
 98      * @throws Exception
 99      */
100     public static String sign(byte[] data, String privateKey) throws Exception {
101         byte[] keyBytes = Base64Utils.decode(privateKey);
102         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
103         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
104         PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
105         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
106         signature.initSign(privateK);
107         signature.update(data);
108         return Base64Utils.encode(signature.sign());
109     }
110 
111     /**
112      * <p>
113      * 校验数字签名
114      * </p>
115      * 
116      * @param data 已加密数据
117      * @param publicKey 公钥(BASE64编码)
118      * @param sign 数字签名
119      * 
120      * @return
121      * @throws Exception
122      * 
123      */
124     public static boolean verify(byte[] data, String publicKey, String sign)
125             throws Exception {
126         byte[] keyBytes = Base64Utils.decode(publicKey);
127         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
128         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
129         PublicKey publicK = keyFactory.generatePublic(keySpec);
130         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
131         signature.initVerify(publicK);
132         signature.update(data);
133         return signature.verify(Base64Utils.decode(sign));
134     }
135 
136     /**
137      * <P>
138      * 私钥解密
139      * </p>
140      * 
141      * @param encryptedData 已加密数据
142      * @param privateKey 私钥(BASE64编码)
143      * @return
144      * @throws Exception
145      */
146     public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
147             throws Exception {
148         byte[] keyBytes = Base64Utils.decode(privateKey);
149         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
150         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
151         Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
152         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
153         cipher.init(Cipher.DECRYPT_MODE, privateK);
154         int inputLen = encryptedData.length;
155         ByteArrayOutputStream out = new ByteArrayOutputStream();
156         int offSet = 0;
157         byte[] cache;
158         int i = 0;
159         // 对数据分段解密
160         while (inputLen - offSet > 0) {
161             if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
162                 cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
163             } else {
164                 cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
165             }
166             out.write(cache, 0, cache.length);
167             i++;
168             offSet = i * MAX_DECRYPT_BLOCK;
169         }
170         byte[] decryptedData = out.toByteArray();
171         out.close();
172         return decryptedData;
173     }
174 
175     /**
176      * <p>
177      * 公钥解密
178      * </p>
179      * 
180      * @param encryptedData 已加密数据
181      * @param publicKey 公钥(BASE64编码)
182      * @return
183      * @throws Exception
184      */
185     public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
186             throws Exception {
187         byte[] keyBytes = Base64Utils.decode(publicKey);
188         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
189         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
190         Key publicK = keyFactory.generatePublic(x509KeySpec);
191         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
192         cipher.init(Cipher.DECRYPT_MODE, publicK);
193         int inputLen = encryptedData.length;
194         ByteArrayOutputStream out = new ByteArrayOutputStream();
195         int offSet = 0;
196         byte[] cache;
197         int i = 0;
198         // 对数据分段解密
199         while (inputLen - offSet > 0) {
200             if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
201                 cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
202             } else {
203                 cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
204             }
205             out.write(cache, 0, cache.length);
206             i++;
207             offSet = i * MAX_DECRYPT_BLOCK;
208         }
209         byte[] decryptedData = out.toByteArray();
210         out.close();
211         return decryptedData;
212     }
213 
214     /**
215      * <p>
216      * 公钥加密
217      * </p>
218      * 
219      * @param data 源数据
220      * @param publicKey 公钥(BASE64编码)
221      * @return
222      * @throws Exception
223      */
224     public static byte[] encryptByPublicKey(byte[] data, String publicKey)
225             throws Exception {
226         byte[] keyBytes = Base64Utils.decode(publicKey);
227         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
228         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
229         Key publicK = keyFactory.generatePublic(x509KeySpec);
230         // 对数据加密
231         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
232         cipher.init(Cipher.ENCRYPT_MODE, publicK);
233         int inputLen = data.length;
234         ByteArrayOutputStream out = new ByteArrayOutputStream();
235         int offSet = 0;
236         byte[] cache;
237         int i = 0;
238         // 对数据分段加密
239         while (inputLen - offSet > 0) {
240             if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
241                 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
242             } else {
243                 cache = cipher.doFinal(data, offSet, inputLen - offSet);
244             }
245             out.write(cache, 0, cache.length);
246             i++;
247             offSet = i * MAX_ENCRYPT_BLOCK;
248         }
249         byte[] encryptedData = out.toByteArray();
250         out.close();
251         return encryptedData;
252     }
253 
254     /**
255      * <p>
256      * 私钥加密
257      * </p>
258      * 
259      * @param data 源数据
260      * @param privateKey 私钥(BASE64编码)
261      * @return
262      * @throws Exception
263      */
264     public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
265             throws Exception {
266         byte[] keyBytes = Base64Utils.decode(privateKey);
267         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
268         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
269         Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
270         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
271         cipher.init(Cipher.ENCRYPT_MODE, privateK);
272         int inputLen = data.length;
273         ByteArrayOutputStream out = new ByteArrayOutputStream();
274         int offSet = 0;
275         byte[] cache;
276         int i = 0;
277         // 对数据分段加密
278         while (inputLen - offSet > 0) {
279             if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
280                 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
281             } else {
282                 cache = cipher.doFinal(data, offSet, inputLen - offSet);
283             }
284             out.write(cache, 0, cache.length);
285             i++;
286             offSet = i * MAX_ENCRYPT_BLOCK;
287         }
288         byte[] encryptedData = out.toByteArray();
289         out.close();
290         return encryptedData;
291     }
292 
293     /**
294      * <p>
295      * 获取私钥
296      * </p>
297      * 
298      * @param keyMap 密钥对
299      * @return
300      * @throws Exception
301      */
302     public static String getPrivateKey(Map<String, Object> keyMap)
303             throws Exception {
304         Key key = (Key) keyMap.get(PRIVATE_KEY);
305         return Base64Utils.encode(key.getEncoded());
306     }
307 
308     /**
309      * <p>
310      * 获取公钥
311      * </p>
312      * 
313      * @param keyMap 密钥对
314      * @return
315      * @throws Exception
316      */
317     public static String getPublicKey(Map<String, Object> keyMap)
318             throws Exception {
319         Key key = (Key) keyMap.get(PUBLIC_KEY);
320         return Base64Utils.encode(key.getEncoded());
321     }
322 
323 }

Base64Utils.java--BASE64编码解码工具包

  1 package com.rjs.util;
  2 
  3 import java.io.ByteArrayInputStream;
  4 import java.io.ByteArrayOutputStream;
  5 import java.io.File;
  6 import java.io.FileInputStream;
  7 import java.io.FileOutputStream;
  8 import java.io.InputStream;
  9 import java.io.OutputStream;
 10 import java.util.Base64;
 11 
 12 /*import it.sauronsoftware.base64.Base64;*/
 13 
 14 /**
 15  * <p>
 16  * BASE64编码解码工具包
 17  * </p>
 18  * <p>
 19  * 依赖javabase64-1.3.1.jar
 20  * </p>
 21  * 
 22  * @author IceWee
 23  * @date 2012-5-19
 24  * @version 1.0
 25  */
 26 public class Base64Utils {
 27 
 28     /**
 29      * 文件读取缓冲区大小
 30      */
 31     private static final int CACHE_SIZE = 1024;
 32 
 33     /**
 34      * <p>
 35      * BASE64字符串解码为二进制数据
 36      * </p>
 37      * 
 38      * @param base64
 39      * @return
 40      * @throws Exception
 41      */
 42     public static byte[] decode(String base64) throws Exception {
 43         return Base64.getDecoder().decode(base64.getBytes());
 44     }
 45 
 46     /**
 47      * <p>
 48      * 二进制数据编码为BASE64字符串
 49      * </p>
 50      * 
 51      * @param bytes
 52      * @return
 53      * @throws Exception
 54      */
 55     public static String encode(byte[] bytes) throws Exception {
 56         return new String(Base64.getEncoder().encodeToString(bytes));
 57     }
 58 
 59     /**
 60      * <p>
 61      * 将文件编码为BASE64字符串
 62      * </p>
 63      * <p>
 64      * 大文件慎用,可能会导致内存溢出
 65      * </p>
 66      * 
 67      * @param filePath
 68      *            文件绝对路径
 69      * @return
 70      * @throws Exception
 71      */
 72     public static String encodeFile(String filePath) throws Exception {
 73         byte[] bytes = fileToByte(filePath);
 74         return encode(bytes);
 75     }
 76 
 77     /**
 78      * <p>
 79      * BASE64字符串转回文件
 80      * </p>
 81      * 
 82      * @param filePath
 83      *            文件绝对路径
 84      * @param base64
 85      *            编码字符串
 86      * @throws Exception
 87      */
 88     public static void decodeToFile(String filePath, String base64) throws Exception {
 89         byte[] bytes = decode(base64);
 90         byteArrayToFile(bytes, filePath);
 91     }
 92 
 93     /**
 94      * <p>
 95      * 文件转换为二进制数组
 96      * </p>
 97      * 
 98      * @param filePath
 99      *            文件路径
100      * @return
101      * @throws Exception
102      */
103     public static byte[] fileToByte(String filePath) throws Exception {
104         byte[] data = new byte[0];
105         File file = new File(filePath);
106         if (file.exists()) {
107             FileInputStream in = new FileInputStream(file);
108             ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
109             byte[] cache = new byte[CACHE_SIZE];
110             int nRead = 0;
111             while ((nRead = in.read(cache)) != -1) {
112                 out.write(cache, 0, nRead);
113                 out.flush();
114             }
115             out.close();
116             in.close();
117             data = out.toByteArray();
118         }
119         return data;
120     }
121 
122     /**
123      * <p>
124      * 二进制数据写文件
125      * </p>
126      * 
127      * @param bytes
128      *            二进制数据
129      * @param filePath
130      *            文件生成目录
131      */
132     public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
133         InputStream in = new ByteArrayInputStream(bytes);
134         File destFile = new File(filePath);
135         if (!destFile.getParentFile().exists()) {
136             destFile.getParentFile().mkdirs();
137         }
138         destFile.createNewFile();
139         OutputStream out = new FileOutputStream(destFile);
140         byte[] cache = new byte[CACHE_SIZE];
141         int nRead = 0;
142         while ((nRead = in.read(cache)) != -1) {
143             out.write(cache, 0, nRead);
144             out.flush();
145         }
146         out.close();
147         in.close();
148     }
149 
150 }

RSATeste.java--测试类

 1 package com.rjs.util;
 2 
 3 import java.util.Map;
 4 
 5 public class RSATest {
 6 
 7     static String publicKey;
 8     static String privateKey;
 9 
10     static {
11         try {
12             Map<String, Object> keyMap = RSA.genKeyPair();
13             publicKey = RSA.getPublicKey(keyMap);
14             privateKey = RSA.getPrivateKey(keyMap);
15             System.err.println("公钥: \n\r" + publicKey);
16             System.err.println("私钥: \n\r" + privateKey);
17         } catch (Exception e) {
18             e.printStackTrace();
19         }
20     }
21     
22     
23     public static void main(String[] args) throws Exception {    
24         test();
25         testSign();
26         testHttpSign();
27     }
28 
29     static void test() throws Exception {    
30         String param = "id=1&name=张三";
31         byte[] encodedData = RSA.encryptByPrivateKey(param.getBytes(), privateKey);
32         System.out.println("加密后:" + encodedData);
33         
34         byte[] decodedData = RSA.decryptByPublicKey(encodedData, publicKey);
35         System.out.println("解密后:" + new String(decodedData));
36         
37         String sign = RSA.sign(encodedData, privateKey);
38         System.err.println("签名:" + sign);
39         
40         boolean status = RSA.verify(encodedData, publicKey, sign);
41         System.err.println("签名验证结果:" + status);
42     }
43 
44     static void testSign() throws Exception {
45         System.err.println("私钥加密——公钥解密");
46         String source = "这是一行测试RSA数字签名的无意义文字";
47         System.out.println("原文字:\r\n" + source);
48         byte[] data = source.getBytes();
49         byte[] encodedData = RSA.encryptByPrivateKey(data, privateKey);
50         System.out.println("加密后:\r\n" + new String(encodedData));
51         byte[] decodedData = RSA.decryptByPublicKey(encodedData, publicKey);
52         String target = new String(decodedData);
53         System.out.println("解密后: \r\n" + target);
54         System.err.println("私钥签名——公钥验证签名");
55         String sign = RSA.sign(encodedData, privateKey);
56         System.err.println("签名:\r" + sign);
57         boolean status = RSA.verify(encodedData, publicKey, sign);
58         System.err.println("验证结果:\r" + status);
59     }
60 
    //原文的: 61 static void testHttpSign() throws Exception { 62 System.err.println("公钥加密——私钥解密"); 63 String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗?"; 64 System.out.println("\r加密前文字:\r\n" + source); 65 byte[] data = source.getBytes(); 66 byte[] encodedData = RSA.encryptByPublicKey(data, publicKey); 67 System.out.println("加密后文字:\r\n" + new String(encodedData)); 68 byte[] decodedData = RSA.decryptByPrivateKey(encodedData, privateKey); 69 String target = new String(decodedData); 70 System.out.println("解密后文字: \r\n" + target); 71 } 72 //修改后:
    

      static void testHttpSign() throws Exception {
      System.err.println("公钥加密——私钥解密");

      //自己加一个UUID,保证加密性
      UUID uuid = UUID.randomUUID();
      String id = uuid.toString().replaceAll("-", "");    //去除UUID的"-"符号

      long time = System.currentTimeMillis();
      String source = "25,18675647281,"+time;

      System.out.println("\r加密前文字:\r\n" + source);
      byte[] data = source.getBytes();
      byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);

      String target = Base64Utils.encode(encodedData);

      System.out.printf("加密后url:?id=%s&time=%s&v=%s \r\n", id ,time,target);

      byte[] decodedData = RSAUtils.decryptByPrivateKey(Base64Utils.decode(target), privateKey);

      System.out.println("解密后文字: \r\n" + new String(decodedData));
}

73 }

 

posted @ 2017-09-07 09:30  还行吗年轻人  阅读(3058)  评论(3编辑  收藏  举报