转载请注明出处:

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. Angularjs: 封装layDate指令

    [摘要]由于业务需要,将bootstrap-datetimepicker改成了layDate. layDate是一个较成熟且便于操作的jQuery日期插件,支持同一个视图内范围选择.封装成一个指令在多 ...

  2. NOI2018归程(Kruskal重构树)

    题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n). 我们依次用 l,a 描述一条边的长度. ...

  3. JavaScript学习总结(2)——JavaScript数据类型判断

    最近做项目中遇到了一些关于javascript数据类型的判断处理,上网找了一下资料,并且亲自验证了各种数据类型的判断,在此做一个总结吧! 一.JS中的数据类型  1.数值型(Number):包括整数. ...

  4. Native开发与JNI机制详解

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 文/李森 博主导读:博主不是代码大师,研究什么都很深,Java除外,所以无论什么问题,方案可以提供, ...

  5. [Vue + TS] Use Dependency Injection in Vue Using @Inject and @Provide Decorators with TypeScript

    Vue 2.2 introduced a simple dependency injection system, allowing you to use provide and inject in y ...

  6. javascript之Ajax起步

    XMLHttpRequest  readyState属性的值: UNSENT--0--已创建XMLHttpRequest对象. OPENED--1--已调用open方法: HEADERS_RECEIV ...

  7. php的数据类型和变量的作用域

    1)php支持例如以下所看到的的基本数据类型: Integer(整数).Float(浮点数).String(字符串).Boolean(布尔值).Array(数组).Object(对象),此外还有两个特 ...

  8. 103.tcp通信实现远程控制

    客户端代码 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include < ...

  9. HTTP请求报文、响应报文

    HTTP请求报文 HTTP请求报文由3部分组成(请求行+请求头+请求体): 请求行:①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE.HEAD.OPTIONS.PUT. ...

  10. HDOJ 5409 CRB and Graph 无向图缩块

    无向图缩块后,以n所在的块为根节点,dp找每块中的最大值. 对于每一个桥的答案为两块中的较小的最大值和较小的最大值加1 CRB and Graph Time Limit: 8000/4000 MS ( ...