Android传输数据时Rsa加密解密详解

论坛 期权论坛 脚本     
匿名网站用户   2020-12-21 09:33   15   0

Android传输数据时Rsa加密解密详解

一、RSA加密算法

RSA加密算法是一种“非对称加密算法”。使用长度可以变化的密钥。RSA是第一个既能用于数据加密也能用于数字签名的算法。

RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算,是的RSA最快的情况也比DES慢,因此通常RSA只能用于加密少量数据或者加密密钥。

RSA算法原理:

1.随机选择两个大质数pq,计算N = p*q;

2.选择一个大于1小于N的自然数ee必须与(p-1)(q-1)互素

3.用公式计算出d: d*e = 1(mod(p-1)(q-1))

4.销毁pq

最终得到的Ne就是“公钥”,d就是“私钥”;发送方使用N去加密数据,接收方只有使用d才能解开数据内容。

二、加密注意事项

Android加密过的数据,服务端无法解密:

1.加密填充方式不同

Android系统RSA实现是“RSA/None/NoPadding

Java JDK实现是“RSA/None/PKCS1Padding

注:加密填充方式选择RSA/None/PKCS1Padding

2.实现分段加密

RSA非对称加密内容长度有限制,1024key最多只能加密127位数据,否则会报错:javax.crypto.IllegalBlockSizeException: inputmust be under 256bytesRSA是常用的非对称加密算法。出现“不正确长度”原因是待加密数据超长所致。

RSA算法规定:待加密的字节数不能超过密钥的长度值除以8再减去11,而加密后得到密文的字数,正好是密钥长度值除以8。

注:小数据可以不使用分段加密,一旦数据超过密钥支持最大字节数,使用分段加密。

3.私钥加密和解密都很耗时,所以根据不同需求采用不同方案进行加解密。个人觉得因为服务器要求解密效率高,所以客户端私钥加密,服务器公钥解密比较好一点。加密之后数据大小差不多是加密前的1.5倍。

三、RSA加密算法实例

1.设置变量

/** 非对称加密密钥算法*/
public static final String RSA = "RSA";
/** 加密填充方式*/
public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";
/** 秘钥默认长度*/
public static final int DEFAULT_KEY_SIZE = 2048;
/** 当要加密的内容超过bufferSize,则采用partSplit进行分块加密*/
public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes();
/** 当前秘钥支持加密的最大字节数*/
public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;

2.生成密钥对

/**
* 随机生成RSA密钥对
*
*
@param keyLength 密钥长度,范围:5122048一般1024
*
@return
*/
public static KeyPair generateRSAKeyPair(int keyLength) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(keyLength);
return kpg.genKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}

3.公钥加密

/**
* 用公钥对字符串进行加密
*
*
@param data 原文
*/
public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
// 得到公钥
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PublicKey keyPublic = kf.generatePublic(keySpec);
// 加密数据
Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
cp.init(Cipher.ENCRYPT_MODE, keyPublic);
return cp.doFinal(data);
}

4.私钥解密

/**
* 使用私钥进行解密
*/
public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception {
// 得到私钥
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PrivateKey keyPrivate = kf.generatePrivate(keySpec);

// 解密数据
Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
cp.init(Cipher.DECRYPT_MODE, keyPrivate);
byte[] arr = cp.doFinal(encrypted);
return arr;
}

5.私钥加密

/**
* 私钥加密
*
*
@param data 待加密数据
*
@param privateKey 密钥
*
@return byte[] 加密数据
*/
public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
// 得到私钥
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PrivateKey keyPrivate = kf.generatePrivate(keySpec);
// 数据加密
Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
return cipher.doFinal(data);
}

6.公钥解密

/**
* 公钥解密
*
*
@param data 待解密数据
*
@param publicKey 密钥
*
@return byte[] 解密数据
*/
public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
// 得到公钥
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory kf = KeyFactory.getInstance(RSA);
PublicKey keyPublic = kf.generatePublic(keySpec);
// 数据解密
Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
cipher.init(Cipher.DECRYPT_MODE, keyPublic);
return cipher.doFinal(data);
}

7.加密解密实现

KeyPair keyPair = generateRSAKeyPair(DEFAULT_KEY_SIZE);
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

try {
//公钥加密
byte[] encryByte =
encryptByPublicKey("Lking".getBytes(),publicKey.getEncoded());
String encryBase64 = Base64.encodeToString(encryByte,Base64.DEFAULT);
Log.e("Lking","RSA公钥加密---->"+encryBase64);

//私钥解密
byte[] encryBytepri =
decryptByPrivateKey(Base64.decode(encryBase64,Base64.DEFAULT),
privateKey.getEncoded());
String pri = new String(encryBytepri);
Log.e("Lking","RSA私钥解密---->"+pri);
} catch (Exception e) {
e.printStackTrace();
}

四、分段RSA加密算法实例

1.设置变量

/** 非对称加密密钥算法*/
public static final String RSA = "RSA";
/** 加密填充方式*/
public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";
/** 秘钥默认长度*/
public static final int DEFAULT_KEY_SIZE = 2048;
/** 当要加密的内容超过bufferSize,则采用partSplit进行分块加密*/
public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes();
/** 当前秘钥支持加密的最大字节数*/
public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;

2.生成密钥对

/**
* 随机生成RSA密钥对
*
*
@param keyLength 密钥长度,范围:5122048
* 一般1024
*
@return
*/
public static KeyPair generateRSAKeyPair(int keyLength) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(keyLength);
return kpg.genKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}

3.公钥分段加密

/**
* 用公钥对字符串进行分段加密
*
*/
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;
}

4.私钥分段解密

/**
* 使用私钥分段解密
*
*/
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;
}

5.私钥分段加密

/**
* 私钥分段加密
*
*
@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;
}

6.公钥分段解密

/**
* 公钥分段解密
*
*
@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;
}

7.

KeyPair keyPair = generateRSAKeyPair(DEFAULT_KEY_SIZE);
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

try {
//公钥分段加密
byte[] encryByte =
encryptByPublicKeyForSpilt("大于秘钥支持加密的最大字节数...".getBytes(),

publicKey.getEncoded());
String encryBase64 = Base64.encodeToString(encryByte,Base64.DEFAULT);
Log.e("Lking","RSA公钥加密---->"+encryBase64);

//私钥分段解密
byte[] encryBytepri =
decryptByPrivateKeyForSpilt(Base64.decode(encryBase64,Base64.DEFAULT),
privateKey.getEncoded());
String pri = new String(encryBytepri);
Log.e("Lking","RSA私钥解密---->"+pri);
} catch (Exception e) {
e.printStackTrace();
}

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP