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;
public class RsaUtils {
private static final int MAX_ENCRYPT_BLOCK = 117;
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++) {
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));
}
}
public static KeyPair getKeyPair(int keySize) throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
keyPairGen.initialize(keySize);
return keyPairGen.generateKeyPair();
}
public static String getPublicKeyBase64(PublicKey publicKey){
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
}
public static String getPrivateKeyBase64(PrivateKey privateKey){
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
}
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);
}
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
byte[] keyBytes = Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
return keyFactory.generatePrivate(spec);
}
public static String encrypt(String message,String publicKeyBase64) throws Exception {
if (message == null ){
return null;
}
PublicKey publicKeyObject = getPublicKey(publicKeyBase64);
return encrypt(message,publicKeyObject);
}
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);
}
}
public static String decrypt(String encodedMessage,String privateKeyBase64) throws Exception{
if (encodedMessage == null ){
return null;
}
PrivateKey privateKey = getPrivateKey(privateKeyBase64);
return decrypt(encodedMessage,privateKey);
}
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);
}
}
}