转载请注明出处:

http://blog.csdn.net/aa464971/article/details/51034462


本文以Android客户端加密提交数据到Java服务端后进行解密为例子。


生成RSA公钥和密钥的方法请参考:

http://blog.csdn.net/aa464971/article/details/51035200


Android端的加密思路需要4步:

1.生成AES密钥;

2.使用RSA公钥加密刚刚生成的AES密钥;

3.再使用第1步生成的AES密钥,通过AES加密需要提交给服务端的数据;

4.将第2与第3生成的内容传给服务端。


JAVA服务端的解密思路只需3步:

1.获取到客户端传过来的AES密钥密文和内容密文;

2.使用RSA私钥解密从客户端拿到的AES密钥密文;

3.再使用第2步解密出来的明文密钥,通过AES解密内容的密文。


AES的代码可以在JAVA和Android上通用

[java] view plain copy
  1. package com.dyhdyh.encrypt;  
  2.   
  3. import java.io.UnsupportedEncodingException;  
  4. import java.security.NoSuchAlgorithmException;  
  5. import java.security.SecureRandom;  
  6.   
  7. import javax.crypto.Cipher;  
  8. import javax.crypto.KeyGenerator;  
  9. import javax.crypto.SecretKey;  
  10. import javax.crypto.spec.SecretKeySpec;  
  11.   
  12. /** 
  13.  * AES 
  14.  * @author dengyuhan 
  15.  * @create 2016/3/31 15:43 
  16.  */  
  17. public class AES {  
  18.     // /** 算法/模式/填充 **/  
  19.     private static final String CipherMode = "AES/ECB/PKCS5Padding";  
  20.     // private static final String CipherMode = "AES";  
  21.   
  22.     /** 
  23.      * 生成一个AES密钥对象 
  24.      * @return 
  25.      */  
  26.     public static SecretKeySpec generateKey(){  
  27.         try {  
  28.             KeyGenerator kgen = KeyGenerator.getInstance("AES");  
  29.             kgen.init(128new SecureRandom());    
  30.             SecretKey secretKey = kgen.generateKey();    
  31.             byte[] enCodeFormat = secretKey.getEncoded();    
  32.             SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");  
  33.             return key;  
  34.         } catch (NoSuchAlgorithmException e) {  
  35.             e.printStackTrace();  
  36.         }  
  37.         return null;  
  38.     }  
  39.   
  40.     /** 
  41.      * 生成一个AES密钥字符串 
  42.      * @return 
  43.      */  
  44.     public static String generateKeyString(){  
  45.         return byte2hex(generateKey().getEncoded());  
  46.     }  
  47.   
  48.     /** 
  49.      * 加密字节数据 
  50.      * @param content 
  51.      * @param key 
  52.      * @return 
  53.      */  
  54.     public static byte[] encrypt(byte[] content,byte[] key) {  
  55.         try {  
  56.             Cipher cipher = Cipher.getInstance(CipherMode);  
  57.             cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));  
  58.             byte[] result = cipher.doFinal(content);  
  59.             return result;  
  60.         } catch (Exception e) {  
  61.             e.printStackTrace();  
  62.         }  
  63.         return null;  
  64.     }  
  65.   
  66.     /** 
  67.      * 通过byte[]类型的密钥加密String 
  68.      * @param content 
  69.      * @param key 
  70.      * @return 16进制密文字符串 
  71.      */  
  72.     public static String encrypt(String content,byte[] key) {  
  73.         try {  
  74.             Cipher cipher = Cipher.getInstance(CipherMode);  
  75.             cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));  
  76.             byte[] data = cipher.doFinal(content.getBytes("UTF-8"));  
  77.             String result = byte2hex(data);  
  78.             return result;  
  79.         } catch (Exception e) {  
  80.             e.printStackTrace();  
  81.         }  
  82.         return null;  
  83.     }  
  84.   
  85.     /** 
  86.      * 通过String类型的密钥加密String 
  87.      * @param content 
  88.      * @param key 
  89.      * @return 16进制密文字符串 
  90.      */  
  91.     public static String encrypt(String content,String key) {  
  92.         byte[] data = null;  
  93.         try {  
  94.             data = content.getBytes("UTF-8");  
  95.         } catch (Exception e) {  
  96.             e.printStackTrace();  
  97.         }  
  98.         data = encrypt(data,new SecretKeySpec(hex2byte(key), "AES").getEncoded());  
  99.         String result = byte2hex(data);  
  100.         return result;  
  101.     }  
  102.   
  103.     /** 
  104.      * 通过byte[]类型的密钥解密byte[] 
  105.      * @param content 
  106.      * @param key 
  107.      * @return 
  108.      */  
  109.     public static byte[] decrypt(byte[] content,byte[] key) {  
  110.         try {  
  111.             Cipher cipher = Cipher.getInstance(CipherMode);  
  112.             cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));  
  113.             byte[] result = cipher.doFinal(content);  
  114.             return result;  
  115.         } catch (Exception e) {  
  116.             e.printStackTrace();  
  117.         }  
  118.         return null;  
  119.     }  
  120.   
  121.     /** 
  122.      * 通过String类型的密钥 解密String类型的密文 
  123.      * @param content 
  124.      * @param key 
  125.      * @return 
  126.      */  
  127.     public static String decrypt(String content, String key) {  
  128.         byte[] data = null;  
  129.         try {  
  130.             data = hex2byte(content);  
  131.         } catch (Exception e) {  
  132.             e.printStackTrace();  
  133.         }  
  134.         data = decrypt(data, hex2byte(key));  
  135.         if (data == null)  
  136.             return null;  
  137.         String result = null;  
  138.         try {  
  139.             result = new String(data, "UTF-8");  
  140.         } catch (UnsupportedEncodingException e) {  
  141.             e.printStackTrace();  
  142.         }  
  143.         return result;  
  144.     }  
  145.   
  146.     /** 
  147.      * 通过byte[]类型的密钥 解密String类型的密文 
  148.      * @param content 
  149.      * @param key 
  150.      * @return 
  151.      */  
  152.     public static String decrypt(String content,byte[] key) {  
  153.         try {  
  154.             Cipher cipher = Cipher.getInstance(CipherMode);  
  155.             cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(key, "AES"));  
  156.             byte[] data = cipher.doFinal(hex2byte(content));  
  157.             return new String(data, "UTF-8");  
  158.         } catch (Exception e) {  
  159.             e.printStackTrace();  
  160.         }  
  161.         return null;  
  162.     }  
  163.   
  164.     /** 
  165.      * 字节数组转成16进制字符串 
  166.      * @param b 
  167.      * @return 
  168.      */  
  169.     public static String byte2hex(byte[] b) { // 一个字节的数,  
  170.         StringBuffer sb = new StringBuffer(b.length * 2);  
  171.         String tmp = "";  
  172.         for (int n = 0; n < b.length; n++) {  
  173.             // 整数转成十六进制表示  
  174.             tmp = (Integer.toHexString(b[n] & 0XFF));  
  175.             if (tmp.length() == 1) {  
  176.                 sb.append("0");  
  177.             }  
  178.             sb.append(tmp);  
  179.         }  
  180.         return sb.toString().toUpperCase(); // 转成大写  
  181.     }  
  182.   
  183.     /** 
  184.      * 将hex字符串转换成字节数组 
  185.      * @param inputString 
  186.      * @return 
  187.      */  
  188.     private static byte[] hex2byte(String inputString) {  
  189.         if (inputString == null || inputString.length() < 2) {  
  190.             return new byte[0];  
  191.         }  
  192.         inputString = inputString.toLowerCase();  
  193.         int l = inputString.length() / 2;  
  194.         byte[] result = new byte[l];  
  195.         for (int i = 0; i < l; ++i) {  
  196.             String tmp = inputString.substring(2 * i, 2 * i + 2);  
  197.             result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);  
  198.         }  
  199.         return result;  
  200.     }  
  201. }  


