import java.io.ByteArrayOutputStream;
import java.util.Base64;
import javax.crypto.Cipher;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.X509EncodedKeySpec;
/**
* RSA public key encryption/decryption utility class
* <p>
* Provides asymmetric encryption and decryption based on public key,
* suitable for encrypted data transmission in API communication.
*/
public class RSAUtils {
// RSA encryption maximum block size (unit: bytes)
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* Encrypt data using public key
*
* @param data Original binary data
* @param publicKey Base64 encoded public key string
* @return Encrypted binary data
*
* Usage scenario: Encrypt business data before sending API requests.
* Automatically handles chunked encryption of large data (117 bytes/chunk).
*
* Example:
* byte[] encrypted = RSAUtils.encryptByPublicKey(
* jsonData.getBytes(),
* "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ..."
* );
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
// 1. Base64 decode public key
byte[] keyBytes = Base64Util.decodeString(publicKey);
// 2. Generate public key object
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(
new X509EncodedKeySpec(keyBytes)
);
// 3. Create and initialize cipher
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
// 4. Chunked encryption for large data
int inputLen = data.length;
int offset = 0;
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
while (inputLen - offset > 0) {
int blockSize = Math.min(inputLen - offset, MAX_ENCRYPT_BLOCK);
byte[] encryptedBlock = cipher.doFinal(data, offset, blockSize);
out.write(encryptedBlock, 0, encryptedBlock.length);
offset += blockSize;
}
return out.toByteArray();
}
/**
* Decrypt data using public key
*
* @param encryptedData Encrypted binary data
* @param publicKey Base64 encoded public key string
* @return Decrypted original binary data
*
* Usage scenario: Decrypt encrypted data returned from APIs.
* Suitable for one-time decryption of small data chunks.
*
* Example:
* byte[] decrypted = RSAUtils.decryptByPublicKey(
* encryptedBytes,
* "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ..."
* );
*/
public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {
final int MAX_DECRYPT_BLOCK = 128;
// 1. Base64 decode public key
byte[] keyBytes = Base64Util.decodeString(publicKey);
// 2. Generate public key object
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(
new X509EncodedKeySpec(keyBytes)
);
// 3. Create and initialize decrypter
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
// 4. One-time decryption (suitable for small data)
// return cipher.doFinal(encryptedData);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// Decrypt data in segments
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();
out.close();
return decryptedData;
}
}