转载请注明出处:

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

本文以Androidclient加密提交数据到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.获取到client传过来的AES密钥密文和内容密文;

2.使用RSA私钥解密从client拿到的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的加密标准与JAVA的加密标准不一致导致,Android上的RSA实现是"RSA/None/NoPadding"。而标准JDK实现是"RSA/None/PKCS1Padding",这造成了在Android上加密后无法在server上解密

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

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加密内容。传给server
String encryptContent = AES.encrypt(content, aesKey);

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

client传过来密文之后,接下来就须要服务端来解密了

JAVA解密

1.载入RSA私钥(这里的私钥是跟client的公钥是成对的)

//载入私钥
RSAPrivateKey privateKey = RSA.loadPrivateKey(new FileInputStream("G:/RSA密钥/pkcs8_rsa_private_key.pem"));

2.通过RSA的私钥解密client传来的AES-KEY(也就是client的第4),由于这个key是加过密的,所以我们须要先将key解密成明文

//解密AES-KEY
String decryptAesKey = RSA.decryptByPrivateKey(aesKey, privateKey);

3.AES-KEY加密成明文之后,如今能够拿这个key来解密client传过来的数据了

//AES解密数据
String decrypt = AES.decrypt(content, decryptAesKey);

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

最后附上完整demo

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

Android交流群:146262062

Android接口安全 - RSA+AES混合加密方案的更多相关文章

  1. 学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密

      学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密 技术标签: RSA  AES  RSA AES  混合加密  整合   前言:   为了提高安全性采用了RS ...

  2. PHP 服务端 和 APP 客户端 实现 RSA+AES 双向加密解密

    目的:服务端和移动端双向加密解密 共有七个文件 其中包括三个类文件 lib_aes.php aes对称加密解密类 server_rsa_crypt.php 服务端RSA公钥私钥非对称加密解密类 cli ...

  3. 前后端API交互数据加密——AES与RSA混合加密完整实例

    前言 前段时间看到一篇文章讲如何保证API调用时数据的安全性(传送门:https://blog.csdn.net/ityouknow/article/details/80603617),文中讲到利用R ...

  4. AES和RSA混合加密技术在网络数据传输中的应用

    原文:http://www.fx361.com/page/2017/0110/519967.shtml          摘要:文章通过分析和比较AES加密算法和RsA加密算法的实现过程和各自的特点, ...

  5. WebSocket数据加密——AES与RSA混合加密

    前言 之前在写“一套简单的web即时通讯”,写到第三版的时候没什么思路,正好微信公众号看到一篇讲API交互加密,于是就自己搞了一套AES与RSA混合加密,无意中产生应用在WebSocket想法,好在思 ...

  6. Android数据加密之Rsa加密

    前言: 最近无意中和同事交流数据安全传输的问题,想起自己曾经使用过的Rsa非对称加密算法,闲下来总结一下. 其他几种加密方式: Android数据加密之Rsa加密 Android数据加密之Aes加密 ...

  7. Android数据库(sqlite)加密方案

    最近因为一些项目的安全性需要将数据库加密,一开始想到的就是先将数据库通过AES加密,然后运行时再解密,另一种是将数据库里的内容加密. 很快这两种方案都是不理想的,第一种加密方式形同虚设,第二种,如果加 ...

  8. polarssl rsa & aes 加密与解密

    上周折腾加密与解密,用了openssl, crypto++, polarssl, cyassl, 说起真的让人很沮丧,只有openssl & polarssl两个库的RSA & AES ...

  9. polarssl rsa & aes 加密与解密<转>

    上周折腾加密与解密,用了openssl, crypto++, polarssl, cyassl, 说起真的让人很沮丧,只有openssl & polarssl两个库的RSA & AES ...

随机推荐

  1. vue 刷新当前页面的方式

    1.使用window.location.href window.location.replace() window.location.reload() 会出现空白,体验不是很好 2.先进入一个空路由, ...

  2. Shiro学习总结(10)——Spring集成Shiro

    1.引入Shiro的Maven依赖 [html] view plain copy <!-- Spring 整合Shiro需要的依赖 --> <dependency> <g ...

  3. Node.js笔记(九)Nodejs与shell

    众所周知.Nodejs是单进程异步执行的.但不光是单进程,Nodejs也提供了多进程方面的支持 其创始人应该还是比較重视这一块的,最有力的证据就是child_process是Nodejs核心模块之中的 ...

  4. 【MongoDB】The connection between two tables

    In mongoDB, there are two general way to connect with two tables. Manual Connection and use DBRef 1. ...

  5. 【解决方法】Unexpected namespace prefix “xmlns” found for tag Layout

    问题描写叙述 出错代码例如以下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&quo ...

  6. 9. ZooKeeper之搭建单机模式。

    转自:https://blog.csdn.net/en_joker/article/details/78673456 在集群和单机两种模式下,我们基本完成了分别针对生产环境和开发环境ZooKeeper ...

  7. 105.UDP通信实现广播

    客户端 #include <stdio.h> #include <string.h> #include <winsock.h> #pragma comment(li ...

  8. Binary Search Algorithm

    二分查找代码: //============================================================================ // Name : Bin ...

  9. 16、cgminer学习之:popen函数和system函数详解(执行系统命令)

    1.popen函数我们先用man指令查一下popen函数: 函数说明: (1)popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令. (2) ...

  10. GO语言学习(八)Go 语言常量

    Go 语言常量 常量是一个简单值的标识符,在程序运行时,不会被修改的量. 常量中的数据类型只可以是布尔型.数字型(整数型.浮点型和复数)和字符串型. 常量的定义格式: const identifier ...