java RSA加密解密实现

时间:2022-09-05 21:11:44

该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar

下载地址:http://download.csdn.net/detail/centralperk/5025595

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

[java]  view plain  copy
  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*..)  

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

 

RSATester.Java

[java]  view plain  copy
  1. package security;  
  2.   
  3. import java.util.Map;  
  4.   
  5. public class RSATester {  
  6.   
  7.     static String publicKey;  
  8.     static String privateKey;  
  9.   
  10.     static {  
  11.         try {  
  12.             Map<String, Object> keyMap = RSAUtils.genKeyPair();  
  13.             publicKey = RSAUtils.getPublicKey(keyMap);  
  14.             privateKey = RSAUtils.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.     public static void main(String[] args) throws Exception {  
  23.         test();  
  24.         testSign();  
  25.     }  
  26.   
  27.     static void test() throws Exception {  
  28.         System.err.println("公钥加密——私钥解密");  
  29.         String source = "这是一行没有任何意义的文字,你看完了等于没看,不是吗?";  
  30.         System.out.println("\r加密前文字:\r\n" + source);  
  31.         byte[] data = source.getBytes();  
  32.         byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);  
  33.         System.out.println("加密后文字:\r\n" + new String(encodedData));  
  34.         byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);  
  35.         String target = new String(decodedData);  
  36.         System.out.println("解密后文字: \r\n" + target);  
  37.     }  
  38.   
  39.     static void testSign() throws Exception {  
  40.         System.err.println("私钥加密——公钥解密");  
  41.         String source = "这是一行测试RSA数字签名的无意义文字";  
  42.         System.out.println("原文字:\r\n" + source);  
  43.         byte[] data = source.getBytes();  
  44.         byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);  
  45.         System.out.println("加密后:\r\n" + new String(encodedData));  
  46.         byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);  
  47.         String target = new String(decodedData);  
  48.         System.out.println("解密后: \r\n" + target);  
  49.         System.err.println("私钥签名——公钥验证签名");  
  50.         String sign = RSAUtils.sign(encodedData, privateKey);  
  51.         System.err.println("签名:\r" + sign);  
  52.         boolean status = RSAUtils.verify(encodedData, publicKey, sign);  
  53.         System.err.println("验证结果:\r" + status);  
  54.     }  
  55.       
  56. }