该系列文章列表
1.网络及数据安全概念及领域概述
网络安全之数据加密/解密/签名/验签/数字证书
2.对称加密/解密算法
对称加密算法之高级数据加密标准-AES
对称加密之三重DES—DESede
对称加密算法之DES
3.非对称加密/解密算法
非对称加密算法概述
非对称加密之密钥交换算法-DH
非对称加密之RSA算法
非对称加密之Curve25519加密算法
4.其他加密解密算法
异或加密算法
5. 消息摘要算法
SHA安全散列算法
6. 数字证书
7. 网络安全协议
1. RSA算法简述
在DH算法的基础上,RSA算法、ElGamal算法及ECC算法等被提出。
RSA算法基于大数因子分解难题, 而ElGamal算法和ECC算法则是基于离散对数难题。
目前,主流计算机语言都提供了对RSA算法的支持。Java中可以很方便地构建该算法。
RSA在1978年,由麻省理工学院(MIT)的Ron Rivest、Adi Shamir和Leonard Adleman三位学者提出,以三位学者姓氏开头字母命名,被成为RSA算法。
RSA算法是唯一被广泛接受并实现的通用公开加密算法,目前已经成为非对称加密算法国际标准。RSA算法也被用于数字签名。
RSA想对于对称加密算法而言,其算法速度要慢得多。
RSA算法是最流行的公钥密码算法,使用长度可以变化的密钥。
2. 模型分析
下面以Alice与Bob双方收发消息为例,说明是RSA进行数据加密/解密的交互流程。这里Alice作为消息发送方,Bob作为消息接收方。Alice与Bob双方在消息传递之前已将RSA算法作为消息传递的加密算法。具体交互流程如下:
- 密钥构建及发布
步骤1、2为密钥构建及发布流程。
- 构建加密消息传递
步骤3、4、5为构建加密消息传递流程, Alice(发送者)向Bob(接收者)发送RSA算法加密数据
步骤6、7、8, Bob(接收者)向Alice(发送者)回复RSA算法加密的数据
特别说明:非对称加密算法领域中,对于私钥加密的数据只能使用公钥解密。对于公钥加密的数据,只能使用私钥解密。
简言之,“私钥加密,公钥解密”或者“公钥加密,私钥解密”。
在传递过程中,公钥可能被截获,截获的加码数据也可能被破解。所以要建立更安全的加密消息传递模型,就需要甲乙方构建两套非对称加密算法密钥,仅遵循“私钥加密,公钥解密”的方式进行加密消息传递。
3.代码实现
RSA算法较DH算法在密钥管理及实现上较为简单,一方面,甲方保留了私钥,而将公钥公布于乙方,甲乙双方密钥一一对应; 另一方面,私钥用于解密,公钥则用于加密,反之亦然。RSA算法仅需要一套密钥即可完成加密/解密操作。Java与Bouncy Castle都对RSA提供了实现,具体实现细节如下:
算法 | 密钥长度 | 密钥默认长度 | 工作模式 | 填充模式 | 备注 |
---|---|---|---|---|---|
RSA | 512~65536位(密钥长度必须是64的倍数) | 1024 | ECB | NoPadding、PKCS1Padding、OAEPWITHMD5AndMGF1Padding、 OAEPWITHSHA1AndMGF1Padding、OAEPWITHSHA256AndMGF1Padding、OAEPWITHSHA384AndMGF1Padding、OAEPWITHSHA512AndMGF1Padding | Java6 |
RSA | 512~65536位(密钥长度必须是64的倍数) | 2048 | NONE | NoPadding、PKCS1Padding、OAEPWITHMD5AndMGF1Padding、 OAEPWITHSHA1AndMGF1Padding、OAEPWITHSHA224AndMGF1Padding、OAEPWITHSHA256AndMGF1Padding、OAEPWITHSHA384AndMGF1Padding、OAEPWITHSHA512AndMGF1Padding、ISO9796-1Padding | Bouncy Castle实现 |
3.1 算法实现
算法基于Java的实现
package com.calvin.android.secrity;
/**
* Author:cl
* Email:lhzheng@grandstream.cn
* Date:20-10-20
*/
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
/**
* RSA安全编码组件
*/
public class RSACoder {
//密钥生成算法
public static final String KEY_ALGORITHM = "RSA";
//数据加密算法
public static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";//加密填充方式
//公钥 Map Key
private static final String PUBLIC_KEY = "RSAPublicKey";
//私钥Map key
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
* RSA密钥长度,默认1024位,密钥长度必须是64的倍数,范围512~65536位之间
*/
private static final int KEY_SIZE = 512;
/**
* 私钥解密
* @param data 待解密数据
* @param key 私钥
* @return byte[] 解密数据
* @throws Exception 异常
*/
public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
//取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
//对数据解密
//指定具体加密算法时 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 私钥加密
* @param data 待加密数据
* @param key 私钥
* @return byte[] 加密数据
* @throws Exception 异常
*/
public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
//取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
//对数据加密
//指定具体加密算法时 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 公钥解密
* @param data 待解密数据
* @param key 公钥
* @return byte[] 解密数据
* @throws Exception 异常
*/
public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {
//取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成公钥
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
//对数据解密
//指定具体加密算法时 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 公钥加密
* @param data 待加密数据
* @param key 公钥
* @return byte[] 加密数据
* @throws Exception 异常
*/
public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
//取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成公钥
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
//对数据解密
//指定具体加密算法时 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
public static Map<String, Object> initKey() throws Exception {
//实例化密钥对生成器
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
//初始化密钥对生辰其
keyPairGen.initialize(KEY_SIZE);
//生成密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
//公钥
RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
//私钥
RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
//封装密钥
Map<String, Object> keyMap = new HashMap<>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
public static byte[] getPublicKey(Map<String, Object> keyMap){
return ((RSAPublicKey)keyMap.get(PUBLIC_KEY)).getEncoded();
}
public static byte[] getPrivateKey(Map<String, Object> keyMap){
return ((RSAPrivateKey)keyMap.get(PRIVATE_KEY)).getEncoded();
}
}
3.2 测试代码
android 单元测试代码
@Test
public void RSATest() throws Exception {
//初始化密钥
Map<String, Object> keyMap = RSACoder.initKey();
byte[] publicKey = RSACoder.getPublicKey(keyMap);
byte[] privateKey = RSACoder.getPrivateKey(keyMap);
System.out.println("公钥:\n"+Base64.encodeToString(publicKey, Base64.DEFAULT));
System.out.println("私钥:\n"+Base64.encodeToString(privateKey, Base64.DEFAULT));
System.out.println("\n ----私钥加密--公钥解密----");
String inputStr1 = "RSA加密算法";
byte[] data1 = inputStr1.getBytes();
System.out.println("原文:\n "+inputStr1);
//加密
byte[] encodedData1 = RSACoder.encryptByPrivateKey(data1, privateKey);
System.out.println("加密后:\n "+Base64.encodeToString(encodedData1, Base64.DEFAULT));
//解密
byte[] decodedData1 = RSACoder.decryptByPublicKey(encodedData1, publicKey);
String outputStr1 = new String(decodedData1);
System.out.println("解密后:\n "+outputStr1);
assertEquals(inputStr1, outputStr1);
System.out.println("\n ----公钥加密--私钥解密----");
String inputStr2 = "RSA Encrypt Algorithm";
byte[] data2 = inputStr2.getBytes();
System.out.println("原文:\n "+inputStr2);
//加密
byte[] encodedData2 = RSACoder.encryptByPublicKey(data2, publicKey);
System.out.println("加密后:\n "+Base64.encodeToString(encodedData2, Base64.DEFAULT));
//解密
byte[] decodedData2 = RSACoder.decryptByPrivateKey(encodedData2, privateKey);
String outputStr2 = new String(decodedData2);
System.out.println("解密后:\n "+outputStr2);
//校验证
assertEquals(inputStr2, outputStr2);
}
3.3 测试结果
android7.0下的运行结果
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: 公钥:
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL5gzKOXMyj7+YAxYzxtjfmsWIviUATR/zTms4YoHGNu
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: gyia00naRS0QDm2Q0iMMWdwgEHrLQT6IoW+nnWWlqwcCAwEAAQ==
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: 私钥:
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEAvmDMo5czKPv5gDFjPG2N+axYi+JQ
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: BNH/NOazhigcY26DKJrTSdpFLRAObZDSIwxZ3CAQestBPoihb6edZaWrBwIDAQABAkAjy0tujqUd
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: 1ZJpmd+QowCIqvDTDDADWABlz+J9HNmJkBA5w/Npg3eu5rYIZo9mkOtEp8A74ghQIJrN1BeoiNHx
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: AiEA9Wr/At1DURtbHio3c9JKwBoI8EbU4clUqHTPGiWzDZ0CIQDGlkFqLTR+GKNCeIXf2amWUXbN
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: Biq5VLDGRx20+WIL8wIhAL0Y6U8Kr/DRtD6k5r9OfJxSMyr4WNV0bM+z2VPbUoCdAiEArnqj3NL8
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: 9PFWt/dGwIfwXZcTx01sykrjykH/ktstzwsCIQDETuncItM2NW3ol+G0woBElkaPrdANYhmWjOG9
2020-10-20 09:57:42.066 4810-4827/com.calvin.android.sample I/System.out: FOG4Lw==
2020-10-20 09:57:42.067 4810-4827/com.calvin.android.sample I/System.out: ----私钥加密--公钥解密----
2020-10-20 09:57:42.067 4810-4827/com.calvin.android.sample I/System.out: 原文:
2020-10-20 09:57:42.067 4810-4827/com.calvin.android.sample I/System.out: RSA加密算法
2020-10-20 09:57:42.071 4810-4827/com.calvin.android.sample I/System.out: 加密后:
2020-10-20 09:57:42.071 4810-4827/com.calvin.android.sample I/System.out: pOqsIefLKzH55AytuUzbxoTj9xpYdDfIqCHAF7f+/9KCEti/qMI4gc3Xbz7NWy7Y9qQxLKCBv9QU
2020-10-20 09:57:42.071 4810-4827/com.calvin.android.sample I/System.out: rmYcnyJ61A==
2020-10-20 09:57:42.072 4810-4827/com.calvin.android.sample I/System.out: 解密后:
2020-10-20 09:57:42.072 4810-4827/com.calvin.android.sample I/System.out: RSA加密算法
2020-10-20 09:57:42.072 4810-4827/com.calvin.android.sample I/System.out: ----公钥加密--私钥解密----
2020-10-20 09:57:42.072 4810-4827/com.calvin.android.sample I/System.out: 原文:
2020-10-20 09:57:42.072 4810-4827/com.calvin.android.sample I/System.out: RSA Encrypt Algorithm
2020-10-20 09:57:42.073 4810-4827/com.calvin.android.sample I/System.out: 加密后:
2020-10-20 09:57:42.073 4810-4827/com.calvin.android.sample I/System.out: IQovrNhy9tcV8BzT7kxeuACfh+wFkhUWjVHbJBsduGDZUmIygzJVNFQMeMj0pKNUIJilNOyvWjGs
2020-10-20 09:57:42.074 4810-4827/com.calvin.android.sample I/System.out: Q9sOAdEiWw==
2020-10-20 09:57:42.075 4810-4827/com.calvin.android.sample I/System.out: 解密后:
2020-10-20 09:57:42.075 4810-4827/com.calvin.android.sample I/System.out: RSA Encrypt Algorithm
4. 算法实现分析
RSA算法原理如下:
1.随机选择两个大质数p和q,p不等于q,计算N=pq;
2.选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素。
3.用公式计算出d:d×e = 1 (mod (p-1)(q-1)) 。
4.销毁p和q。
最终得到的N和e就是“公钥”,d就是“私钥”,发送方使用N去加密数据,接收方只有使用d才能解开数据内容。
RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算,使得RSA最快的情况也比DES慢上倍,这是RSA最大的缺陷,因此通常只能用于加密少量数据或者加密密钥,但RSA仍然不失为一种高强度的算法。
5. 数据分段处理
关于加密填充方式:之前以为上面这些操作就能实现rsa加解密,以为万事大吉了,呵呵,这事还没完,悲剧还是发生了,Android这边加密过的数据,服务器端死活解密不了,原来android系统的RSA实现是"RSA/None/NoPadding",而标准JDK实现是"RSA/None/PKCS1Padding" ,这造成了在android机上加密后无法在服务器上解密的原因,所以在实现的时候这个一定要注意。
public static final String RSA = "RSA";// 非对称加密密钥算法
public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式
实现分段加密:搞定了填充方式之后又自信的认为万事大吉了,可是意外还是发生了,RSA非对称加密内容长度有限制,1024位key的最多只能加密127位数据,否则就会报错(javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes) , RSA 是常用的非对称加密算法。最近使用时却出现了“不正确的长度”的异常,研究发现是由于待加密的数据超长所致。RSA 算法规定:待加密的字节数不能超过密钥的长度值除以 8 再减去 11(即:KeySize / 8 - 11),而加密后得到密文的字节数,正好是密钥的长度值除以 8(即:KeySize / 8)。
public static final int DEFAULT_KEY_SIZE = 2048;//秘钥默认长度
public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes(); // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密
public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;// 当前秘钥支持加密的最大字节数
公钥分段加密
/**
* 用公钥对字符串进行分段加密
*
*/
public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception {
int dataLen = data.length;
if (dataLen <= DEFAULT_BUFFERSIZE) {
return encryptByPublicKey(data, publicKey);
}
List<Byte> allBytes = new ArrayList<Byte>(2048);
int bufIndex = 0;
int subDataLoop = 0;
byte[] buf = new byte[DEFAULT_BUFFERSIZE];
for (int i = 0; i < dataLen; i++) {
buf[bufIndex] = data[i];
if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) {
subDataLoop++;
if (subDataLoop != 1) {
for (byte b : DEFAULT_SPLIT) {
allBytes.add(b);
}
}
byte[] encryptBytes = encryptByPublicKey(buf, publicKey);
for (byte b : encryptBytes) {
allBytes.add(b);
}
bufIndex = 0;
if (i == dataLen - 1) {
buf = null;
} else {
buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)];
}
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
私钥分段加密
/**
* 分段加密
*
* @param data 要加密的原始数据
* @param privateKey 秘钥
*/
public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception {
int dataLen = data.length;
if (dataLen <= DEFAULT_BUFFERSIZE) {
return encryptByPrivateKey(data, privateKey);
}
List<Byte> allBytes = new ArrayList<Byte>(2048);
int bufIndex = 0;
int subDataLoop = 0;
byte[] buf = new byte[DEFAULT_BUFFERSIZE];
for (int i = 0; i < dataLen; i++) {
buf[bufIndex] = data[i];
if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) {
subDataLoop++;
if (subDataLoop != 1) {
for (byte b : DEFAULT_SPLIT) {
allBytes.add(b);
}
}
byte[] encryptBytes = encryptByPrivateKey(buf, privateKey);
for (byte b : encryptBytes) {
allBytes.add(b);
}
bufIndex = 0;
if (i == dataLen - 1) {
buf = null;
} else {
buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)];
}
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
公钥分段解密
/**
* 公钥分段解密
*
* @param encrypted 待解密数据
* @param publicKey 密钥
*/
public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception {
int splitLen = DEFAULT_SPLIT.length;
if (splitLen <= 0) {
return decryptByPublicKey(encrypted, publicKey);
}
int dataLen = encrypted.length;
List<Byte> allBytes = new ArrayList<Byte>(1024);
int latestStartIndex = 0;
for (int i = 0; i < dataLen; i++) {
byte bt = encrypted[i];
boolean isMatchSplit = false;
if (i == dataLen - 1) {
// 到data的最后了
byte[] part = new byte[dataLen - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPublicKey(part, publicKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
} else if (bt == DEFAULT_SPLIT[0]) {
// 这个是以split[0]开头
if (splitLen > 1) {
if (i + splitLen < dataLen) {
// 没有超出data的范围
for (int j = 1; j < splitLen; j++) {
if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
break;
}
if (j == splitLen - 1) {
// 验证到split的最后一位,都没有break,则表明已经确认是split段
isMatchSplit = true;
}
}
}
} else {
// split只有一位,则已经匹配了
isMatchSplit = true;
}
}
if (isMatchSplit) {
byte[] part = new byte[i - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPublicKey(part, publicKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
私钥分段解密
/**
* 使用私钥分段解密
*
*/
public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception {
int splitLen = DEFAULT_SPLIT.length;
if (splitLen <= 0) {
return decryptByPrivateKey(encrypted, privateKey);
}
int dataLen = encrypted.length;
List<Byte> allBytes = new ArrayList<Byte>(1024);
int latestStartIndex = 0;
for (int i = 0; i < dataLen; i++) {
byte bt = encrypted[i];
boolean isMatchSplit = false;
if (i == dataLen - 1) {
// 到data的最后了
byte[] part = new byte[dataLen - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPrivateKey(part, privateKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
} else if (bt == DEFAULT_SPLIT[0]) {
// 这个是以split[0]开头
if (splitLen > 1) {
if (i + splitLen < dataLen) {
// 没有超出data的范围
for (int j = 1; j < splitLen; j++) {
if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
break;
}
if (j == splitLen - 1) {
// 验证到split的最后一位,都没有break,则表明已经确认是split段
isMatchSplit = true;
}
}
}
} else {
// split只有一位,则已经匹配了
isMatchSplit = true;
}
}
if (isMatchSplit) {
byte[] part = new byte[i - latestStartIndex];
System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
byte[] decryptPart = decryptByPrivateKey(part, privateKey);
for (byte b : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex - 1;
}
}
byte[] bytes = new byte[allBytes.size()];
{
int i = 0;
for (Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
return bytes;
}
这样总算把遇见的问题解决了,项目中使用的方案是客户端公钥加密,服务器私钥解密,服务器开发人员说是出于效率考虑,所以还是自己写了个程序测试一下真正的效率
第一步:准备100条对象数据
List<Person> personList=new ArrayList<>();
int testMaxCount=100;//测试的最大数据条数
//添加测试数据
for(int i=0;i<testMaxCount;i++){
Person person =new Person();
person.setAge(i);
person.setName(String.valueOf(i));
personList.add(person);
}
//FastJson生成json数据
String jsonData=JsonUtils.objectToJsonForFastJson(personList);
Log.e("MainActivity","加密前json数据 ---->"+jsonData);
Log.e("MainActivity","加密前json数据长度 ---->"+jsonData.length());
第二步生成秘钥对
KeyPair keyPair=RSAUtils.generateRSAKeyPair(RSAUtils.DEFAULT_KEY_SIZE);
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
接下来分别使用公钥加密 私钥解密 私钥加密 公钥解密
//公钥加密
long start=System.currentTimeMillis();
byte[] encryptBytes= RSAUtils.encryptByPublicKeyForSpilt(jsonData.getBytes(),publicKey.getEncoded());
long end=System.currentTimeMillis();
Log.e("MainActivity","公钥加密耗时 cost time---->"+(end-start));
String encryStr=Base64Encoder.encode(encryptBytes);
Log.e("MainActivity","加密后json数据 --1-->"+encryStr);
Log.e("MainActivity","加密后json数据长度 --1-->"+encryStr.length());
//私钥解密
start=System.currentTimeMillis();
byte[] decryptBytes= RSAUtils.decryptByPrivateKeyForSpilt(Base64Decoder.decodeToBytes(encryStr),privateKey.getEncoded());
String decryStr=new String(decryptBytes);
end=System.currentTimeMillis();
Log.e("MainActivity","私钥解密耗时 cost time---->"+(end-start));
Log.e("MainActivity","解密后json数据 --1-->"+decryStr);
//私钥加密
start=System.currentTimeMillis();
encryptBytes= RSAUtils.encryptByPrivateKeyForSpilt(jsonData.getBytes(),privateKey.getEncoded());
end=System.currentTimeMillis();
Log.e("MainActivity","私钥加密密耗时 cost time---->"+(end-start));
encryStr=Base64Encoder.encode(encryptBytes);
Log.e("MainActivity","加密后json数据 --2-->"+encryStr);
Log.e("MainActivity","加密后json数据长度 --2-->"+encryStr.length());
//公钥解密
start=System.currentTimeMillis();
decryptBytes= RSAUtils.decryptByPublicKeyForSpilt(Base64Decoder.decodeToBytes(encryStr),publicKey.getEncoded());
decryStr=new String(decryptBytes);
end=System.currentTimeMillis();
Log.e("MainActivity","公钥解密耗时 cost time---->"+(end-start));
Log.e("MainActivity","解密后json数据 --2-->"+decryStr);
运行结果:
对比发现:私钥的加解密都很耗时,所以可以根据不同的需求采用不能方案来进行加解密。个人觉得服务器要求解密效率高,客户端私钥加密,服务器公钥解密比较好一点
加密后数据大小的变化:数据量差不多是加密前的1.5倍