Introduction
RSA (Rivest-Shamir-Adleman) is one of the first public-key cryptosystems widely used for secure data transmission. It involves generating a pair of keys: a public key for encryption and a private key for decryption. Java provides comprehensive support for RSA key generation through the Java Cryptography Architecture (JCA).
Basic RSA Key Pair Generation
Simple Key Pair Generation
import java.security.*;
import java.security.spec.*;
import java.util.Base64;
public class BasicRSAKeyGenerator {
private static final String ALGORITHM = "RSA";
private static final int KEY_SIZE = 2048; // Recommended minimum size
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
return keyPairGenerator.generateKeyPair();
}
public static void main(String[] args) {
try {
KeyPair keyPair = generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("=== RSA Key Pair Generated ===");
System.out.println("Algorithm: " + publicKey.getAlgorithm());
System.out.println("Format: " + publicKey.getFormat());
// Display key information
System.out.println("\nPublic Key:");
System.out.println("Length: " + publicKey.getEncoded().length + " bytes");
System.out.println("Base64: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
System.out.println("\nPrivate Key:");
System.out.println("Length: " + privateKey.getEncoded().length + " bytes");
System.out.println("Base64: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
} catch (NoSuchAlgorithmException e) {
System.err.println("RSA algorithm not available: " + e.getMessage());
}
}
}
Advanced RSA Key Generation with Custom Parameters
Configurable Key Generator
import java.security.*;
import java.security.spec.*;
import java.util.*;
public class AdvancedRSAKeyGenerator {
private final int keySize;
private final SecureRandom secureRandom;
public AdvancedRSAKeyGenerator(int keySize) {
this.keySize = keySize;
this.secureRandom = new SecureRandom();
}
public AdvancedRSAKeyGenerator(int keySize, byte[] seed) {
this.keySize = keySize;
this.secureRandom = new SecureRandom(seed);
}
public KeyPair generateKeyPair() throws NoSuchAlgorithmException {
return generateKeyPair(keySize, secureRandom);
}
public KeyPair generateKeyPair(int keySize, SecureRandom random)
throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize, random);
return keyPairGenerator.generateKeyPair();
}
// Generate key pair with specific RSA parameter specifications
public KeyPair generateKeyPairWithSpec(BigInteger publicExponent)
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(
keySize,
publicExponent
);
keyPairGenerator.initialize(spec, secureRandom);
return keyPairGenerator.generateKeyPair();
}
// Generate key pair using KeyPairGeneratorSpec (for Android compatibility)
public KeyPair generateKeyPairWithGeneratorSpec(String alias)
throws Exception {
// Note: This approach is more common in Android development
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
end.add(Calendar.YEAR, 1); // Valid for 1 year
// This is a simplified version - actual implementation may vary
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize);
return keyPairGenerator.generateKeyPair();
}
// Test different key sizes
public static void testKeySizes() {
int[] keySizes = {1024, 2048, 3072, 4096};
for (int size : keySizes) {
try {
long startTime = System.currentTimeMillis();
AdvancedRSAKeyGenerator generator = new AdvancedRSAKeyGenerator(size);
KeyPair keyPair = generator.generateKeyPair();
long endTime = System.currentTimeMillis();
System.out.printf("Key size: %d bits | Generation time: %d ms%n",
size, (endTime - startTime));
} catch (Exception e) {
System.err.println("Failed to generate " + size + "-bit key: " + e.getMessage());
}
}
}
}
Key Storage and Management
Key Serialization and Deserialization
import java.security.*;
import java.security.spec.*;
import java.util.Base64;
public class RSAKeySerializer {
// Convert PublicKey to Base64 string
public static String publicKeyToString(PublicKey publicKey) {
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
}
// Convert PrivateKey to Base64 string
public static String privateKeyToString(PrivateKey privateKey) {
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
}
// Convert Base64 string back to PublicKey
public static PublicKey publicKeyFromString(String keyString)
throws GeneralSecurityException {
byte[] keyBytes = Base64.getDecoder().decode(keyString);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
return keyFactory.generatePublic(keySpec);
}
// Convert Base64 string back to PrivateKey
public static PrivateKey privateKeyFromString(String keyString)
throws GeneralSecurityException {
byte[] keyBytes = Base64.getDecoder().decode(keyString);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
return keyFactory.generatePrivate(keySpec);
}
// Save key pair to files
public static void saveKeyPair(KeyPair keyPair, String baseFileName)
throws Exception {
// Save public key
try (var out = new java.io.FileWriter(baseFileName + ".pub")) {
out.write(publicKeyToString(keyPair.getPublic()));
}
// Save private key
try (var out = new java.io.FileWriter(baseFileName + ".key")) {
out.write(privateKeyToString(keyPair.getPrivate()));
}
}
// Load key pair from files
public static KeyPair loadKeyPair(String baseFileName)
throws Exception {
// Load public key
String publicKeyStr;
try (var in = new java.io.FileReader(baseFileName + ".pub")) {
publicKeyStr = new java.util.Scanner(in).useDelimiter("\\A").next();
}
// Load private key
String privateKeyStr;
try (var in = new java.io.FileReader(baseFileName + ".key")) {
privateKeyStr = new java.util.Scanner(in).useDelimiter("\\A").next();
}
PublicKey publicKey = publicKeyFromString(publicKeyStr);
PrivateKey privateKey = privateKeyFromString(privateKeyStr);
return new KeyPair(publicKey, privateKey);
}
// Generate and display key information
public static void displayKeyInfo(KeyPair keyPair) {
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
if (publicKey instanceof RSAPublicKey) {
RSAPublicKey rsaPublic = (RSAPublicKey) publicKey;
System.out.println("Public Key Info:");
System.out.println(" Modulus: " + rsaPublic.getModulus());
System.out.println(" Public Exponent: " + rsaPublic.getPublicExponent());
}
if (privateKey instanceof RSAPrivateKey) {
RSAPrivateKey rsaPrivate = (RSAPrivateKey) privateKey;
System.out.println("Private Key Info:");
System.out.println(" Modulus: " + rsaPrivate.getModulus());
if (rsaPrivate instanceof RSAPrivateCrtKey) {
RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey) rsaPrivate;
System.out.println(" Private Exponent: " + crtKey.getPrivateExponent());
System.out.println(" Prime P: " + crtKey.getPrimeP());
System.out.println(" Prime Q: " + crtKey.getPrimeQ());
}
}
}
}
RSA Encryption and Decryption
Crypto Utility Class
import javax.crypto.*;
import java.security.*;
import java.util.Base64;
public class RSACryptoUtils {
private static final String TRANSFORMATION = "RSA/ECB/PKCS1Padding";
// Alternative transformations:
// - "RSA/ECB/PKCS1Padding" (most common)
// - "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" (more secure)
// - "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"
public static String encrypt(String plainText, PublicKey publicKey)
throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
return Base64.getEncoder().encodeToString(encryptedBytes);
}
public static String decrypt(String encryptedText, PrivateKey privateKey)
throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes);
}
// For larger data, use hybrid encryption (RSA + AES)
public static HybridEncryptionResult hybridEncrypt(String largeData, PublicKey publicKey)
throws GeneralSecurityException {
// Generate random AES key
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey aesKey = keyGen.generateKey();
// Encrypt data with AES
Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding");
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encryptedData = aesCipher.doFinal(largeData.getBytes());
// Encrypt AES key with RSA
Cipher rsaCipher = Cipher.getInstance(TRANSFORMATION);
rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedAesKey = rsaCipher.doFinal(aesKey.getEncoded());
return new HybridEncryptionResult(
Base64.getEncoder().encodeToString(encryptedData),
Base64.getEncoder().encodeToString(encryptedAesKey),
Base64.getEncoder().encodeToString(aesCipher.getIV())
);
}
public static String hybridDecrypt(HybridEncryptionResult result, PrivateKey privateKey)
throws GeneralSecurityException {
// Decrypt AES key with RSA
Cipher rsaCipher = Cipher.getInstance(TRANSFORMATION);
rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] aesKeyBytes = rsaCipher.doFinal(
Base64.getDecoder().decode(result.getEncryptedAesKey()));
SecretKey aesKey = new javax.crypto.spec.SecretKeySpec(aesKeyBytes, "AES");
// Decrypt data with AES
Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128,
Base64.getDecoder().decode(result.getIv()));
aesCipher.init(Cipher.DECRYPT_MODE, aesKey, spec);
byte[] decryptedData = aesCipher.doFinal(
Base64.getDecoder().decode(result.getEncryptedData()));
return new String(decryptedData);
}
// Helper class for hybrid encryption results
public static class HybridEncryptionResult {
private final String encryptedData;
private final String encryptedAesKey;
private final String iv;
public HybridEncryptionResult(String encryptedData, String encryptedAesKey, String iv) {
this.encryptedData = encryptedData;
this.encryptedAesKey = encryptedAesKey;
this.iv = iv;
}
// Getters
public String getEncryptedData() { return encryptedData; }
public String getEncryptedAesKey() { return encryptedAesKey; }
public String getIv() { return iv; }
}
}
Digital Signatures with RSA
Signature Generation and Verification
import java.security.*;
import java.util.Base64;
public class RSASignatureUtils {
private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
// Alternative algorithms:
// - "SHA1withRSA"
// - "SHA256withRSA" (recommended)
// - "SHA512withRSA"
// - "RSASSA-PSS"
public static String sign(String data, PrivateKey privateKey)
throws GeneralSecurityException {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey);
signature.update(data.getBytes());
byte[] digitalSignature = signature.sign();
return Base64.getEncoder().encodeToString(digitalSignature);
}
public static boolean verify(String data, String digitalSignature, PublicKey publicKey)
throws GeneralSecurityException {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicKey);
signature.update(data.getBytes());
byte[] signatureBytes = Base64.getDecoder().decode(digitalSignature);
return signature.verify(signatureBytes);
}
// Sign with PSS padding (more secure)
public static String signWithPSS(String data, PrivateKey privateKey)
throws GeneralSecurityException {
Signature signature = Signature.getInstance("RSASSA-PSS");
// Configure PSS parameters
PSSParameterSpec pssSpec = new PSSParameterSpec(
"SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
signature.setParameter(pssSpec);
signature.initSign(privateKey);
signature.update(data.getBytes());
byte[] digitalSignature = signature.sign();
return Base64.getEncoder().encodeToString(digitalSignature);
}
public static boolean verifyWithPSS(String data, String digitalSignature, PublicKey publicKey)
throws GeneralSecurityException {
Signature signature = Signature.getInstance("RSASSA-PSS");
// Configure PSS parameters
PSSParameterSpec pssSpec = new PSSParameterSpec(
"SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
signature.setParameter(pssSpec);
signature.initVerify(publicKey);
signature.update(data.getBytes());
byte[] signatureBytes = Base64.getDecoder().decode(digitalSignature);
return signature.verify(signatureBytes);
}
}
Complete RSA Key Management System
Comprehensive Key Manager
import java.security.*;
import java.security.spec.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class RSAKeyManager {
private final Map<String, KeyPair> keyStore;
private final int defaultKeySize;
private final SecureRandom secureRandom;
public RSAKeyManager(int defaultKeySize) {
this.keyStore = new ConcurrentHashMap<>();
this.defaultKeySize = defaultKeySize;
this.secureRandom = new SecureRandom();
}
public String generateKeyPair(String keyId) throws GeneralSecurityException {
return generateKeyPair(keyId, defaultKeySize);
}
public String generateKeyPair(String keyId, int keySize) throws GeneralSecurityException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize, secureRandom);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
keyStore.put(keyId, keyPair);
return keyId;
}
public KeyPair getKeyPair(String keyId) {
return keyStore.get(keyId);
}
public PublicKey getPublicKey(String keyId) {
KeyPair keyPair = keyStore.get(keyId);
return (keyPair != null) ? keyPair.getPublic() : null;
}
public PrivateKey getPrivateKey(String keyId) {
KeyPair keyPair = keyStore.get(keyId);
return (keyPair != null) ? keyPair.getPrivate() : null;
}
public boolean removeKeyPair(String keyId) {
return keyStore.remove(keyId) != null;
}
public Set<String> getAllKeyIds() {
return keyStore.keySet();
}
public void clearAllKeys() {
keyStore.clear();
}
// Key rotation - generate new key and return old public key
public PublicKey rotateKey(String keyId) throws GeneralSecurityException {
KeyPair oldKeyPair = keyStore.get(keyId);
generateKeyPair(keyId);
return (oldKeyPair != null) ? oldKeyPair.getPublic() : null;
}
// Export public key as string
public String exportPublicKey(String keyId) {
PublicKey publicKey = getPublicKey(keyId);
return (publicKey != null) ?
Base64.getEncoder().encodeToString(publicKey.getEncoded()) : null;
}
// Import public key
public void importPublicKey(String keyId, String publicKeyStr)
throws GeneralSecurityException {
byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
// Store with null private key (public key only)
keyStore.put(keyId, new KeyPair(publicKey, null));
}
// Key information and statistics
public Map<String, Object> getKeyInfo(String keyId) {
KeyPair keyPair = keyStore.get(keyId);
if (keyPair == null) return null;
Map<String, Object> info = new HashMap<>();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
if (publicKey instanceof RSAPublicKey) {
RSAPublicKey rsaPublic = (RSAPublicKey) publicKey;
info.put("keySize", rsaPublic.getModulus().bitLength());
info.put("publicExponent", rsaPublic.getPublicExponent());
}
info.put("hasPrivateKey", privateKey != null);
info.put("algorithm", publicKey.getAlgorithm());
info.put("format", publicKey.getFormat());
return info;
}
// Bulk operations
public Map<String, String> exportAllPublicKeys() {
Map<String, String> exportedKeys = new HashMap<>();
for (String keyId : keyStore.keySet()) {
exportedKeys.put(keyId, exportPublicKey(keyId));
}
return exportedKeys;
}
}
Testing and Validation
Comprehensive Test Suite
import java.security.*;
import java.util.Base64;
public class RSAKeyGeneratorTest {
public static void main(String[] args) {
try {
testBasicKeyGeneration();
testEncryptionDecryption();
testDigitalSignatures();
testKeyManager();
testPerformance();
} catch (Exception e) {
System.err.println("Test failed: " + e.getMessage());
e.printStackTrace();
}
}
public static void testBasicKeyGeneration() throws Exception {
System.out.println("=== Testing Basic Key Generation ===");
KeyPair keyPair = BasicRSAKeyGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("✓ Key pair generated successfully");
System.out.println(" Public Key Algorithm: " + publicKey.getAlgorithm());
System.out.println(" Private Key Format: " + privateKey.getFormat());
// Test key serialization
String pubKeyStr = RSAKeySerializer.publicKeyToString(publicKey);
String privKeyStr = RSAKeySerializer.privateKeyToString(privateKey);
PublicKey restoredPubKey = RSAKeySerializer.publicKeyFromString(pubKeyStr);
PrivateKey restoredPrivKey = RSAKeySerializer.privateKeyFromString(privKeyStr);
System.out.println("✓ Key serialization/deserialization successful");
System.out.println(" Original and restored public keys match: " +
publicKey.equals(restoredPubKey));
System.out.println(" Original and restored private keys match: " +
privateKey.equals(restoredPrivKey));
}
public static void testEncryptionDecryption() throws Exception {
System.out.println("\n=== Testing Encryption/Decryption ===");
KeyPair keyPair = BasicRSAKeyGenerator.generateKeyPair();
String originalText = "This is a secret message that needs to be encrypted!";
// Test basic encryption
String encrypted = RSACryptoUtils.encrypt(originalText, keyPair.getPublic());
String decrypted = RSACryptoUtils.decrypt(encrypted, keyPair.getPrivate());
System.out.println("✓ Basic encryption/decryption successful");
System.out.println(" Original: " + originalText);
System.out.println(" Decrypted: " + decrypted);
System.out.println(" Match: " + originalText.equals(decrypted));
// Test hybrid encryption for larger data
String largeData = "A".repeat(1000); // 1000 characters
RSACryptoUtils.HybridEncryptionResult hybridResult =
RSACryptoUtils.hybridEncrypt(largeData, keyPair.getPublic());
String hybridDecrypted =
RSACryptoUtils.hybridDecrypt(hybridResult, keyPair.getPrivate());
System.out.println("✓ Hybrid encryption/decryption successful");
System.out.println(" Large data match: " + largeData.equals(hybridDecrypted));
}
public static void testDigitalSignatures() throws Exception {
System.out.println("\n=== Testing Digital Signatures ===");
KeyPair keyPair = BasicRSAKeyGenerator.generateKeyPair();
String message = "This message needs to be signed";
// Create signature
String signature = RSASignatureUtils.sign(message, keyPair.getPrivate());
// Verify signature
boolean isValid = RSASignatureUtils.verify(message, signature, keyPair.getPublic());
System.out.println("✓ Digital signature creation successful");
System.out.println(" Signature verification: " + isValid);
// Test tampering detection
String tamperedMessage = "This message has been tampered with";
boolean isTamperedValid = RSASignatureUtils.verify(tamperedMessage, signature, keyPair.getPublic());
System.out.println(" Tampering detection: " + !isTamperedValid);
}
public static void testKeyManager() throws Exception {
System.out.println("\n=== Testing Key Manager ===");
RSAKeyManager keyManager = new RSAKeyManager(2048);
// Generate multiple key pairs
keyManager.generateKeyPair("user1");
keyManager.generateKeyPair("user2", 3072);
keyManager.generateKeyPair("service", 4096);
System.out.println("✓ Multiple key pairs generated");
System.out.println(" Key IDs: " + keyManager.getAllKeyIds());
// Test key operations
String message = "Test message";
String encrypted = RSACryptoUtils.encrypt(message, keyManager.getPublicKey("user1"));
String decrypted = RSACryptoUtils.decrypt(encrypted, keyManager.getPrivateKey("user1"));
System.out.println("✓ Key manager encryption/decryption successful");
System.out.println(" Message match: " + message.equals(decrypted));
// Test key export/import
String exportedKey = keyManager.exportPublicKey("user2");
keyManager.importPublicKey("user2-imported", exportedKey);
System.out.println("✓ Key export/import successful");
System.out.println(" Imported key ID: user2-imported");
}
public static void testPerformance() throws Exception {
System.out.println("\n=== Testing Performance ===");
int[] keySizes = {1024, 2048, 3072, 4096};
int iterations = 10;
for (int keySize : keySizes) {
long keyGenTime = 0;
long encryptionTime = 0;
long decryptionTime = 0;
for (int i = 0; i < iterations; i++) {
// Key generation time
long start = System.nanoTime();
KeyPair keyPair = new AdvancedRSAKeyGenerator(keySize).generateKeyPair();
keyGenTime += System.nanoTime() - start;
// Encryption time
String testData = "Test data for encryption";
start = System.nanoTime();
String encrypted = RSACryptoUtils.encrypt(testData, keyPair.getPublic());
encryptionTime += System.nanoTime() - start;
// Decryption time
start = System.nanoTime();
RSACryptoUtils.decrypt(encrypted, keyPair.getPrivate());
decryptionTime += System.nanoTime() - start;
}
System.out.printf("Key Size: %d bits%n", keySize);
System.out.printf(" Average Key Generation: %.2f ms%n",
(keyGenTime / (iterations * 1_000_000.0)));
System.out.printf(" Average Encryption: %.2f ms%n",
(encryptionTime / (iterations * 1_000_000.0)));
System.out.printf(" Average Decryption: %.2f ms%n",
(decryptionTime / (iterations * 1_000_000.0)));
}
}
}
Security Best Practices
Security Configuration
import java.security.*;
public class RSASecurityConfig {
// Recommended security practices
public static class SecurityBestPractices {
// Minimum recommended key size
public static final int MIN_KEY_SIZE = 2048;
// Recommended key size for new systems
public static final int RECOMMENDED_KEY_SIZE = 3072;
// For long-term security
public static final int LONG_TERM_KEY_SIZE = 4096;
// Recommended signature algorithms
public static final String RECOMMENDED_SIGNATURE_ALGORITHM = "SHA256withRSA";
public static final String SECURE_SIGNATURE_ALGORITHM = "RSASSA-PSS";
// Recommended encryption padding
public static final String RECOMMENDED_ENCRYPTION_PADDING = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
public static void validateKeySize(int keySize) {
if (keySize < MIN_KEY_SIZE) {
throw new SecurityException(
"Key size " + keySize + " is below minimum recommended size of " + MIN_KEY_SIZE);
}
}
public static void validateAlgorithm(String algorithm) {
if (!algorithm.equals("RSA")) {
throw new SecurityException("Unsupported algorithm: " + algorithm);
}
}
// Check if strong cryptographic providers are available
public static void checkCryptographicStrength() {
try {
if (Cipher.getMaxAllowedKeyLength("AES") < 256) {
System.err.println("Warning: Unlimited strength cryptography may not be available");
}
} catch (Exception e) {
System.err.println("Warning: Cannot determine cryptographic strength: " + e.getMessage());
}
}
}
// Secure random number generator configuration
public static class SecureRandomConfig {
public static SecureRandom createSecureRandom() {
try {
// Prefer NativePRNGNonBlocking for better performance
return SecureRandom.getInstance("NativePRNGNonBlocking");
} catch (NoSuchAlgorithmException e) {
// Fallback to default SecureRandom
return new SecureRandom();
}
}
public static SecureRandom createSeededSecureRandom(byte[] seed) {
SecureRandom random = createSecureRandom();
random.setSeed(seed);
return random;
}
}
// Key storage security recommendations
public static class KeyStorageSecurity {
// In production, consider using:
// - Hardware Security Modules (HSM)
// - Key Management Systems (KMS)
// - Java KeyStore with strong passwords
// - Secure environment variables
public static void validateKeyStorage(Key key) {
// Basic validation - in real scenarios, check if key is stored securely
if (key == null) {
throw new SecurityException("Key cannot be null");
}
// Additional security checks would go here
// - Check if key is stored in secure storage
// - Validate key access controls
// - Audit key usage
}
}
}
Conclusion
RSA key pair generation in Java provides a robust foundation for secure applications:
Key Features:
- Strong cryptographic key generation
- Multiple key size options (2048-bit minimum recommended)
- Support for encryption, decryption, and digital signatures
- Comprehensive key management capabilities
Security Best Practices:
- Use at least 2048-bit keys for new systems
- Prefer RSA-PSS for signatures and OAEP for encryption
- Implement proper key storage and rotation policies
- Use secure random number generators
- Regularly update cryptographic libraries
Performance Considerations:
- RSA is slower than symmetric cryptography
- Use hybrid encryption for large data
- Consider key size vs performance trade-offs
- Cache frequently used keys when appropriate
This implementation provides a complete RSA key management solution suitable for enterprise applications, with proper security considerations and performance optimizations.