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.