• Java中的RSA加密解密实现 分类: Java 2014-01-16 19:05 1412人阅读 评论(1) 收藏


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

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

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

    [java] view plaincopy
    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 plaincopy
    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 plaincopy
    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 plaincopy
    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("公钥:  " + publicKey);  
    16.             System.err.println("私钥:  " + 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(" 加密前文字: " + source);  
    31.         byte[] data = source.getBytes();  
    32.         byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);  
    33.         System.out.println("加密后文字: " + new String(encodedData));  
    34.         byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);  
    35.         String target = new String(decodedData);  
    36.         System.out.println("解密后文字:  " + target);  
    37.     }  
    38.   
    39.     static void testSign() throws Exception {  
    40.         System.err.println("私钥加密——公钥解密");  
    41.         String source = "这是一行测试RSA数字签名的无意义文字";  
    42.         System.out.println("原文字: " + source);  
    43.         byte[] data = source.getBytes();  
    44.         byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);  
    45.         System.out.println("加密后: " + new String(encodedData));  
    46.         byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);  
    47.         String target = new String(decodedData);  
    48.         System.out.println("解密后:  " + target);  
    49.         System.err.println("私钥签名——公钥验证签名");  
    50.         String sign = RSAUtils.sign(encodedData, privateKey);  
    51.         System.err.println("签名: " + sign);  
    52.         boolean status = RSAUtils.verify(encodedData, publicKey, sign);  
    53.         System.err.println("验证结果: " + status);  
    54.     }  
    55.       
    56. }  

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    根据出生日期来计算年龄
    tomcat 7 7.0.73 url 参数 大括号 {} 不支持 , 7.0.67支持
    hdu 1272(并查集)
    hdu 1558(计算几何+并查集)
    hdu 1856(hash+启发式并查集)
    hdu 1598(最小生成树)
    poj 3164(最小树形图模板)
    hdu 2489(状态压缩+最小生成树)
    hdu 3371(启发式合并的最小生成树)
    hdu 1301(最小生成树)
  • 原文地址:https://www.cnblogs.com/pjdssswe/p/4696104.html
Copyright © 2020-2023  润新知