import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.UUID;
/**
* RSA 工具
* RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。
* @author chunyang.leng
* @date 2021-12-06 3:04 下午
*/
public class RsaUtils {
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 加密算法
*/
private static final String ALGORITHM = "RSA";
public static void main(String[] args) throws Exception {
// 获取密码对
KeyPair keyPair = getKeyPair(1024);
// 获取公钥
PublicKey publicKey = keyPair.getPublic();
// 获取私钥
PrivateKey privateKey = keyPair.getPrivate();
for (int i = 0; i < 10000; i++) {
// 循环1w次,做编解码测试
String uuid = UUID.randomUUID().toString();
// 使用公钥加密
String encrypt1 = encrypt(uuid, publicKey);
String encrypt2 = encrypt(uuid, getPublicKeyBase64(publicKey));
// 使用私钥解密
String decrypt1 = decrypt(encrypt1, privateKey);
String decrypt2 = decrypt(encrypt2, getPrivateKeyBase64(privateKey));
// 输出加解密结果
System.out.println(decrypt1.equals(decrypt2) && uuid.equals(decrypt1));
}
}
/**
* 获取密钥对创建对象
* @param keySize 密钥长度,正整数,如果过大,加解密速度会很慢
* @return 密钥对
* @throws NoSuchAlgorithmException
*/
public static KeyPair getKeyPair(int keySize) throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
keyPairGen.initialize(keySize);
return keyPairGen.generateKeyPair();
}
/**
* 根据 publicKey 对象,获取可以传输的 base64 公钥
* @param publicKey rsa 公钥对象
* @return 可以传输的 base64 公钥
*/
public static String getPublicKeyBase64(PublicKey publicKey){
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
}
/**
* 根据 privateKey 对象,获取可以传输的 base64 私钥
* @param privateKey rsa 私钥对象
* @return 可以传输的 base64 私钥
*/
public static String getPrivateKeyBase64(PrivateKey privateKey){
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
}
/**
* 根据公钥字符串,创建 RSAPublicKey
* @param publicKey 公钥字符串
* @return RSAPublicKey
* @throws Exception
*/
public static PublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
byte[] keyBytes = Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
return keyFactory.generatePublic(spec);
}
/**
* 根据 私钥字符串 创建RSAPrivateKey
* @param privateKey 私钥字符串
* @return RSAPrivateKey 对象
* @throws Exception
*/
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
byte[] keyBytes = Base64.getDecoder().decode(privateKey);
// Only RSAPrivate(Crt)KeySpec and PKCS8EncodedKeySpec supported for RSA private keys
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
return keyFactory.generatePrivate(spec);
}
/**
* 使用公钥加密数据
* @param message 待加密的数据
* @param publicKeyBase64 rsa 公钥字符串
* @return 加密后的字符串
* @throws Exception
*/
public static String encrypt(String message,String publicKeyBase64) throws Exception {
if (message == null ){
return null;
}
PublicKey publicKeyObject = getPublicKey(publicKeyBase64);
return encrypt(message,publicKeyObject);
}
/**
* 使用公钥加密
* @param message 待加密待信息
* @param publicKey rsa 公钥对象
* @return 加密后待字符串
* @throws Exception
*/
public static String encrypt(String message,PublicKey publicKey) throws Exception {
if (message == null ){
return null;
}
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.PUBLIC_KEY, publicKey);
byte[] data = message.getBytes(StandardCharsets.UTF_8);
int inputLen = data.length;
try (ByteArrayOutputStream out = new ByteArrayOutputStream();){
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
return Base64.getEncoder().encodeToString(encryptedData);
}
}
/**
* 根据私钥,解密信息
* @param encodedMessage 待解密的信息
* @param privateKeyBase64 rsa 私钥字符串
* @return 解密后的信息
*/
public static String decrypt(String encodedMessage,String privateKeyBase64) throws Exception{
if (encodedMessage == null ){
return null;
}
PrivateKey privateKey = getPrivateKey(privateKeyBase64);
return decrypt(encodedMessage,privateKey);
}
/**
* 根据私钥,解密信息
* @param encodedMessage 待解密的信息
* @param privateKey rsa 私钥 对象
* @return 解密后的信息
*/
public static String decrypt(String encodedMessage,PrivateKey privateKey) throws Exception {
if (encodedMessage == null ){
return null;
}
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.PRIVATE_KEY, privateKey);
byte[] encryptedData = Base64.getDecoder().decode(encodedMessage);
int inputLen = encryptedData.length;
try (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(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
return new String(decryptedData, StandardCharsets.UTF_8);
}
}
}
JAVA使用RSA实现非对称加密
最新推荐文章于 2024-03-19 11:52:07 发布