Android - RSA实现

[java] view plain copy
  1. package com.dyhdyh.encrypt;  
  2.   
  3. import android.util.Base64;  
  4.   
  5. import java.io.BufferedReader;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.InputStreamReader;  
  9. import java.security.KeyFactory;  
  10. import java.security.NoSuchAlgorithmException;  
  11. import java.security.interfaces.RSAPrivateKey;  
  12. import java.security.interfaces.RSAPublicKey;  
  13. import java.security.spec.InvalidKeySpecException;  
  14. import java.security.spec.PKCS8EncodedKeySpec;  
  15. import java.security.spec.X509EncodedKeySpec;  
  16.   
  17. import javax.crypto.Cipher;  
  18.   
  19. /** 
  20.  * 用于Android平台的RSA加密解密 
  21.  *  
  22.  * @desc 
  23.  * @author dengyuhan 
  24.  * @create 2016-3-31 下午2:36:18 
  25.  */  
  26. public class RSA {  
  27.     private static final String ALGORITHM = "RSA";  
  28.     private static final String TRANSFORMATION = "RSA";  
  29.   
  30.     /** 
  31.      * 从文件中输入流中加载公钥 
  32.      *  
  33.      * @param in 
  34.      *            公钥输入流 
  35.      * @throws Exception 
  36.      *             加载公钥时产生的异常 
  37.      */  
  38.     public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {  
  39.         try {  
  40.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
  41.             String readLine = null;  
  42.             StringBuilder sb = new StringBuilder();  
  43.             while ((readLine = br.readLine()) != null) {  
  44.                 if (readLine.charAt(0) == '-') {  
  45.                     continue;  
  46.                 } else {  
  47.                     sb.append(readLine);  
  48.                     sb.append('\r');  
  49.                 }  
  50.             }  
  51.             return loadPublicKey(sb.toString());  
  52.         } catch (IOException e) {  
  53.             throw new Exception("公钥数据流读取错误");  
  54.         } catch (NullPointerException e) {  
  55.             throw new Exception("公钥输入流为空");  
  56.         }  
  57.     }  
  58.   
  59.     /** 
  60.      * 从字符串中加载公钥 
  61.      *  
  62.      * @param publicKeyStr 
  63.      *            公钥数据字符串 
  64.      * @return 
  65.      * @throws Exception 
  66.      *             加载公钥时产生的异常 
  67.      */  
  68.     public static RSAPublicKey loadPublicKey(String publicKeyStr)  
  69.             throws Exception {  
  70.         try {  
  71.             byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);  
  72.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
  73.             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);  
  74.             return (RSAPublicKey) keyFactory.generatePublic(keySpec);  
  75.         } catch (NoSuchAlgorithmException e) {  
  76.             throw new Exception("无此算法");  
  77.         } catch (InvalidKeySpecException e) {  
  78.             throw new Exception("公钥非法");  
  79.         }catch (NullPointerException e) {  
  80.             throw new Exception("公钥数据为空");  
  81.         }  
  82.     }  
  83.   
  84.     /** 
  85.      * 从文件中加载私钥 
  86.      *  
  87.      * @param in 
  88.      *            私钥输入流 
  89.      * @return 
  90.      * @throws Exception 
  91.      */  
  92.     public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {  
  93.         try {  
  94.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
  95.             String readLine = null;  
  96.             StringBuilder sb = new StringBuilder();  
  97.             while ((readLine = br.readLine()) != null) {  
  98.                 if (readLine.charAt(0) == '-') {  
  99.                     continue;  
  100.                 } else {  
  101.                     sb.append(readLine);  
  102.                     sb.append('\r');  
  103.                 }  
  104.             }  
  105.             return loadPrivateKey(sb.toString());  
  106.         } catch (IOException e) {  
  107.             throw new Exception("私钥数据读取错误");  
  108.         } catch (NullPointerException e) {  
  109.             throw new Exception("私钥输入流为空");  
  110.         }  
  111.     }  
  112.   
  113.     /** 
  114.      * 从字符串中加载私钥 
  115.      *  
  116.      * @desc 
  117.      * @param privateKeyStr 
  118.      *            私钥字符串 
  119.      * @return 
  120.      * @throws Exception 
  121.      */  
  122.     public static RSAPrivateKey loadPrivateKey(String privateKeyStr)  
  123.             throws Exception {  
  124.         try {  
  125.             byte[] buffer = Base64.decode(privateKeyStr, Base64.DEFAULT);  
  126.             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);  
  127.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
  128.             return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);  
  129.         } catch (NoSuchAlgorithmException e) {  
  130.             throw new Exception("无此算法");  
  131.         } catch (InvalidKeySpecException e) {  
  132.             throw new Exception("私钥非法");  
  133.         }catch (NullPointerException e) {  
  134.             throw new Exception("私钥数据为空");  
  135.         }  
  136.     }  
  137.   
  138.     /** 
  139.      * 公钥加密 
  140.      *  
  141.      * @param data 
  142.      * @param publicKey 
  143.      * @return 
  144.      * @throws Exception 
  145.      */  
  146.     public static String encryptByPublicKey(String data, RSAPublicKey publicKey)  
  147.             throws Exception {  
  148.         // 模长  
  149.         int key_len = publicKey.getModulus().bitLength() / 8;  
  150.         // 加密数据长度 <= 模长-11  
  151.         String[] datas = splitString(data, key_len - 11);  
  152.         String mi = "";  
  153.         // 如果明文长度大于模长-11则要分组加密  
  154.         for (String s : datas) {  
  155.             mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));  
  156.         }  
  157.         return mi;  
  158.     }  
  159.   
  160.     /** 
  161.      * 公钥加密 
  162.      * @desc  
  163.      * @param data 
  164.      * @param publicKey 
  165.      * @return 
  166.      * @throws Exception 
  167.      */  
  168.     public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)  
  169.             throws Exception {  
  170.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
  171.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  172.         return cipher.doFinal(data);  
  173.     }  
  174.   
  175.     /** 
  176.      * 私钥加密 
  177.      * @desc  
  178.      * @param data 
  179.      * @param privateKey 
  180.      * @return 
  181.      * @throws Exception 
  182.      */  
  183.     public static byte[] encryptByPrivateKey(byte[] data,  
  184.             RSAPrivateKey privateKey) throws Exception {  
  185.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
  186.         cipher.init(Cipher.ENCRYPT_MODE, privateKey);  
  187.         return cipher.doFinal(data);  
  188.     }  
  189.   
  190.   
  191.     /** 
  192.      * 私钥加密 
  193.      * @desc  
  194.      * @param data 
  195.      * @param privateKey 
  196.      * @return 
  197.      * @throws Exception 
  198.      */  
  199.     public static String encryptByPrivateKey(String data,  
  200.             RSAPrivateKey privateKey) throws Exception {  
  201.         // 模长  
  202.         int key_len = privateKey.getModulus().bitLength() / 8;  
  203.         // 加密数据长度 <= 模长-11  
  204.         String[] datas = splitString(data, key_len - 11);  
  205.         String mi = "";  
  206.         // 如果明文长度大于模长-11则要分组加密  
  207.         for (String s : datas) {  
  208.             mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));  
  209.         }  
  210.         return mi;  
  211.     }  
  212.   
  213.     /** 
  214.      * 私钥解密 
  215.      *  
  216.      * @param data 
  217.      * @param privateKey 
  218.      * @return 
  219.      * @throws Exception 
  220.      */  
  221.     public static String decryptByPrivateKey(String data,  
  222.             RSAPrivateKey privateKey) throws Exception {  
  223.         // 模长  
  224.         int key_len = privateKey.getModulus().bitLength() / 8;  
  225.         byte[] bytes = data.getBytes();  
  226.         byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
  227.         // 如果密文长度大于模长则要分组解密  
  228.         String ming = "";  
  229.         byte[][] arrays = splitArray(bcd, key_len);  
  230.         for (byte[] arr : arrays) {  
  231.             ming += new String(decryptByPrivateKey(arr, privateKey));  
  232.         }  
  233.         return ming;  
  234.     }  
  235.       
  236.     /** 
  237.      * 私钥解密 
  238.      * @desc  
  239.      * @param data 
  240.      * @param privateKey 
  241.      * @return 
  242.      * @throws Exception 
  243.      */  
  244.     public static byte[] decryptByPrivateKey(byte[] data,  
  245.             RSAPrivateKey privateKey) throws Exception {  
  246.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
  247.         cipher.init(Cipher.DECRYPT_MODE, privateKey);  
  248.         return cipher.doFinal(data);  
  249.     }  
  250.       
  251.     /** 
  252.      * 公钥解密 
  253.      * @desc  
  254.      * @param data 
  255.      * @param publicKey 
  256.      * @return 
  257.      * @throws Exception 
  258.      */  
  259.     public static String decryptByPublicKey(String data,  
  260.             RSAPublicKey publicKey) throws Exception {  
  261.         // 模长  
  262.         int key_len = publicKey.getModulus().bitLength() / 8;  
  263.         byte[] bytes = data.getBytes();  
  264.         byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
  265.         // 如果密文长度大于模长则要分组解密  
  266.         String ming = "";  
  267.         byte[][] arrays = splitArray(bcd, key_len);  
  268.         for (byte[] arr : arrays) {  
  269.             ming += new String(decryptByPublicKey(arr, publicKey));  
  270.         }  
  271.         return ming;  
  272.     }  
  273.       
  274.     /** 
  275.      * 公钥解密 
  276.      * @desc  
  277.      * @param data 
  278.      * @param publicKey 
  279.      * @return 
  280.      * @throws Exception 
  281.      */  
  282.     public static byte[] decryptByPublicKey(byte[] data,  
  283.             RSAPublicKey publicKey) throws Exception {  
  284.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
  285.         cipher.init(Cipher.DECRYPT_MODE, publicKey);  
  286.         return cipher.doFinal(data);  
  287.     }  
  288.   
  289.     /** 
  290.      * ASCII码转BCD码 
  291.      *  
  292.      */  
  293.     private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {  
  294.         byte[] bcd = new byte[asc_len / 2];  
  295.         int j = 0;  
  296.         for (int i = 0; i < (asc_len + 1) / 2; i++) {  
  297.             bcd[i] = asc_to_bcd(ascii[j++]);  
  298.             bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));  
  299.         }  
  300.         return bcd;  
  301.     }  
  302.   
  303.     private static byte asc_to_bcd(byte asc) {  
  304.         byte bcd;  
  305.   
  306.         if ((asc >= '0') && (asc <= '9'))  
  307.             bcd = (byte) (asc - '0');  
  308.         else if ((asc >= 'A') && (asc <= 'F'))  
  309.             bcd = (byte) (asc - 'A' + 10);  
  310.         else if ((asc >= 'a') && (asc <= 'f'))  
  311.             bcd = (byte) (asc - 'a' + 10);  
  312.         else  
  313.             bcd = (byte) (asc - 48);  
  314.         return bcd;  
  315.     }  
  316.   
  317.     /** 
  318.      * BCD转字符串 
  319.      */  
  320.     private static String bcd2Str(byte[] bytes) {  
  321.         char temp[] = new char[bytes.length * 2], val;  
  322.   
  323.         for (int i = 0; i < bytes.length; i++) {  
  324.             val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);  
  325.             temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
  326.   
  327.             val = (char) (bytes[i] & 0x0f);  
  328.             temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
  329.         }  
  330.         return new String(temp);  
  331.     }  
  332.   
  333.     /** 
  334.      * 拆分字符串 
  335.      */  
  336.     private static String[] splitString(String string, int len) {  
  337.         int x = string.length() / len;  
  338.         int y = string.length() % len;  
  339.         int z = 0;  
  340.         if (y != 0) {  
  341.             z = 1;  
  342.         }  
  343.         String[] strings = new String[x + z];  
  344.         String str = "";  
  345.         for (int i = 0; i < x + z; i++) {  
  346.             if (i == x + z - 1 && y != 0) {  
  347.                 str = string.substring(i * len, i * len + y);  
  348.             } else {  
  349.                 str = string.substring(i * len, i * len + len);  
  350.             }  
  351.             strings[i] = str;  
  352.         }  
  353.         return strings;  
  354.     }  
  355.   
  356.     /** 
  357.      * 拆分数组 
  358.      */  
  359.     private static byte[][] splitArray(byte[] data, int len) {  
  360.         int x = data.length / len;  
  361.         int y = data.length % len;  
  362.         int z = 0;  
  363.         if (y != 0) {  
  364.             z = 1;  
  365.         }  
  366.         byte[][] arrays = new byte[x + z][];  
  367.         byte[] arr;  
  368.         for (int i = 0; i < x + z; i++) {  
  369.             arr = new byte[len];  
  370.             if (i == x + z - 1 && y != 0) {  
  371.                 System.arraycopy(data, i * len, arr, 0, y);  
  372.             } else {  
  373.                 System.arraycopy(data, i * len, arr, 0, len);  
  374.             }  
  375.             arrays[i] = arr;  
  376.         }  
  377.         return arrays;  
  378.     }  
  379. }  

