Android传输数据时Rsa加密解密详解
来源:互联网 发布:金英杰免费网络课2017 编辑:程序博客网 时间:2024/06/07 07:01
Android传输数据时Rsa加密解密详解
一、RSA加密算法
RSA加密算法是一种“非对称加密算法”。使用长度可以变化的密钥。RSA是第一个既能用于数据加密也能用于数字签名的算法。
RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算,是的RSA最快的情况也比DES慢,因此通常RSA只能用于加密少量数据或者加密密钥。
RSA算法原理:
1. 随机选择两个大质数p和q,计算N = p*q;
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才能解开数据内容。
二、加密注意事项
Android加密过的数据,服务端无法解密:
1. 加密填充方式不同
Android系统RSA实现是“RSA/None/NoPadding”
Java 的JDK实现是“RSA/None/PKCS1Padding”
注:加密填充方式选择“RSA/None/PKCS1Padding”
2. 实现分段加密
RSA非对称加密内容长度有限制,1024位key最多只能加密127位数据,否则会报错:javax.crypto.IllegalBlockSizeException:input must beunder 256 bytes,RSA是常用的非对称加密算法。出现“不正确长度”原因是待加密数据超长所致。
RSA算法规定:待加密的字节数不能超过密钥的长度值除以8再减去11,而加密后得到密文的字数,正好是密钥长度值除以8。
注:小数据可以不使用分段加密,一旦数据超过密钥支持最大字节数,使用分段加密。
3. 私钥加密和解密都很耗时,所以根据不同需求采用不同方案进行加解密。个人觉得因为服务器要求解密效率高,所以客户端私钥加密,服务器公钥解密比较好一点。加密之后数据大小差不多是加密前的1.5倍。
三、RSA加密算法实例
1. 设置变量
/**非对称加密密钥算法*/
public static finalString RSA= "RSA";
/** 加密填充方式*/
public static finalString ECB_PKCS1_PADDING= "RSA/ECB/PKCS1Padding";
/** 秘钥默认长度*/
public static final intDEFAULT_KEY_SIZE = 2048;
/** 当要加密的内容超过bufferSize,则采用partSplit进行分块加密*/
public static final byte[]DEFAULT_SPLIT = "#PART#".getBytes();
/** 当前秘钥支持加密的最大字节数*/
public static final intDEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE/ 8) - 11;
2. 生成密钥对
/**
* 随机生成RSA密钥对
*
* @param keyLength密钥长度,范围:512~2048 一般1024
* @return
*/
public static KeyPair generateRSAKeyPair(intkeyLength) {
try{
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(keyLength);
returnkpg.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);
returncp.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);
returnarr;
}
5. 私钥加密
/**
* 私钥加密
*
* @param data 待加密数据
* @param privateKey密钥
* @returnbyte[] 加密数据
*/
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);
returncipher.doFinal(data);
}
6. 公钥解密
/**
* 公钥解密
*
* @param data 待解密数据
* @param publicKey密钥
* @returnbyte[] 解密数据
*/
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);
returncipher.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 = newString(encryBytepri);
Log.e("Lking","RSA私钥解密---->"+pri);
} catch(Exception e) {
e.printStackTrace();
}
四、分段RSA加密算法实例
1. 设置变量
/**非对称加密密钥算法*/
public static finalString RSA= "RSA";
/** 加密填充方式*/
public static finalString ECB_PKCS1_PADDING= "RSA/ECB/PKCS1Padding";
/** 秘钥默认长度*/
public static final intDEFAULT_KEY_SIZE = 2048;
/** 当要加密的内容超过bufferSize,则采用partSplit进行分块加密*/
public static final byte[]DEFAULT_SPLIT = "#PART#".getBytes();
/** 当前秘钥支持加密的最大字节数*/
public static final intDEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE/ 8) - 11;
2. 生成密钥对
/**
* 随机生成RSA密钥对
*
* @param keyLength密钥长度,范围:512~2048
* 一般1024
* @return
*/
public static KeyPair generateRSAKeyPair(intkeyLength) {
try{
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(keyLength);
returnkpg.genKeyPair();
} catch(NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
3. 公钥分段加密
/**
* 用公钥对字符串进行分段加密
*
*/
public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey)throws Exception {
intdataLen = data.length;
if(dataLen <=DEFAULT_BUFFERSIZE) {
returnencryptByPublicKey(data, publicKey);
}
List<Byte> allBytes =new ArrayList<Byte>(2048);
intbufIndex =0;
intsubDataLoop =0;
byte[] buf =new byte[DEFAULT_BUFFERSIZE];
for(inti = 0; i < dataLen; i++) {
buf[bufIndex] = data[i];
if(++bufIndex ==DEFAULT_BUFFERSIZE|| i == dataLen -1) {
subDataLoop++;
if(subDataLoop !=1) {
for(byteb : DEFAULT_SPLIT) {
allBytes.add(b);
}
}
byte[] encryptBytes =encryptByPublicKey(buf, publicKey);
for(byteb : 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()];
{
inti = 0;
for(Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
returnbytes;
}
4. 私钥分段解密
/**
* 使用私钥分段解密
*
*/
public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey)throws Exception {
intsplitLen =DEFAULT_SPLIT.length;
if(splitLen <=0) {
returndecryptByPrivateKey(encrypted, privateKey);
}
intdataLen = encrypted.length;
List<Byte> allBytes =new ArrayList<Byte>(1024);
intlatestStartIndex =0;
for(inti = 0; i < dataLen; i++) {
bytebt = encrypted[i];
booleanisMatchSplit =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(byteb : 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(intj = 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(byteb : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex -1;
}
}
byte[] bytes =new byte[allBytes.size()];
{
inti = 0;
for(Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
returnbytes;
}
5. 私钥分段加密
/**
* 私钥分段加密
*
* @paramdata 要加密的原始数据
* @paramprivateKey 秘钥
*/
public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey)throws Exception {
intdataLen = data.length;
if(dataLen <=DEFAULT_BUFFERSIZE) {
returnencryptByPrivateKey(data, privateKey);
}
List<Byte> allBytes =new ArrayList<Byte>(2048);
intbufIndex =0;
intsubDataLoop =0;
byte[] buf =new byte[DEFAULT_BUFFERSIZE];
for(inti = 0; i < dataLen; i++) {
buf[bufIndex] = data[i];
if(++bufIndex ==DEFAULT_BUFFERSIZE|| i == dataLen -1) {
subDataLoop++;
if(subDataLoop !=1) {
for(byteb : DEFAULT_SPLIT) {
allBytes.add(b);
}
}
byte[] encryptBytes =encryptByPrivateKey(buf, privateKey);
for(byteb : 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()];
{
inti = 0;
for(Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
returnbytes;
}
6. 公钥分段解密
/**
* 公钥分段解密
*
* @paramencrypted 待解密数据
* @parampublicKey 密钥
*/
public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey)throws Exception {
intsplitLen =DEFAULT_SPLIT.length;
if(splitLen <=0) {
returndecryptByPublicKey(encrypted, publicKey);
}
intdataLen = encrypted.length;
List<Byte> allBytes =new ArrayList<Byte>(1024);
intlatestStartIndex =0;
for(inti = 0; i < dataLen; i++) {
bytebt = encrypted[i];
booleanisMatchSplit =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(byteb : 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(intj = 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(byteb : decryptPart) {
allBytes.add(b);
}
latestStartIndex = i + splitLen;
i = latestStartIndex -1;
}
}
byte[] bytes =new byte[allBytes.size()];
{
inti = 0;
for(Byte b : allBytes) {
bytes[i++] = b.byteValue();
}
}
returnbytes;
}
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();
}
- Android传输数据时Rsa加密解密详解
- Android传输数据时MD5加密解密详解
- Android传输数据时Des加密解密详解
- Android传输数据时Aes加密解密详解
- java RSA 加密解密传输
- RSA加密解密详解
- RSA 数据加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- Android RSA加密解密
- java.lang.UnsupportedClassVersionError: Bad version number in .class file
- 我的第一篇博客
- select2默认选中
- 出勤记录I (水道DP)
- java的递归和copy文件艺术
- Android传输数据时Rsa加密解密详解
- RESTful API 设计最佳实践
- java抽象类和抽象方法之间的关系
- #ifndef..#define..#endif和#pragma once的区别
- Java NIO 之 Buffer
- Android设计模式学习(包含Java设计模式)-Builder模式-AJDesignMode03
- Python数据处理pandas、numpy等第三方库函数笔记(持续更新)
- Windows重装系统
- oracle超出打开游标的最大数的原因和解决方案