IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [转]JAVA实现RSA加密

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

    Base64Utils文件

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

    测试用例:



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

    生成RSA密钥、保存到文件、从文件读取、加密、解密等操作

    [html] view plain copy
    1. import java.security.Key;     
    2. import java.security.KeyFactory;     
    3. import java.security.KeyPair;     
    4. import java.security.KeyPairGenerator;     
    5. import java.security.NoSuchAlgorithmException;     
    6. import java.security.PrivateKey;     
    7. import java.security.PublicKey;     
    8. import java.security.SecureRandom;     
    9. import java.security.interfaces.RSAPrivateKey;     
    10. import java.security.interfaces.RSAPublicKey;     
    11. import java.security.spec.InvalidKeySpecException;     
    12. import java.security.spec.PKCS8EncodedKeySpec;     
    13. import java.security.spec.X509EncodedKeySpec;     
    14. import javax.crypto.Cipher;     
    15. import org.apache.commons.configuration.ConfigurationException;     
    16. import org.apache.commons.configuration.PropertiesConfiguration;     
    17. import org.bouncycastle.jce.provider.BouncyCastleProvider;     
    18.     
    19. public class RSATest {     
    20.     
    21.     public static void main(String[] args) {     
    22.         try {     
    23.             RSATest encrypt = new RSATest();     
    24.             String encryptText = "encryptText";     
    25.     
    26.             // Generate keys     
    27.             KeyPair keyPair = encrypt.generateKey();     
    28.             RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();     
    29.             RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();     
    30.     
    31.             byte[] e = encrypt.encrypt(publicKey, encryptText.getBytes());     
    32.             byte[] de = encrypt.decrypt(privateKey, e);     
    33.             System.out.println(toHexString(e));     
    34.             System.out.println(toHexString(de));     
    35.         } catch (Exception e) {     
    36.             e.printStackTrace();     
    37.         }     
    38.     }     
    39.     
    40.     public KeyPair generateKey() throws NoSuchAlgorithmException {     
    41.         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");     
    42.         keyPairGen.initialize(1024, new SecureRandom());     
    43.     
    44.         KeyPair keyPair = keyPairGen.generateKeyPair();     
    45.         return keyPair;     
    46.     }     
    47.     
    48.     public void saveKey(KeyPair keyPair, String publicKeyFile,     
    49.             String privateKeyFile) throws ConfigurationException {     
    50.         PublicKey pubkey = keyPair.getPublic();     
    51.         PrivateKey prikey = keyPair.getPrivate();     
    52.     
    53.         // save public key     
    54.         PropertiesConfiguration publicConfig = new PropertiesConfiguration(     
    55.                 publicKeyFile);     
    56.         publicConfig.setProperty("PULIICKEY", toHexString(pubkey.getEncoded()));     
    57.         publicConfig.save();     
    58.     
    59.         // save private key     
    60.         PropertiesConfiguration privateConfig = new PropertiesConfiguration(     
    61.                 privateKeyFile);     
    62.         privateConfig.setProperty("PRIVATEKEY",     
    63.                 toHexString(prikey.getEncoded()));     
    64.         privateConfig.save();     
    65.     }     
    66.     
    67.     /**    
    68.      * @param filename    
    69.      * @param type:    
    70.      *            1-public 0-private    
    71.      * @return    
    72.      * @throws ConfigurationException    
    73.      * @throws NoSuchAlgorithmException    
    74.      * @throws InvalidKeySpecException    
    75.      */    
    76.     public Key loadKey(String filename, int type)     
    77.             throws ConfigurationException, NoSuchAlgorithmException,     
    78.             InvalidKeySpecException {     
    79.         PropertiesConfiguration config = new PropertiesConfiguration(filename);     
    80.         KeyFactory keyFactory = KeyFactory.getInstance("RSA",     
    81.                 new BouncyCastleProvider());     
    82.     
    83.         if (type == 0) {     
    84.             // privateKey     
    85.             String privateKeyValue = config.getString("PULIICKEY");     
    86.             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(     
    87.                     toBytes(privateKeyValue));     
    88.             PrivateKey privateKey = keyFactory.generatePrivate(priPKCS8);     
    89.             return privateKey;     
    90.     
    91.         } else {     
    92.             // publicKey     
    93.             String privateKeyValue = config.getString("PRIVATEKEY");     
    94.             X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(     
    95.                     toBytes(privateKeyValue));     
    96.             PublicKey publicKey = keyFactory.generatePublic(bobPubKeySpec);     
    97.             return publicKey;     
    98.         }     
    99.     }     
    100.     
    101.     /**    
    102.      * Encrypt String.    
    103.      *     
    104.      * @return byte[]    
    105.      */    
    106.     protected byte[] encrypt(RSAPublicKey publicKey, byte[] data) {     
    107.         if (publicKey != null) {     
    108.             try {     
    109.                 Cipher cipher = Cipher.getInstance("RSA",     
    110.                         new BouncyCastleProvider());     
    111.                 cipher.init(Cipher.ENCRYPT_MODE, publicKey);     
    112.                 return cipher.doFinal(data);     
    113.             } catch (Exception e) {     
    114.                 e.printStackTrace();     
    115.             }     
    116.         }     
    117.         return null;     
    118.     }     
    119.     
    120.     /**    
    121.      * Basic decrypt method    
    122.      *     
    123.      * @return byte[]    
    124.      */    
    125.     protected byte[] decrypt(RSAPrivateKey privateKey, byte[] raw) {     
    126.         if (privateKey != null) {     
    127.             try {     
    128.                 Cipher cipher = Cipher.getInstance("RSA",     
    129.                         new BouncyCastleProvider());     
    130.                 cipher.init(Cipher.DECRYPT_MODE, privateKey);     
    131.                 return cipher.doFinal(raw);     
    132.             } catch (Exception e) {     
    133.                 e.printStackTrace();     
    134.             }     
    135.         }     
    136.     
    137.         return null;     
    138.     }     
    139.     
    140.     public static String toHexString(byte[] b) {     
    141.         StringBuilder sb = new StringBuilder(b.length * 2);     
    142.         for (int i = 0; i < b.length; i++) {     
    143.             sb.append(HEXCHAR[(b[i] & 0xf0) >>> 4]);     
    144.             sb.append(HEXCHAR[b[i] & 0x0f]);     
    145.         }     
    146.         return sb.toString();     
    147.     }     
    148.     
    149.     public static final byte[] toBytes(String s) {     
    150.         byte[] bytes;     
    151.         bytes = new byte[s.length() / 2];     
    152.         for (int i = 0; i < bytes.length; i++) {     
    153.             bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2),     
    154.                     16);     
    155.         }     
    156.         return bytes;     
    157.     }     
    158.     
    159.     private static char[] HEXCHAR = { '0', '1', '2', '3', '4', '5', '6', '7',     
    160.             '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };     
    161.     
    162. }  


    Java中RSA非对称密钥加解密使用示例

    一、简介:

      RSA加密算法是最常用的非对称加密算法,CFCA在证书服务中离不了它。RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名。这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法。

      二、RSA的公钥、私钥的组成,以及加密、解密的公式可见于下表

      三、使用方式:

      ① 假设A、B机器进行通信,已A机器为主;

      ② A首先需要用自己的私钥为发送请求数据签名,并将公钥一同发送给B;

      ③ B收到数据后,需要用A发送的公钥进行验证,已确保收到的数据是未经篡改的;

      ④ B验签通过后,处理逻辑,并把处理结果返回,返回数据需要用A发送的公钥进行加密(公钥加密后,只能用配对的私钥解密);

      ⑤ A收到B返回的数据,使用私钥解密,至此,一次数据交互完成。

      四、代码示例:

      1、第一步获取私钥,为签名做准备。

    [html] view plain copy
    1. /**  
    2.      * 读取私钥  返回PrivateKey  
    3.      * @param path  包含私钥的证书路径  
    4.      * @param password  私钥证书密码  
    5.      * @return 返回私钥PrivateKey  
    6.      * @throws KeyStoreException  
    7.      * @throws NoSuchAlgorithmException  
    8.      * @throws CertificateException  
    9.      * @throws IOException  
    10.      * @throws UnrecoverableKeyException  
    11.      */  
    12.     private static PrivateKey getPrivateKey(String path,String password)  
    13.             throws KeyStoreException, NoSuchAlgorithmException, CertificateException,  
    14.             IOException, UnrecoverableKeyException {  
    15.         KeyStore ks = KeyStore.getInstance("PKCS12");  
    16.         FileInputStream fis = new FileInputStream(path);  
    17.         char[] nPassword = null;  
    18.         if ((password == null) || password.trim().equals("")) {  
    19.             nPassword = null;  
    20.         } else {  
    21.             nPassword = password.toCharArray();  
    22.         }  
    23.         ks.load(fis, nPassword);  
    24.         fis.close();  
    25.         Enumeration<String> en = ks.aliases();  
    26.         String keyAlias = null;  
    27.         if (en.hasMoreElements()) {  
    28.             keyAlias = (String) en.nextElement();  
    29.         }  
    30.    
    31.         return (PrivateKey) ks.getKey(keyAlias, nPassword);  
    32.     }  


    2、签名示例:通过第一步得到的私钥,进行签名操作,具体请看以下代码:

    [html] view plain copy
    1. /**  
    2.      * 私钥签名: 签名方法如下:BASE64(RSA(MD5(src),privatekey)),其中src为需要签名的字符串,  
    3. privatekey是商户的CFCA证书私钥。  
    4.      * @param plainText 待签名字符串  
    5.      * @param path 签名私钥路径  
    6.      * @param password  签名私钥密码  
    7.      * @return 返回签名后的字符串  
    8.      * @throws Exception  
    9.      */  
    10.     public static String sign(String plainText,String path,String password)  
    11.             throws Exception  {  
    12.         /*  
    13.          * MD5加密  
    14.          */  
    15.         MessageDigest md5 = MessageDigest.getInstance("MD5");  
    16.         md5.update(plainText.getBytes("utf-8"));  
    17.         byte[] digestBytes = md5.digest();  
    18.         /*  
    19.          * 用私钥进行签名 RSA  
    20.          * Cipher负责完成加密或解密工作,基于RSA  
    21.          */  
    22.         Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");  
    23.         //ENCRYPT_MODE表示为加密模式  
    24.         cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(path, password));  
    25.         //加密  
    26.         byte[] rsaBytes = cipher.doFinal(digestBytes);  
    27.         //Base64编码  
    28.         return Base64.byteArrayToBase64(rsaBytes);}  

    3、B收到数据后,需要使用A提供的公钥信息进行验签,此处使用公钥的N、E进行验签

      首先通过公钥N、E得到公钥PublicKey,如下:

    [html] view plain copy
    1. /**   
    2.      * 根据公钥n、e生成公钥  
    3.      * @param modulus   公钥n串  
    4.      * @param publicExponent  公钥e串  
    5.      * @return 返回公钥PublicKey  
    6.      * @throws Exception  
    7.      */  
    8.     public static PublicKey getPublickKey(String modulus, String publicExponent)  
    9.             throws Exception {  
    10.         KeySpec publicKeySpec = new RSAPublicKeySpec(  
    11.                 new BigInteger(modulus, 16), new BigInteger(publicExponent, 16));  
    12.         KeyFactory factory = KeyFactory.getInstance("RSA");  
    13.         PublicKey publicKey = factory.generatePublic(publicKeySpec);  
    14.         return publicKey;  
    15.     }  

    得到公钥PublicKey后,再去验证签名,代码如下:

    [html] view plain copy
    1. /**  
    2.      * 用公钥证书进行验签  
    3.      * @param message  签名之前的原文  
    4.      * @param cipherText  签名  
    5.      * @param pubKeyn 公钥n串  
    6.      * @param pubKeye 公钥e串  
    7.      * @return boolean 验签成功为true,失败为false  
    8.      * @throws Exception  
    9.      */  
    10.     public static boolean verify(String message, String cipherText,String pubKeyn,  
    11.             String pubKeye) throws Exception {  
    12.         Cipher c4 = Cipher.getInstance("RSA/ECB/PKCS1Padding");  
    13.         // 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示解密模式  
    14.         c4.init(Cipher.DECRYPT_MODE, getPublickKey(pubKeyn,pubKeye));  
    15.         // 解密  
    16.         byte[] desDecTextBytes = c4.doFinal(Base64.base64ToByteArray(cipherText));  
    17.         // 得到前置对原文进行的MD5  
    18.         String md5Digest1 = Base64.byteArrayToBase64(desDecTextBytes);  
    19.         MessageDigest md5 = MessageDigest.getInstance("MD5");  
    20.         md5.update(message.getBytes("utf-8"));  
    21.         byte[] digestBytes = md5.digest();  
    22.         // 得到商户对原文进行的MD5  
    23.         String md5Digest2 = Base64.byteArrayToBase64(digestBytes);  
    24.         // 验证签名  
    25.         if (md5Digest1.equals(md5Digest2)) {  
    26.             return true;  
    27.         } else {  
    28.             return false;  
    29.         }  
    30.     }  

     至此,签名验签已经完毕

      4、提供一个从.cer文件读取公钥的方法:

    [html] view plain copy
    1. /**  
    2.      * 读取公钥cer  
    3.      * @param path .cer文件的路径  如:c:/abc.cer  
    4.      * @return  base64后的公钥串  
    5.      * @throws IOException  
    6.      * @throws CertificateException  
    7.      */  
    8.     public static String getPublicKey(String path) throws IOException,  
    9.     CertificateException{  
    10.         InputStream inStream = new FileInputStream(path);  
    11.         ByteArrayOutputStream out = new ByteArrayOutputStream();  
    12.         int ch;  
    13.         String res = "";  
    14.         while ((ch = inStream.read()) != -1) {  
    15.             out.write(ch);  
    16.         }  
    17.         byte[] result = out.toByteArray();  
    18.         res = Base64.byteArrayToBase64(result);  
    19.         return res;  
    20.     }  


沪ICP备19023445号-2号
友情链接