JAVA - RSA实现

[java] view plain copy
  1. package com.dyhdyh.encrypt;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.security.KeyFactory;  
  8. import java.security.NoSuchAlgorithmException;  
  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.   
  15. import javax.crypto.Cipher;  
  16.   
  17. import org.bouncycastle.jce.provider.BouncyCastleProvider;  
  18.   
  19. import sun.misc.BASE64Decoder;  
  20.   
  21. /** 
  22.  * 用于java平台的RSA加密解密 
  23.  *  
  24.  * @desc 
  25.  * @author dengyuhan 
  26.  * @create 2016-3-31 下午2:36:18 
  27.  */  
  28. public class RSA {  
  29.     private static final String ALGORITHM = "RSA";  
  30.     private static final String TRANSFORMATION = "RSA";  
  31.   
  32.     /** 
  33.      * 从文件中输入流中加载公钥 
  34.      *  
  35.      * @param in 
  36.      *            公钥输入流 
  37.      * @throws Exception 
  38.      *             加载公钥时产生的异常 
  39.      */  
  40.     public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {  
  41.         try {  
  42.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
  43.             String readLine = null;  
  44.             StringBuilder sb = new StringBuilder();  
  45.             while ((readLine = br.readLine()) != null) {  
  46.                 if (readLine.charAt(0) == '-') {  
  47.                     continue;  
  48.                 } else {  
  49.                     sb.append(readLine);  
  50.                     sb.append('\r');  
  51.                 }  
  52.             }  
  53.             return loadPublicKey(sb.toString());  
  54.         } catch (IOException e) {  
  55.             throw new Exception("公钥数据流读取错误");  
  56.         } catch (NullPointerException e) {  
  57.             throw new Exception("公钥输入流为空");  
  58.         }  
  59.     }  
  60.   
  61.     /** 
  62.      * 从字符串中加载公钥 
  63.      *  
  64.      * @param publicKeyStr 
  65.      *            公钥数据字符串 
  66.      * @return 
  67.      * @throws Exception 
  68.      *             加载公钥时产生的异常 
  69.      */  
  70.     public static RSAPublicKey loadPublicKey(String publicKeyStr)  
  71.             throws Exception {  
  72.         try {  
  73.             BASE64Decoder base64Decoder = new BASE64Decoder();  
  74.             byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);  
  75.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
  76.             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);  
  77.             return (RSAPublicKey) keyFactory.generatePublic(keySpec);  
  78.         } catch (NoSuchAlgorithmException e) {  
  79.             throw new Exception("无此算法");  
  80.         } catch (InvalidKeySpecException e) {  
  81.             throw new Exception("公钥非法");  
  82.         } catch (IOException e) {  
  83.             throw new Exception("公钥数据内容读取错误");  
  84.         } catch (NullPointerException e) {  
  85.             throw new Exception("公钥数据为空");  
  86.         }  
  87.     }  
  88.   
  89.     /** 
  90.      * 从文件中加载私钥 
  91.      *  
  92.      * @param in 
  93.      *            私钥输入流 
  94.      * @return 
  95.      * @throws Exception 
  96.      */  
  97.     public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {  
  98.         try {  
  99.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
  100.             String readLine = null;  
  101.             StringBuilder sb = new StringBuilder();  
  102.             while ((readLine = br.readLine()) != null) {  
  103.                 if (readLine.charAt(0) == '-') {  
  104.                     continue;  
  105.                 } else {  
  106.                     sb.append(readLine);  
  107.                     sb.append('\r');  
  108.                 }  
  109.             }  
  110.             return loadPrivateKey(sb.toString());  
  111.         } catch (IOException e) {  
  112.             throw new Exception("私钥数据读取错误");  
  113.         } catch (NullPointerException e) {  
  114.             throw new Exception("私钥输入流为空");  
  115.         }  
  116.     }  
  117.   
  118.     /** 
  119.      * 从字符串中加载私钥 
  120.      *  
  121.      * @desc 
  122.      * @param privateKeyStr 
  123.      *            私钥字符串 
  124.      * @return 
  125.      * @throws Exception 
  126.      */  
  127.     public static RSAPrivateKey loadPrivateKey(String privateKeyStr)  
  128.             throws Exception {  
  129.         try {  
  130.             BASE64Decoder base64Decoder = new BASE64Decoder();  
  131.             byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);  
  132.             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);  
  133.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
  134.             return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);  
  135.         } catch (NoSuchAlgorithmException e) {  
  136.             throw new Exception("无此算法");  
  137.         } catch (InvalidKeySpecException e) {  
  138.             throw new Exception("私钥非法");  
  139.         } catch (IOException e) {  
  140.             throw new Exception("私钥数据内容读取错误");  
  141.         } catch (NullPointerException e) {  
  142.             throw new Exception("私钥数据为空");  
  143.         }  
  144.     }  
  145.   
  146.     /** 
  147.      * 公钥加密 
  148.      *  
  149.      * @param data 
  150.      * @param publicKey 
  151.      * @return 
  152.      * @throws Exception 
  153.      */  
  154.     public static String encryptByPublicKey(String data, RSAPublicKey publicKey)  
  155.             throws Exception {  
  156.         // 模长  
  157.         int key_len = publicKey.getModulus().bitLength() / 8;  
  158.         // 加密数据长度 <= 模长-11  
  159.         String[] datas = splitString(data, key_len - 11);  
  160.         String mi = "";  
  161.         // 如果明文长度大于模长-11则要分组加密  
  162.         for (String s : datas) {  
  163.             mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));  
  164.         }  
  165.         return mi;  
  166.     }  
  167.   
  168.     /** 
  169.      * 公钥加密 
  170.      * @desc  
  171.      * @param data 
  172.      * @param publicKey 
  173.      * @return 
  174.      * @throws Exception 
  175.      */  
  176.     public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)  
  177.             throws Exception {  
  178.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
  179.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  180.         return cipher.doFinal(data);  
  181.     }  
  182.   
  183.     /** 
  184.      * 私钥加密 
  185.      * @desc  
  186.      * @param data 
  187.      * @param privateKey 
  188.      * @return 
  189.      * @throws Exception 
  190.      */  
  191.     public static byte[] encryptByPrivateKey(byte[] data,  
  192.             RSAPrivateKey privateKey) throws Exception {  
  193.         Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
  194.         cipher.init(Cipher.ENCRYPT_MODE, privateKey);  
  195.         return cipher.doFinal(data);  
  196.     }  
  197.       
  198.     /** 
  199.      * 私钥加密 
  200.      * @desc  
  201.      * @param data 
  202.      * @param privateKey 
  203.      * @return 
  204.      * @throws Exception 
  205.      */  
  206.     public static String encryptByPrivateKey(String data,  
  207.             RSAPrivateKey privateKey) throws Exception {  
  208.         // 模长  
  209.         int key_len = privateKey.getModulus().bitLength() / 8;  
  210.         // 加密数据长度 <= 模长-11  
  211.         String[] datas = splitString(data, key_len - 11);  
  212.         String mi = "";  
  213.         // 如果明文长度大于模长-11则要分组加密  
  214.         for (String s : datas) {  
  215.             mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));  
  216.         }  
  217.         return mi;  
  218.     }  
  219.   
  220.     /** 
  221.      * 私钥解密 
  222.      *  
  223.      * @param data 
  224.      * @param privateKey 
  225.      * @return 
  226.      * @throws Exception 
  227.      */  
  228.     public static String decryptByPrivateKey(String data,  
  229.             RSAPrivateKey privateKey) throws Exception {  
  230.         // 模长  
  231.         int key_len = privateKey.getModulus().bitLength() / 8;  
  232.         byte[] bytes = data.getBytes();  
  233.         byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
  234.         // 如果密文长度大于模长则要分组解密  
  235.         String ming = "";  
  236.         byte[][] arrays = splitArray(bcd, key_len);  
  237.         for (byte[] arr : arrays) {  
  238.             ming += new String(decryptByPrivateKey(arr, privateKey));  
  239.         }  
  240.         return ming;  
  241.     }  
  242.       
  243.     /** 
  244.      * 私钥解密 
  245.      * @desc  
  246.      * @param data 
  247.      * @param privateKey 
  248.      * @return 
  249.      * @throws Exception 
  250.      */  
  251.     public static byte[] decryptByPrivateKey(byte[] data,  
  252.             RSAPrivateKey privateKey) throws Exception {  
  253.         Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider());  
  254.         cipher.init(Cipher.DECRYPT_MODE, privateKey);  
  255.         return cipher.doFinal(data);  
  256.     }  
  257.       
  258.     /** 
  259.      * 公钥解密 
  260.      * @desc  
  261.      * @param data 
  262.      * @param publicKey 
  263.      * @return 
  264.      * @throws Exception 
  265.      */  
  266.     public static String decryptByPublicKey(String data,  
  267.             RSAPublicKey publicKey) throws Exception {  
  268.         // 模长  
  269.         int key_len = publicKey.getModulus().bitLength() / 8;  
  270.         byte[] bytes = data.getBytes();  
  271.         byte[] bcd = ASCII_To_BCD(bytes, bytes.length);  
  272.         // 如果密文长度大于模长则要分组解密  
  273.         String ming = "";  
  274.         byte[][] arrays = splitArray(bcd, key_len);  
  275.         for (byte[] arr : arrays) {  
  276.             ming += new String(decryptByPublicKey(arr, publicKey));  
  277.         }  
  278.         return ming;  
  279.     }  
  280.       
  281.     /** 
  282.      * 公钥解密 
  283.      * @desc  
  284.      * @param data 
  285.      * @param publicKey 
  286.      * @return 
  287.      * @throws Exception 
  288.      */  
  289.     public static byte[] decryptByPublicKey(byte[] data,  
  290.             RSAPublicKey publicKey) throws Exception {  
  291.         Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider());  
  292.         cipher.init(Cipher.DECRYPT_MODE, publicKey);  
  293.         return cipher.doFinal(data);  
  294.     }  
  295.   
  296.     /** 
  297.      * ASCII码转BCD码 
  298.      *  
  299.      */  
  300.     private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {  
  301.         byte[] bcd = new byte[asc_len / 2];  
  302.         int j = 0;  
  303.         for (int i = 0; i < (asc_len + 1) / 2; i++) {  
  304.             bcd[i] = asc_to_bcd(ascii[j++]);  
  305.             bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));  
  306.         }  
  307.         return bcd;  
  308.     }  
  309.   
  310.     private static byte asc_to_bcd(byte asc) {  
  311.         byte bcd;  
  312.   
  313.         if ((asc >= '0') && (asc <= '9'))  
  314.             bcd = (byte) (asc - '0');  
  315.         else if ((asc >= 'A') && (asc <= 'F'))  
  316.             bcd = (byte) (asc - 'A' + 10);  
  317.         else if ((asc >= 'a') && (asc <= 'f'))  
  318.             bcd = (byte) (asc - 'a' + 10);  
  319.         else  
  320.             bcd = (byte) (asc - 48);  
  321.         return bcd;  
  322.     }  
  323.   
  324.     /** 
  325.      * BCD转字符串 
  326.      */  
  327.     private static String bcd2Str(byte[] bytes) {  
  328.         char temp[] = new char[bytes.length * 2], val;  
  329.   
  330.         for (int i = 0; i < bytes.length; i++) {  
  331.             val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);  
  332.             temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
  333.   
  334.             val = (char) (bytes[i] & 0x0f);  
  335.             temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');  
  336.         }  
  337.         return new String(temp);  
  338.     }  
  339.   
  340.     /** 
  341.      * 拆分字符串 
  342.      */  
  343.     private static String[] splitString(String string, int len) {  
  344.         int x = string.length() / len;  
  345.         int y = string.length() % len;  
  346.         int z = 0;  
  347.         if (y != 0) {  
  348.             z = 1;  
  349.         }  
  350.         String[] strings = new String[x + z];  
  351.         String str = "";  
  352.         for (int i = 0; i < x + z; i++) {  
  353.             if (i == x + z - 1 && y != 0) {  
  354.                 str = string.substring(i * len, i * len + y);  
  355.             } else {  
  356.                 str = string.substring(i * len, i * len + len);  
  357.             }  
  358.             strings[i] = str;  
  359.         }  
  360.         return strings;  
  361.     }  
  362.   
  363.     /** 
  364.      * 拆分数组 
  365.      */  
  366.     private static byte[][] splitArray(byte[] data, int len) {  
  367.         int x = data.length / len;  
  368.         int y = data.length % len;  
  369.         int z = 0;  
  370.         if (y != 0) {  
  371.             z = 1;  
  372.         }  
  373.         byte[][] arrays = new byte[x + z][];  
  374.         byte[] arr;  
  375.         for (int i = 0; i < x + z; i++) {  
  376.             arr = new byte[len];  
  377.             if (i == x + z - 1 && y != 0) {  
  378.                 System.arraycopy(data, i * len, arr, 0, y);  
  379.             } else {  
  380.                 System.arraycopy(data, i * len, arr, 0, len);  
  381.             }  
  382.             arrays[i] = arr;  
  383.         }  
  384.         return arrays;  
  385.     }  
  386. }  

