Java Cryptography: A Comprehensive Guide
Introduction to Java Cryptography
Cryptography is essential for securing data and communications in Java applications. This guide covers encryption, hashing, digital signatures, and other cryptographic operations using Java's security APIs.
Symmetric Encryption
AES Implementation
public class AESEncryption {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
public static byte[] encrypt(byte[] data, SecretKey key, byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(data);
}
public static byte[] decrypt(byte[] encryptedData, SecretKey key, byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(encryptedData);
}
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
keyGen.init(256);
return keyGen.generateKey();
}
}
Asymmetric Encryption
RSA Implementation
public class RSAEncryption {
private static final String ALGORITHM = "RSA";
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(2048);
return keyGen.generateKeyPair();
}
public static byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
public static byte[] decrypt(byte[] encryptedData, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(encryptedData);
}
}
Hashing
SHA-256 Implementation
public class HashUtils {
private static final String ALGORITHM = "SHA-256";
public static byte[] hash(byte[] data) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance(ALGORITHM);
return digest.digest(data);
}
public static String hashToHex(byte[] data) throws NoSuchAlgorithmException {
byte[] hash = hash(data);
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
}
Digital Signatures
DSA Implementation
public class DigitalSignature {
private static final String ALGORITHM = "SHA256withDSA";
public static byte[] sign(byte[] data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance(ALGORITHM);
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public static boolean verify(byte[] data, byte[] signature, PublicKey publicKey) throws Exception {
Signature sig = Signature.getInstance(ALGORITHM);
sig.initVerify(publicKey);
sig.update(data);
return sig.verify(signature);
}
}
Key Storage
KeyStore Implementation
public class KeyStoreManager {
private static final String KEYSTORE_TYPE = "PKCS12";
private static final String KEYSTORE_PATH = "keystore.p12";
public static KeyStore createKeyStore(char[] password) throws Exception {
KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
keyStore.load(null, password);
return keyStore;
}
public static void storeKey(KeyStore keyStore, String alias, Key key, char[] password) throws Exception {
keyStore.setKeyEntry(alias, key, password, null);
try (FileOutputStream fos = new FileOutputStream(KEYSTORE_PATH)) {
keyStore.store(fos, password);
}
}
public static Key loadKey(KeyStore keyStore, String alias, char[] password) throws Exception {
return keyStore.getKey(alias, password);
}
}
Secure Random Numbers
Implementation
public class SecureRandomGenerator {
private static final SecureRandom secureRandom = new SecureRandom();
public static byte[] generateRandomBytes(int length) {
byte[] bytes = new byte[length];
secureRandom.nextBytes(bytes);
return bytes;
}
public static String generateRandomString(int length) {
byte[] bytes = generateRandomBytes(length);
return Base64.getEncoder().encodeToString(bytes);
}
}
SSL/TLS Communication
SSL Socket Implementation
public class SecureSocketServer {
private static final int PORT = 8443;
public static void startServer() throws Exception {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
SSLServerSocketFactory factory = sslContext.getServerSocketFactory();
SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(PORT);
while (true) {
SSLSocket socket = (SSLSocket) serverSocket.accept();
new Thread(() -> handleClient(socket)).start();
}
}
private static void handleClient(SSLSocket socket) {
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(
socket.getOutputStream(), true);
String message = reader.readLine();
writer.println("Server received: " + message);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Cryptography Best Practices
- Use strong algorithms and key sizes
- Implement proper key management
- Use secure random number generation
- Implement proper error handling
- Follow cryptographic standards
- Regular security audits
Common Cryptographic Vulnerabilities
- Weak key generation
- Insecure key storage
- Algorithm downgrade attacks
- Padding oracle attacks
- Timing attacks
- Man-in-the-middle attacks
Conclusion
Implementing proper cryptography is crucial for securing Java applications. Follow best practices, use appropriate cryptographic algorithms, and regularly update security measures to protect against evolving threats.