RSA加密解密以及内容超长时采用分段加密
1、在使用 RSA加密解密内容时会出现这样的异常 : Data must not be longer than 117 bytes。
解决办法是:分段加密和分段解密。
2、分段加密
/**
* @Title: RSAEncode
* @Description: 将字符串加密
* @param key
* @param data
* @return String
*/
public static String RSAEncode(String data, RSAPublicKey publicKey) {
byte[] b = data.getBytes();
try {
int inputLen = b.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(b, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(b, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return Base64.toBase64String(decryptedData);
} catch (Exception e) {
logger.error(e.getMessage());
}
return null;
}
3、分段解密
/**
* @Title: RSADecode
* @Description: 将字符串解密
* @param key
* @param encodedText
* @return String
*/
public static String RSADecode(String data, RSAPrivateKey privateKey) {
try {
byte[] b = Base64.decode(data);
int inputLen = b.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(b, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(b, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return new String(decryptedData);
} catch (Exception e) {
logger.error(e.getMessage());
}
return null;
}
3、当出现前端加解密没问题,后台加解密没问题,但是前端不能完全解密后台的密文,前端给的密文后台解不出的问题。
原因:前端和后台生产秘药对采用的补位方式不同,所以出现加解密失败。
解决方案:
使用模和指数生成RSA公钥 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA/None/NoPadding】
前端修改代码:
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
4、采用本方法生产的公私钥对,因为位数的问题对ios不适用的问题。
我们代码自己生产的秘钥对对ios不适用,需要让ios在端自己生产一份,我们来加解密,进行操作。
部分代码如下:
public static void main(String[] args) {
try {
Map<String, Object> map = RsaUtils.getKeys();
RSAPublicKey publicKey = (RSAPublicKey) map.get("public");
RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");
// 模
String modulus = publicKey.getModulus().toString();
logger.info("modulus:"+modulus);
// 公钥指数
String public_exponent = publicKey.getPublicExponent().toString();
logger.info("public_exponent:"+public_exponent);
// 私钥指数
String private_exponent = privateKey.getPrivateExponent().toString();
logger.info("private_exponent:"+private_exponent);
// 明文
String ming = "这是一段加密明文,可以很长的数据进行加密,采用分组加密";
// 使用模和指数生成公钥和私钥
RSAPublicKey pubKey = RsaUtils.getPublicKey(modulus, public_exponent);
RSAPrivateKey priKey = RsaUtils.getPrivateKey(modulus, private_exponent);
//自己生产的公私钥对
String publicKeyStr = Base64.toBase64String(pubKey.getEncoded());
String privateKeyStr = Base64.toBase64String(priKey.getEncoded());
System.out.println("public key :"+publicKeyStr);
System.out.println("private key :"+privateKeyStr);
// 加密后的密文
String mi = RsaUtils.RSAEncode(ming, RsaUtils.loadPublicKey(publicKeyStr));
logger.info("密文:"+mi);
// 解密后的明文
//String mi = "Johjwa/2jAe/k3pkB9Ax9WE0RMjq4s73csdBg==这是一段加密的密文数据,用来测试解密的";
ming = RsaUtils.RSADecode(mi, RsaUtils.loadPrivateKey(privateKeyStr));
logger.info("明文:"+ming);
} catch (Exception e) {
logger.error(e.getMessage());
}
}
有需要完整代码的请到下载页面进行获取《
》,不喜勿喷。每天努力一点,每天都在进步。