JAVA的RSA跟Android的RSA有所不同:

1.加载key的时候,JAVA上用的是BASE64Decoder

[java] view plain copy
  1. BASE64Decoder base64Decoder = new BASE64Decoder();  
  2. byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);  

而Android上用的Base64这个地方只是API不一样,作用是一样的 [java] view plain copy
  1. byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);  


2.在JAVA平台上调用Cipher.getInstance()的时候,需要多传一个参数,也就是BouncyCastleProvider的实例:

[java] view plain copy
  1. Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider());  

这个类jdk上是没有的,所以需要添加一个jar包bcprov-jdk15-143.jar



如果不这样做,JAVA上解密的时候就会抛出一个BadPaddingException

[java] view plain copy
  1. Exception in thread "main" javax.crypto.BadPaddingException: Blocktype mismatch: 0  
  2.     at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:332)  
  3.     at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272)  
  4.     at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)  
  5.     at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)  
  6.     at javax.crypto.Cipher.doFinal(Cipher.java:2087)  
  7.     at com.dyhdyh.encrypt.RSA.decryptByPrivateKey(RSA.java:255)  
  8.     at com.dyhdyh.encrypt.RSA.decryptByPrivateKey(RSA.java:238)  
这是因为Android的加密标准与JAVA的加密标准不一致导致,Android上的RSA实现是"RSA/None/NoPadding",而标准JDK实现是"RSA/None/PKCS1Padding",这造成了在Android上加密后无法在服务器上解密


