基本概念
RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。
解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文。
生成私钥
# 生成rsa私钥,以X509编码,指定生成的密钥的位数: 2048
openssl genrsa -out rsa_private_key_2048.pem 2048
# 将上一步生成的rsa私钥转换成PKCS#8编码
openssl pkcs8 -topk8 -in rsa_private_key_2048.pem -out pkcs8_rsa_private_key_2048.pem -nocrypt
生成公钥
openssl rsa -in rsa_private_key_2048.pem -out rsa_public_key_2048.pem -pubout
依赖
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.5</version>
</dependency>
</dependencies>
工具类
/**
* <p>
* RSA加解密工具类
* <p>
* 密钥长度 2048 bits
* 密钥格式 PKCS#8
* 加密算法 RSA/ECB/PKCS1Padding
* 签名算法 SHA1withRSA
*
* @author 苦瓜不苦
* @date 2021/6/9 10:22
**/
public class RSAHelperUtil {
// 加密算法
private final static String ENCRYPT_ARITHMETIC = "RSA/ECB/PKCS1Padding";
// 签名算法
private final static String SIGN_ARITHMETIC = "SHA1withRSA";
// 2048 bits 的RSA 密钥对
private final static int KEY_BIT = 2048;
// 2048 bits 的RSA 密钥对
private final static int RESERVE_BYTES = 11;
// 实例化私钥
private static PrivateKey privateKey = null;
// 实例化公钥
private static PublicKey publicKey = null;
// 私钥
private final static String PRIVATE_KEY = "xxxxx";
// 公钥
private final static String PUBLIC_KEY = "xxxxx";
static {
try {
Account account = new Account();
privateKey = RSAHelperUtil.getPrivateKey(account.getPrivateKey());
publicKey = RSAHelperUtil.getPublicKey(account.getPublicKey());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 实例化公钥
*
* @param publicKey
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(String publicKey) throws Exception {
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] publicKeyByte = base64Decoder.decodeBuffer(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByte);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
}
/**
* 实例化私钥
*
* @param privateKey
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] privateKeyByte = base64Decoder.decodeBuffer(privateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}
/**
* 公钥分段加密
*
* @param text 明文字符串
* @return 加密密文
*/
public static String encrypt(String text) {
try {
// 2048 bits 的RSA 密钥对, 最大加密明文大小计算公式: 2048 (bits) / 8 - 11(byte) = 245 byte
int maxEncryptBlock = KEY_BIT / 8 - RESERVE_BYTES;
Cipher cipher = Cipher.getInstance(ENCRYPT_ARITHMETIC);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);
int textBytesLength = textBytes.length;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 分段加密
for (int offset = 0; offset < textBytesLength; offset += maxEncryptBlock) {
// 字节长度不能超过max_encrypt_block
int block = textBytesLength - offset;
if (block > maxEncryptBlock) {
block = maxEncryptBlock;
}
// 得到分段加密结果
byte[] encryptBlock = cipher.doFinal(textBytes, offset, block);
// 追加结果
outputStream.write(encryptBlock);
}
// 关闭流
outputStream.flush();
outputStream.close();
// 获取加密字节
byte[] encryptBytes = outputStream.toByteArray();
// Base64编码
byte[] encode = Base64.getEncoder().encode(encryptBytes);
return new String(encode, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 私钥分段解密
*
* @param text 加密字符串
* @return 加密明文
*/
public static String decrypt(String text) {
try {
// 2048 bits 的RSA 密钥对, 最大解密明文大小计算公式: 2048 (bits) / 8 = 256 byte
int maxDecryptBlock = KEY_BIT / 8;
Cipher cipher = Cipher.getInstance(ENCRYPT_ARITHMETIC);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] textBytes = Base64.getDecoder().decode(text.getBytes(StandardCharsets.UTF_8));
int textBytesLength = textBytes.length;
// 分段解密
for (int offset = 0; offset < textBytesLength; offset += maxDecryptBlock) {
// 字节长度不能超过max_decrypt_block
int block = Math.min(textBytesLength - offset, maxDecryptBlock);
// 得到分段加密结果
byte[] encryptBlock = cipher.doFinal(textBytes, offset, block);
// 追加结果
outputStream.write(encryptBlock);
}
// 关闭流
outputStream.flush();
outputStream.close();
// 获取数据
return outputStream.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 生成签名
*
* @param text 明文数据
* @return 签名的信息
*/
public static String generateSign(String text) {
try {
// 实例化
Signature signature = Signature.getInstance(SIGN_ARITHMETIC);
signature.initSign(privateKey);
signature.update(text.getBytes(StandardCharsets.UTF_8));
// 生成签名
byte[] sign = signature.sign();
// base64编码
return new String(Base64.getEncoder().encode(sign), StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 验证签名
*
* @param text 明文数据
* @param signText 签名的信息
* @return
*/
public static Boolean verifySign(String text, String signText) {
try {
Signature signature = Signature.getInstance(SIGN_ARITHMETIC);
signature.initVerify(publicKey);
signature.update(text.getBytes(StandardCharsets.UTF_8));
// base64解码
byte[] signByte = Base64.getDecoder().decode(signText.getBytes(StandardCharsets.UTF_8));
// 验证签名
return signature.verify(signByte);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}