转载请注明出处:
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上通用
- package com.dyhdyh.encrypt;
- import java.io.UnsupportedEncodingException;
- import java.security.NoSuchAlgorithmException;
- import java.security.SecureRandom;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.SecretKeySpec;
- /**
- * AES
- * @author dengyuhan
- * @create 2016/3/31 15:43
- */
- public class AES {
- // /** 算法/模式/填充 **/
- private static final String CipherMode = "AES/ECB/PKCS5Padding";
- // private static final String CipherMode = "AES";
- /**
- * 生成一个AES密钥对象
- * @return
- */
- public static SecretKeySpec generateKey(){
- try {
- KeyGenerator kgen = KeyGenerator.getInstance("AES");
- kgen.init(128, new SecureRandom());
- SecretKey secretKey = kgen.generateKey();
- byte[] enCodeFormat = secretKey.getEncoded();
- SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
- return key;
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 生成一个AES密钥字符串
- * @return
- */
- public static String generateKeyString(){
- return byte2hex(generateKey().getEncoded());
- }
- /**
- * 加密字节数据
- * @param content
- * @param key
- * @return
- */
- public static byte[] encrypt(byte[] content,byte[] key) {
- try {
- Cipher cipher = Cipher.getInstance(CipherMode);
- cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
- byte[] result = cipher.doFinal(content);
- return result;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 通过byte[]类型的密钥加密String
- * @param content
- * @param key
- * @return 16进制密文字符串
- */
- public static String encrypt(String content,byte[] key) {
- try {
- Cipher cipher = Cipher.getInstance(CipherMode);
- cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
- byte[] data = cipher.doFinal(content.getBytes("UTF-8"));
- String result = byte2hex(data);
- return result;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 通过String类型的密钥加密String
- * @param content
- * @param key
- * @return 16进制密文字符串
- */
- public static String encrypt(String content,String key) {
- byte[] data = null;
- try {
- data = content.getBytes("UTF-8");
- } catch (Exception e) {
- e.printStackTrace();
- }
- data = encrypt(data,new SecretKeySpec(hex2byte(key), "AES").getEncoded());
- String result = byte2hex(data);
- return result;
- }
- /**
- * 通过byte[]类型的密钥解密byte[]
- * @param content
- * @param key
- * @return
- */
- public static byte[] decrypt(byte[] content,byte[] key) {
- try {
- Cipher cipher = Cipher.getInstance(CipherMode);
- cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
- byte[] result = cipher.doFinal(content);
- return result;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 通过String类型的密钥 解密String类型的密文
- * @param content
- * @param key
- * @return
- */
- public static String decrypt(String content, String key) {
- byte[] data = null;
- try {
- data = hex2byte(content);
- } catch (Exception e) {
- e.printStackTrace();
- }
- data = decrypt(data, hex2byte(key));
- if (data == null)
- return null;
- String result = null;
- try {
- result = new String(data, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return result;
- }
- /**
- * 通过byte[]类型的密钥 解密String类型的密文
- * @param content
- * @param key
- * @return
- */
- public static String decrypt(String content,byte[] key) {
- try {
- Cipher cipher = Cipher.getInstance(CipherMode);
- cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(key, "AES"));
- byte[] data = cipher.doFinal(hex2byte(content));
- return new String(data, "UTF-8");
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 字节数组转成16进制字符串
- * @param b
- * @return
- */
- public static String byte2hex(byte[] b) { // 一个字节的数,
- StringBuffer sb = new StringBuffer(b.length * 2);
- String tmp = "";
- for (int n = 0; n < b.length; n++) {
- // 整数转成十六进制表示
- tmp = (Integer.toHexString(b[n] & 0XFF));
- if (tmp.length() == 1) {
- sb.append("0");
- }
- sb.append(tmp);
- }
- return sb.toString().toUpperCase(); // 转成大写
- }
- /**
- * 将hex字符串转换成字节数组
- * @param inputString
- * @return
- */
- private static byte[] hex2byte(String inputString) {
- if (inputString == null || inputString.length() < 2) {
- return new byte[0];
- }
- inputString = inputString.toLowerCase();
- int l = inputString.length() / 2;
- byte[] result = new byte[l];
- for (int i = 0; i < l; ++i) {
- String tmp = inputString.substring(2 * i, 2 * i + 2);
- result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);
- }
- return result;
- }
- }
Android - RSA实现
- package com.dyhdyh.encrypt;
- import android.util.Base64;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.security.KeyFactory;
- import java.security.NoSuchAlgorithmException;
- import java.security.interfaces.RSAPrivateKey;
- import java.security.interfaces.RSAPublicKey;
- import java.security.spec.InvalidKeySpecException;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.security.spec.X509EncodedKeySpec;
- import javax.crypto.Cipher;
- /**
- * 用于Android平台的RSA加密解密
- *
- * @desc
- * @author dengyuhan
- * @create 2016-3-31 下午2:36:18
- */
- public class RSA {
- private static final String ALGORITHM = "RSA";
- private static final String TRANSFORMATION = "RSA";
- /**
- * 从文件中输入流中加载公钥
- *
- * @param in
- * 公钥输入流
- * @throws Exception
- * 加载公钥时产生的异常
- */
- public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {
- try {
- BufferedReader br = new BufferedReader(new InputStreamReader(in));
- String readLine = null;
- StringBuilder sb = new StringBuilder();
- while ((readLine = br.readLine()) != null) {
- if (readLine.charAt(0) == '-') {
- continue;
- } else {
- sb.append(readLine);
- sb.append('\r');
- }
- }
- return loadPublicKey(sb.toString());
- } catch (IOException e) {
- throw new Exception("公钥数据流读取错误");
- } catch (NullPointerException e) {
- throw new Exception("公钥输入流为空");
- }
- }
- /**
- * 从字符串中加载公钥
- *
- * @param publicKeyStr
- * 公钥数据字符串
- * @return
- * @throws Exception
- * 加载公钥时产生的异常
- */
- public static RSAPublicKey loadPublicKey(String publicKeyStr)
- throws Exception {
- try {
- byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);
- KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
- return (RSAPublicKey) keyFactory.generatePublic(keySpec);
- } catch (NoSuchAlgorithmException e) {
- throw new Exception("无此算法");
- } catch (InvalidKeySpecException e) {
- throw new Exception("公钥非法");
- }catch (NullPointerException e) {
- throw new Exception("公钥数据为空");
- }
- }
- /**
- * 从文件中加载私钥
- *
- * @param in
- * 私钥输入流
- * @return
- * @throws Exception
- */
- public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {
- try {
- BufferedReader br = new BufferedReader(new InputStreamReader(in));
- String readLine = null;
- StringBuilder sb = new StringBuilder();
- while ((readLine = br.readLine()) != null) {
- if (readLine.charAt(0) == '-') {
- continue;
- } else {
- sb.append(readLine);
- sb.append('\r');
- }
- }
- return loadPrivateKey(sb.toString());
- } catch (IOException e) {
- throw new Exception("私钥数据读取错误");
- } catch (NullPointerException e) {
- throw new Exception("私钥输入流为空");
- }
- }
- /**
- * 从字符串中加载私钥
- *
- * @desc
- * @param privateKeyStr
- * 私钥字符串
- * @return
- * @throws Exception
- */
- public static RSAPrivateKey loadPrivateKey(String privateKeyStr)
- throws Exception {
- try {
- byte[] buffer = Base64.decode(privateKeyStr, Base64.DEFAULT);
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
- KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
- return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
- } catch (NoSuchAlgorithmException e) {
- throw new Exception("无此算法");
- } catch (InvalidKeySpecException e) {
- throw new Exception("私钥非法");
- }catch (NullPointerException e) {
- throw new Exception("私钥数据为空");
- }
- }
- /**
- * 公钥加密
- *
- * @param data
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
- throws Exception {
- // 模长
- int key_len = publicKey.getModulus().bitLength() / 8;
- // 加密数据长度 <= 模长-11
- String[] datas = splitString(data, key_len - 11);
- String mi = "";
- // 如果明文长度大于模长-11则要分组加密
- for (String s : datas) {
- mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));
- }
- return mi;
- }
- /**
- * 公钥加密
- * @desc
- * @param data
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)
- throws Exception {
- Cipher cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.ENCRYPT_MODE, publicKey);
- return cipher.doFinal(data);
- }
- /**
- * 私钥加密
- * @desc
- * @param data
- * @param privateKey
- * @return
- * @throws Exception
- */
- public static byte[] encryptByPrivateKey(byte[] data,
- RSAPrivateKey privateKey) throws Exception {
- Cipher cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.ENCRYPT_MODE, privateKey);
- return cipher.doFinal(data);
- }
- /**
- * 私钥加密
- * @desc
- * @param data
- * @param privateKey
- * @return
- * @throws Exception
- */
- public static String encryptByPrivateKey(String data,
- RSAPrivateKey privateKey) throws Exception {
- // 模长
- int key_len = privateKey.getModulus().bitLength() / 8;
- // 加密数据长度 <= 模长-11
- String[] datas = splitString(data, key_len - 11);
- String mi = "";
- // 如果明文长度大于模长-11则要分组加密
- for (String s : datas) {
- mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));
- }
- return mi;
- }
- /**
- * 私钥解密
- *
- * @param data
- * @param privateKey
- * @return
- * @throws Exception
- */
- public static String decryptByPrivateKey(String data,
- RSAPrivateKey privateKey) throws Exception {
- // 模长
- int key_len = privateKey.getModulus().bitLength() / 8;
- byte[] bytes = data.getBytes();
- byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
- // 如果密文长度大于模长则要分组解密
- String ming = "";
- byte[][] arrays = splitArray(bcd, key_len);
- for (byte[] arr : arrays) {
- ming += new String(decryptByPrivateKey(arr, privateKey));
- }
- return ming;
- }
- /**
- * 私钥解密
- * @desc
- * @param data
- * @param privateKey
- * @return
- * @throws Exception
- */
- public static byte[] decryptByPrivateKey(byte[] data,
- RSAPrivateKey privateKey) throws Exception {
- Cipher cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- return cipher.doFinal(data);
- }
- /**
- * 公钥解密
- * @desc
- * @param data
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static String decryptByPublicKey(String data,
- RSAPublicKey publicKey) throws Exception {
- // 模长
- int key_len = publicKey.getModulus().bitLength() / 8;
- byte[] bytes = data.getBytes();
- byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
- // 如果密文长度大于模长则要分组解密
- String ming = "";
- byte[][] arrays = splitArray(bcd, key_len);
- for (byte[] arr : arrays) {
- ming += new String(decryptByPublicKey(arr, publicKey));
- }
- return ming;
- }
- /**
- * 公钥解密
- * @desc
- * @param data
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static byte[] decryptByPublicKey(byte[] data,
- RSAPublicKey publicKey) throws Exception {
- Cipher cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.DECRYPT_MODE, publicKey);
- return cipher.doFinal(data);
- }
- /**
- * ASCII码转BCD码
- *
- */
- private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
- byte[] bcd = new byte[asc_len / 2];
- int j = 0;
- for (int i = 0; i < (asc_len + 1) / 2; i++) {
- bcd[i] = asc_to_bcd(ascii[j++]);
- bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
- }
- return bcd;
- }
- private static byte asc_to_bcd(byte asc) {
- byte bcd;
- if ((asc >= '0') && (asc <= '9'))
- bcd = (byte) (asc - '0');
- else if ((asc >= 'A') && (asc <= 'F'))
- bcd = (byte) (asc - 'A' + 10);
- else if ((asc >= 'a') && (asc <= 'f'))
- bcd = (byte) (asc - 'a' + 10);
- else
- bcd = (byte) (asc - 48);
- return bcd;
- }
- /**
- * BCD转字符串
- */
- private static String bcd2Str(byte[] bytes) {
- char temp[] = new char[bytes.length * 2], val;
- for (int i = 0; i < bytes.length; i++) {
- val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
- temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
- val = (char) (bytes[i] & 0x0f);
- temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
- }
- return new String(temp);
- }
- /**
- * 拆分字符串
- */
- private static String[] splitString(String string, int len) {
- int x = string.length() / len;
- int y = string.length() % len;
- int z = 0;
- if (y != 0) {
- z = 1;
- }
- String[] strings = new String[x + z];
- String str = "";
- for (int i = 0; i < x + z; i++) {
- if (i == x + z - 1 && y != 0) {
- str = string.substring(i * len, i * len + y);
- } else {
- str = string.substring(i * len, i * len + len);
- }
- strings[i] = str;
- }
- return strings;
- }
- /**
- * 拆分数组
- */
- private static byte[][] splitArray(byte[] data, int len) {
- int x = data.length / len;
- int y = data.length % len;
- int z = 0;
- if (y != 0) {
- z = 1;
- }
- byte[][] arrays = new byte[x + z][];
- byte[] arr;
- for (int i = 0; i < x + z; i++) {
- arr = new byte[len];
- if (i == x + z - 1 && y != 0) {
- System.arraycopy(data, i * len, arr, 0, y);
- } else {
- System.arraycopy(data, i * len, arr, 0, len);
- }
- arrays[i] = arr;
- }
- return arrays;
- }
- }
JAVA - RSA实现
- package com.dyhdyh.encrypt;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.security.KeyFactory;
- import java.security.NoSuchAlgorithmException;
- import java.security.interfaces.RSAPrivateKey;
- import java.security.interfaces.RSAPublicKey;
- import java.security.spec.InvalidKeySpecException;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.security.spec.X509EncodedKeySpec;
- import javax.crypto.Cipher;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- import sun.misc.BASE64Decoder;
- /**
- * 用于java平台的RSA加密解密
- *
- * @desc
- * @author dengyuhan
- * @create 2016-3-31 下午2:36:18
- */
- public class RSA {
- private static final String ALGORITHM = "RSA";
- private static final String TRANSFORMATION = "RSA";
- /**
- * 从文件中输入流中加载公钥
- *
- * @param in
- * 公钥输入流
- * @throws Exception
- * 加载公钥时产生的异常
- */
- public static RSAPublicKey loadPublicKey(InputStream in) throws Exception {
- try {
- BufferedReader br = new BufferedReader(new InputStreamReader(in));
- String readLine = null;
- StringBuilder sb = new StringBuilder();
- while ((readLine = br.readLine()) != null) {
- if (readLine.charAt(0) == '-') {
- continue;
- } else {
- sb.append(readLine);
- sb.append('\r');
- }
- }
- return loadPublicKey(sb.toString());
- } catch (IOException e) {
- throw new Exception("公钥数据流读取错误");
- } catch (NullPointerException e) {
- throw new Exception("公钥输入流为空");
- }
- }
- /**
- * 从字符串中加载公钥
- *
- * @param publicKeyStr
- * 公钥数据字符串
- * @return
- * @throws Exception
- * 加载公钥时产生的异常
- */
- public static RSAPublicKey loadPublicKey(String publicKeyStr)
- throws Exception {
- try {
- BASE64Decoder base64Decoder = new BASE64Decoder();
- byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);
- KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
- return (RSAPublicKey) keyFactory.generatePublic(keySpec);
- } catch (NoSuchAlgorithmException e) {
- throw new Exception("无此算法");
- } catch (InvalidKeySpecException e) {
- throw new Exception("公钥非法");
- } catch (IOException e) {
- throw new Exception("公钥数据内容读取错误");
- } catch (NullPointerException e) {
- throw new Exception("公钥数据为空");
- }
- }
- /**
- * 从文件中加载私钥
- *
- * @param in
- * 私钥输入流
- * @return
- * @throws Exception
- */
- public static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {
- try {
- BufferedReader br = new BufferedReader(new InputStreamReader(in));
- String readLine = null;
- StringBuilder sb = new StringBuilder();
- while ((readLine = br.readLine()) != null) {
- if (readLine.charAt(0) == '-') {
- continue;
- } else {
- sb.append(readLine);
- sb.append('\r');
- }
- }
- return loadPrivateKey(sb.toString());
- } catch (IOException e) {
- throw new Exception("私钥数据读取错误");
- } catch (NullPointerException e) {
- throw new Exception("私钥输入流为空");
- }
- }
- /**
- * 从字符串中加载私钥
- *
- * @desc
- * @param privateKeyStr
- * 私钥字符串
- * @return
- * @throws Exception
- */
- public static RSAPrivateKey loadPrivateKey(String privateKeyStr)
- throws Exception {
- try {
- BASE64Decoder base64Decoder = new BASE64Decoder();
- byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
- KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
- return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
- } catch (NoSuchAlgorithmException e) {
- throw new Exception("无此算法");
- } catch (InvalidKeySpecException e) {
- throw new Exception("私钥非法");
- } catch (IOException e) {
- throw new Exception("私钥数据内容读取错误");
- } catch (NullPointerException e) {
- throw new Exception("私钥数据为空");
- }
- }
- /**
- * 公钥加密
- *
- * @param data
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
- throws Exception {
- // 模长
- int key_len = publicKey.getModulus().bitLength() / 8;
- // 加密数据长度 <= 模长-11
- String[] datas = splitString(data, key_len - 11);
- String mi = "";
- // 如果明文长度大于模长-11则要分组加密
- for (String s : datas) {
- mi += bcd2Str(encryptByPublicKey(s.getBytes(), publicKey));
- }
- return mi;
- }
- /**
- * 公钥加密
- * @desc
- * @param data
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey)
- throws Exception {
- Cipher cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.ENCRYPT_MODE, publicKey);
- return cipher.doFinal(data);
- }
- /**
- * 私钥加密
- * @desc
- * @param data
- * @param privateKey
- * @return
- * @throws Exception
- */
- public static byte[] encryptByPrivateKey(byte[] data,
- RSAPrivateKey privateKey) throws Exception {
- Cipher cipher = Cipher.getInstance(TRANSFORMATION);
- cipher.init(Cipher.ENCRYPT_MODE, privateKey);
- return cipher.doFinal(data);
- }
- /**
- * 私钥加密
- * @desc
- * @param data
- * @param privateKey
- * @return
- * @throws Exception
- */
- public static String encryptByPrivateKey(String data,
- RSAPrivateKey privateKey) throws Exception {
- // 模长
- int key_len = privateKey.getModulus().bitLength() / 8;
- // 加密数据长度 <= 模长-11
- String[] datas = splitString(data, key_len - 11);
- String mi = "";
- // 如果明文长度大于模长-11则要分组加密
- for (String s : datas) {
- mi += bcd2Str(encryptByPrivateKey(s.getBytes(), privateKey));
- }
- return mi;
- }
- /**
- * 私钥解密
- *
- * @param data
- * @param privateKey
- * @return
- * @throws Exception
- */
- public static String decryptByPrivateKey(String data,
- RSAPrivateKey privateKey) throws Exception {
- // 模长
- int key_len = privateKey.getModulus().bitLength() / 8;
- byte[] bytes = data.getBytes();
- byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
- // 如果密文长度大于模长则要分组解密
- String ming = "";
- byte[][] arrays = splitArray(bcd, key_len);
- for (byte[] arr : arrays) {
- ming += new String(decryptByPrivateKey(arr, privateKey));
- }
- return ming;
- }
- /**
- * 私钥解密
- * @desc
- * @param data
- * @param privateKey
- * @return
- * @throws Exception
- */
- public static byte[] decryptByPrivateKey(byte[] data,
- RSAPrivateKey privateKey) throws Exception {
- Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider());
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- return cipher.doFinal(data);
- }
- /**
- * 公钥解密
- * @desc
- * @param data
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static String decryptByPublicKey(String data,
- RSAPublicKey publicKey) throws Exception {
- // 模长
- int key_len = publicKey.getModulus().bitLength() / 8;
- byte[] bytes = data.getBytes();
- byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
- // 如果密文长度大于模长则要分组解密
- String ming = "";
- byte[][] arrays = splitArray(bcd, key_len);
- for (byte[] arr : arrays) {
- ming += new String(decryptByPublicKey(arr, publicKey));
- }
- return ming;
- }
- /**
- * 公钥解密
- * @desc
- * @param data
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static byte[] decryptByPublicKey(byte[] data,
- RSAPublicKey publicKey) throws Exception {
- Cipher cipher = Cipher.getInstance(TRANSFORMATION,new BouncyCastleProvider());
- cipher.init(Cipher.DECRYPT_MODE, publicKey);
- return cipher.doFinal(data);
- }
- /**
- * ASCII码转BCD码
- *
- */
- private static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
- byte[] bcd = new byte[asc_len / 2];
- int j = 0;
- for (int i = 0; i < (asc_len + 1) / 2; i++) {
- bcd[i] = asc_to_bcd(ascii[j++]);
- bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
- }
- return bcd;
- }
- private static byte asc_to_bcd(byte asc) {
- byte bcd;
- if ((asc >= '0') && (asc <= '9'))
- bcd = (byte) (asc - '0');
- else if ((asc >= 'A') && (asc <= 'F'))
- bcd = (byte) (asc - 'A' + 10);
- else if ((asc >= 'a') && (asc <= 'f'))
- bcd = (byte) (asc - 'a' + 10);
- else
- bcd = (byte) (asc - 48);
- return bcd;
- }
- /**
- * BCD转字符串
- */
- private static String bcd2Str(byte[] bytes) {
- char temp[] = new char[bytes.length * 2], val;
- for (int i = 0; i < bytes.length; i++) {
- val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
- temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
- val = (char) (bytes[i] & 0x0f);
- temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
- }
- return new String(temp);
- }
- /**
- * 拆分字符串
- */
- private static String[] splitString(String string, int len) {
- int x = string.length() / len;
- int y = string.length() % len;
- int z = 0;
- if (y != 0) {
- z = 1;
- }
- String[] strings = new String[x + z];
- String str = "";
- for (int i = 0; i < x + z; i++) {
- if (i == x + z - 1 && y != 0) {
- str = string.substring(i * len, i * len + y);
- } else {
- str = string.substring(i * len, i * len + len);
- }
- strings[i] = str;
- }
- return strings;
- }
- /**
- * 拆分数组
- */
- private static byte[][] splitArray(byte[] data, int len) {
- int x = data.length / len;
- int y = data.length % len;
- int z = 0;
- if (y != 0) {
- z = 1;
- }
- byte[][] arrays = new byte[x + z][];
- byte[] arr;
- for (int i = 0; i < x + z; i++) {
- arr = new byte[len];
- if (i == x + z - 1 && y != 0) {
- System.arraycopy(data, i * len, arr, 0, y);
- } else {
- System.arraycopy(data, i * len, arr, 0, len);
- }
- arrays[i] = arr;
- }
- return arrays;
- }
- }
JAVA的RSA跟Android的RSA有所不同:
1.加载key的时候,JAVA上用的是BASE64Decoder
- BASE64Decoder base64Decoder = new BASE64Decoder();
- byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);
而Android上用的Base64,这个地方只是API不一样,作用是一样的
- byte[] buffer = Base64.decode(publicKeyStr, Base64.DEFAULT);
2.在JAVA平台上调用Cipher.getInstance()的时候,需要多传一个参数,也就是BouncyCastleProvider的实例:
- Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider());
这个类jdk上是没有的,所以需要添加一个jar包bcprov-jdk15-143.jar
如果不这样做,JAVA上解密的时候就会抛出一个BadPaddingException
- Exception in thread "main" javax.crypto.BadPaddingException: Blocktype mismatch: 0
- at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:332)
- at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272)
- at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
- at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
- at javax.crypto.Cipher.doFinal(Cipher.java:2087)
- at com.dyhdyh.encrypt.RSA.decryptByPrivateKey(RSA.java:255)
- at com.dyhdyh.encrypt.RSA.decryptByPrivateKey(RSA.java:238)
最后来看看怎样混合加密(这里只举一种方式,附件里有完整的)
Android上加密
1.将openssl生成出来的公钥,放入assets文件夹内(不一定要放这里,只要能拿到文件内容就行)。
2.加载放在assets文件里的公钥
- //加载RSA公钥
- RSAPublicKey rsaPublicKey = RSA.loadPublicKey(getAssets().open("rsa_public_key.pem"));
3.再生成一个AES的密钥,用于AES加密
- //生成一个AES密钥
- String aesKey=AES.generateKeyString();
4.通过RSA的公钥来加密刚刚生成的AES密钥
- //用RSA公钥加密AES的密钥
- String encryptAesKey = RSA.encryptByPublicKey(aesKey, rsaPublicKey);
5.最后使用AES来加密需要传输的数据,AES加密需要传入两个参数,第一个是明文数据,第二个是3步生成出来的密钥
- //再使用AES加密内容,传给服务器
- String encryptContent = AES.encrypt(content, aesKey);
6.第5步返回的字符串就是加密过后的数据,最后将4和5传给服务端,接下来就是服务端的事情了。
客户端传过来密文之后,接下来就需要服务端来解密了
JAVA解密
1.加载RSA私钥(这里的私钥是跟客户端的公钥是成对的)
- //加载私钥
- RSAPrivateKey privateKey = RSA.loadPrivateKey(new FileInputStream("G:/RSA密钥/pkcs8_rsa_private_key.pem"));
- //解密AES-KEY
- String decryptAesKey = RSA.decryptByPrivateKey(aesKey, privateKey);
3.AES-KEY加密成明文之后,现在可以拿这个key来解密客户端传过来的数据了
- //AES解密数据
- String decrypt = AES.decrypt(content, decryptAesKey);
RSA-AES混合加密就是这个样子,有什么问题请跟帖回复,我会继续改进
最后附上完整demo