简介
RSA算法属于非对称加密算法,非对称加密算法需要两个秘钥:公开密钥(publickey)和私有秘钥(privatekey).公开密钥和私有秘钥是一对,如果公开密钥对数据进行加密,只有用对应的私有秘钥才能解密;如果私有秘钥对数据进行加密那么只有用对应的公开密钥才能解密.因为加密解密使用的是两个不同的秘钥,所以这种算法叫做非对称加密算法.简单的说就是公钥加密私钥解密,私钥加密公钥解密
获取公私钥
通过KeyPairGenerator.getInstance("RSA");来获取RSA的公钥与私钥,1024长度的密钥最大解密密文大小为128,最大加密密文大小为127。2048长度的密钥最大解密密文大小为256,最大加密密文大小为255。本文使用2048长度的key,密文过大是会使用分段加解密。
开发中通常会使用公钥加密,使用私钥解密。所以通常会有2对公私钥来使前后端相互通信。
所以本文只说公钥加密,使用私钥解密方法
/** 生成密钥对,即公钥和私钥。key长度是512-2048,一般为1024 本文使用2048长度的key*/
public static KeyPair generateRSAKeyPair(int keyLength) throws NoSuchAlgorithmException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(keyLength);
return kpg.genKeyPair();
}
/** 获取公钥*/
public static byte[] getPublicKey(KeyPair keyPair) {
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
return rsaPublicKey.getEncoded();
}
/** 获取私钥*/
public static byte[] getPrivateKey(KeyPair keyPair) {
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
return rsaPrivateKey.getEncoded();
}
使用公钥加密
/**
* 使用公钥加密
* @param content 需要加密的密文(String类型)
* @param publicKeyString 公钥(String类型)
* @return base64数据
* @throws Exception
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public static String encryptByPublicKey(String content, String publicKeyString) throws Exception {
byte[] publicKey = Base64.getDecoder().decode(publicKeyString.getBytes());
// 得到公钥对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
// 加密数据
Cipher cp = Cipher.getInstance(TRANSFORMATION);
cp.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] byteArray = cp.doFinal(content.getBytes());
return byteArray != null?Base64.getEncoder().encodeToString(byteArray):null;
}
使用私钥解密
/**
* 使用私钥解密
* @param content content 需要加密的密文
* @param privateKeyString 私钥
* @return String数据所以需要fastjson转object
* @throws Exception
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public static String decryptByPrivateKey(String content, String privateKeyString) throws Exception {
byte[] privateKey = Base64.getDecoder().decode(privateKeyString.getBytes());
byte[] encrypt = Base64Utils.decodeToBytes(content);
// 得到私钥对象
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey keyPrivate = kf.generatePrivate(keySpec);
// 解密数据
Cipher cp = Cipher.getInstance(TRANSFORMATION);
cp.init(Cipher.DECRYPT_MODE, keyPrivate);
byte[] byteArray = cp.doFinal(encrypt);
return byteArray!=null?new String(byteArray):null;
}
使用公钥分段加密
1024长度的密钥最大解密密文大小为128,最大加密密文大小为127;2048长度的密钥最大解密密文大小为256,最大加密密文大小为255(本文使用2048长度的key)。
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 255;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 256;
/**
* 使用公钥分段加密
* @param content 需要加密的密文(String类型)
* @param publicKeyString 公钥(String类型)
* @return base64数据
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public static String encryptByPublicKeySection(String content , String publicKeyString) {
byte[] publicKey = Base64.getDecoder().decode(publicKeyString.getBytes());
// 加密
String str = "";
try {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory fac = KeyFactory.getInstance("RSA");
RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, rsaPubKey);
int inputLen = content.getBytes().length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
//MAX_ENCRYPT_BLOCK 117
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(content.getBytes(), offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(content.getBytes(), offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
str = Base64.getEncoder().encodeToString(encryptedData);
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
使用私钥分段解密
同上
**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 255;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 256;
/**
* 使用私钥分段解密
* @param data 已经加密的密文(通常为base64类型)
* @param privateKeyString 私钥(String类型)
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.O)
public static String decryptByPrivateKeySection(String data , String privateKeyString) {
byte[] privateKey = Base64.getDecoder().decode(privateKeyString.getBytes());
// 加密
String str = "";
try {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory fac = KeyFactory.getInstance("RSA");
RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64Utils.decodeToBytes(data);
int inputLen = dataBytes.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的内容
str = new String(decryptedData);
} catch (Exception e) {
e.printStackTrace();
}
return str;
}