最后来看看怎样混合加密(这里只举一种方式,附件里有完整的)


Android上加密

1.将openssl生成出来的公钥,放入assets文件夹内(不一定要放这里,只要能拿到文件内容就行)。



2.加载放在assets文件里的公钥

[java] view plain copy
  1. //加载RSA公钥  
  2. RSAPublicKey rsaPublicKey = RSA.loadPublicKey(getAssets().open("rsa_public_key.pem"));  

3.再生成一个AES的密钥,用于AES加密 [java] view plain copy
  1. //生成一个AES密钥  
  2. String aesKey=AES.generateKeyString();  

4.通过RSA的公钥来加密刚刚生成的AES密钥 [java] view plain copy
  1. //用RSA公钥加密AES的密钥  
  2. String encryptAesKey = RSA.encryptByPublicKey(aesKey, rsaPublicKey);  

5.最后使用AES来加密需要传输的数据,AES加密需要传入两个参数,第一个是明文数据,第二个是3步生成出来的密钥

[java] view plain copy
  1. //再使用AES加密内容,传给服务器  
  2. String encryptContent = AES.encrypt(content, aesKey);  

6.第5步返回的字符串就是加密过后的数据,最后将4和5传给服务端,接下来就是服务端的事情了。


客户端传过来密文之后,接下来就需要服务端来解密了


JAVA解密

1.加载RSA私钥(这里的私钥是跟客户端的公钥是成对的)

[java] view plain copy
  1. //加载私钥  
  2. RSAPrivateKey privateKey = RSA.loadPrivateKey(new FileInputStream("G:/RSA密钥/pkcs8_rsa_private_key.pem"));  


2.通过RSA的私钥解密客户端传来的AES-KEY(也就是客户端的第4),因为这个key是加过密的,所以我们需要先将key解密成明文 [java] view plain copy
  1. //解密AES-KEY  
  2. String decryptAesKey = RSA.decryptByPrivateKey(aesKey, privateKey);  

3.AES-KEY加密成明文之后,现在可以拿这个key来解密客户端传过来的数据了 [java] view plain copy
  1. //AES解密数据  
  2. String decrypt = AES.decrypt(content, decryptAesKey);  


RSA-AES混合加密就是这个样子,有什么问题请跟帖回复,我会继续改进


最后附上完整demo

http://download.csdn.net/detail/aa464971/9478798

更多相关文章

  1. Android下面的MD5加密
  2. Android:TextUtils类介绍以及常见使用
  3. Android(安卓)Studio中图片的格式转换
  4. Android(安卓)Studio中src/main/res/values中strings.xml文件中
  5. Android(安卓)Studio——Android(安卓)TextUtils类介绍
  6. Android版本的RSA非对称加密实现
  7. Android连接指定的wifi热点
  8. Android(安卓)连接加密网络
  9. Android(安卓)TextView设置一个或多个关键字的颜色

随机推荐

  1. 在项目之间共享ASP.NET MVC部分视图
  2. 获取拆分字符串数组的最后一个元素
  3. 我可以更改javascript“this”的上下文吗
  4. FusionCharts的Line.swf做法,我想出现2条
  5. jQuery:执行一个函数AFTER toggleClass被
  6. jquery 更改angularJS input 内容导致绑
  7. 等待执行所有ajax回调的最佳解决方案
  8. AngularJs location.path没有传递参数
  9. « VS 2010 和 .NET 4.0 系列之《VS 2010
  10. 在多个文件中需要相同的模块