package com.example.crypto.algorithms; // import org.bouncycastle.jce.provider.BouncyCastleProvider; // import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider; // import org.bouncycastle.pqc.jcajce.spec.KyberParameterSpec; // import org.bouncycastle.util.Strings; import java.security.*; import java.security.spec.ECGenParameterSpec; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * Demonstrates various Key Encapsulation Mechanisms (KEMs), including: * * 1) RSA-KEM (emulated using RSA-OAEP for ephemeral key wrapping) - CBOM/SAST: * Classified as a Hybrid Cryptosystem (public-key based key encapsulation). * While RSA-OAEP is secure, using it to emulate KEM (without a standard scheme) * may be flagged. * * 2) ECIES (Elliptic Curve Integrated Encryption Scheme) - CBOM/SAST: * Classified as a Hybrid Cryptosystem (KEM+DEM) based on ECDH and AES. Note: * Directly using the raw ECDH shared secret as key material is insecure in * production. * * 3) Kyber (Post-Quantum KEM using BouncyCastle PQC) - CBOM/SAST: Classified as * a Post-Quantum Key Encapsulation mechanism. This is modern and secure when * using standardized parameters. * * 4) Basic ephemeral flows that mimic KEM logic using ephemeral ECDH. - * CBOM/SAST: Classified as a simple KEM mimic based on ephemeral ECDH. */ public class KeyEncapsulation { // static { // // Adding both classical and PQC providers. // Security.addProvider(new BouncyCastleProvider()); // Security.addProvider(new BouncyCastlePQCProvider()); // } ////////////////////////////////////// // 1. RSA-KEM-Like Flow ////////////////////////////////////// /** * Emulates RSA-KEM by using RSA-OAEP to wrap a random AES key. * * SAST/CBOM Classification: * - Parent: Hybrid Cryptosystem (RSA-OAEP based key encapsulation). * - Note: Although RSA-OAEP is secure, using it to "wrap" an ephemeral key is a * non-standard KEM pattern. * * @param rsaPub The RSA public key of the recipient. */ public void rsaKEMEncapsulation(PublicKey rsaPub) throws Exception { // 1) Generate an ephemeral AES key (symmetric key for data encryption) KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(256); // 256-bit AES key. SecretKey aesKey = keyGen.generateKey(); System.out.println("Ephemeral AES Key: " + Base64.getEncoder().encodeToString(aesKey.getEncoded())); // 2) Encrypt (wrap) the ephemeral AES key with RSA-OAEP. // SAST Note: This RSA-OAEP wrapping is used to encapsulate the AES key. Cipher rsaCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); rsaCipher.init(Cipher.ENCRYPT_MODE, rsaPub); byte[] wrappedKey = rsaCipher.doFinal(aesKey.getEncoded()); System.out.println("RSA-KEM Encapsulated AES Key: " + Base64.getEncoder().encodeToString(wrappedKey)); // 3) Example usage: Encrypt data with the ephemeral AES key using AES-GCM. Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding"); byte[] iv = new byte[12]; // Standard IV length for GCM. new SecureRandom().nextBytes(iv); GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv); aesCipher.init(Cipher.ENCRYPT_MODE, aesKey, gcmSpec); byte[] ciphertext = aesCipher.doFinal("KEM-based encryption".getBytes()); System.out.println("AES-GCM ciphertext: " + Base64.getEncoder().encodeToString(ciphertext)); } /** * Performs RSA decapsulation by decrypting the wrapped AES key. * * SAST/CBOM Classification: - Parent: Hybrid Cryptosystem (RSA-OAEP based * key decapsulation). - Note: Secure when used with matching RSA key pairs. * * @param rsaPriv The RSA private key corresponding to the public key used. * @param wrappedKey The RSA-wrapped ephemeral AES key. */ public void rsaKEMDecapsulation(PrivateKey rsaPriv, byte[] wrappedKey) throws Exception { Cipher rsaCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); rsaCipher.init(Cipher.DECRYPT_MODE, rsaPriv); byte[] aesKeyBytes = rsaCipher.doFinal(wrappedKey); SecretKey aesKey = new SecretKeySpec(aesKeyBytes, "AES"); System.out.println("RSA-KEM Decapsulated AES Key: " + Base64.getEncoder().encodeToString(aesKey.getEncoded())); } ////////////////////////////////////// // 2. ECIES Example ////////////////////////////////////// /** * Implements a simplified ECIES flow using ephemeral ECDH and AES-GCM. * * SAST/CBOM Classification: * - Parent: Hybrid Cryptosystem (ECIES: ECDH-based key encapsulation + DEM). * - Note: Directly using the raw ECDH shared secret as key material is * insecure. * In practice, a proper KDF must be applied. * * @param ecPub The recipient's EC public key. */ public void eciesEncapsulation(PublicKey ecPub) throws Exception { // Generate an ephemeral EC key pair. KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); kpg.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom()); KeyPair ephemeralEC = kpg.generateKeyPair(); // Perform ECDH key agreement to derive the shared secret. KeyAgreement ka = KeyAgreement.getInstance("ECDH"); ka.init(ephemeralEC.getPrivate()); ka.doPhase(ecPub, true); byte[] sharedSecret = ka.generateSecret(); System.out.println("ECIES ephemeral ECDH Secret: " + Base64.getEncoder().encodeToString(sharedSecret)); // For demonstration only: directly use part of the shared secret as an AES key. // SAST Note: This is insecure; a proper key derivation function (KDF) must be // used. SecretKey aesKey = new SecretKeySpec(sharedSecret, 0, 16, "AES"); // Encrypt the message using AES-GCM. Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding"); byte[] iv = new byte[12]; new SecureRandom().nextBytes(iv); aesCipher.init(Cipher.ENCRYPT_MODE, aesKey, new GCMParameterSpec(128, iv)); byte[] ciphertext = aesCipher.doFinal("ECIES message".getBytes()); // The ephemeral public key (ephemeralEC.getPublic()) is transmitted as part of // the output. System.out.println( "ECIES ephemeral public: " + Base64.getEncoder().encodeToString(ephemeralEC.getPublic().getEncoded())); System.out.println("ECIES ciphertext: " + Base64.getEncoder().encodeToString(ciphertext)); } ////////////////////////////////////// // 3. Kyber Example (Post-Quantum KEM) ////////////////////////////////////// // /** // * Demonstrates a Kyber-based encapsulation using BouncyCastle's PQC provider. // * // * SAST/CBOM Classification: // * - Parent: Post-Quantum KEM. // * - Note: Kyber is a modern, post-quantum secure KEM. This example uses // * Kyber-512. // * // * @param kyberRecipientKP The recipient's Kyber key pair. // */ // public void kyberEncapsulate(KeyPair kyberRecipientKP) throws Exception { // // Use an ephemeral label for demonstration. // byte[] ephemeralLabel = Strings.toByteArray("Kyber-KEM-Label"); // Cipher kemCipher = Cipher.getInstance("Kyber", "BCPQC"); // kemCipher.init(Cipher.ENCRYPT_MODE, kyberRecipientKP.getPublic(), new SecureRandom()); // byte[] ciphertext = kemCipher.doFinal(ephemeralLabel); // System.out.println("Kyber ciphertext: " + Base64.getEncoder().encodeToString(ciphertext)); // } ////////////////////////////////////// // 4. Basic Ephemeral Flows That Mimic KEM ////////////////////////////////////// /** * Uses ephemeral ECDH to derive a shared secret that mimics a KEM. * * SAST/CBOM Classification: * - Parent: Ephemeral Key Agreement (mimicking KEM). * - Note: This simple approach demonstrates the concept of using ephemeral keys * to derive a secret. * In a full scheme, the ephemeral public key would also be transmitted. * * @param recipientPubKey The recipient's public key. */ public void ephemeralECDHMimicKEM(PublicKey recipientPubKey) throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); kpg.initialize(new ECGenParameterSpec("secp256r1")); KeyPair ephemeralKP = kpg.generateKeyPair(); KeyAgreement ka = KeyAgreement.getInstance("ECDH"); ka.init(ephemeralKP.getPrivate()); ka.doPhase(recipientPubKey, true); byte[] sharedSecret = ka.generateSecret(); System.out.println( "Ephemeral ECDH shared secret (mimics KEM): " + Base64.getEncoder().encodeToString(sharedSecret)); // In a full implementation, the ephemeral public key and the shared secret are // used together. } ////////////////////////////////////// // Test / Demo Method ////////////////////////////////////// /** * Demonstrates each of the key encapsulation flows. */ public void runKeyEncapsulationDemos() throws Exception { // 1) RSA-KEM-like Flow: KeyPairGenerator rsaKpg = KeyPairGenerator.getInstance("RSA"); rsaKpg.initialize(2048); KeyPair rsaKP = rsaKpg.generateKeyPair(); rsaKEMEncapsulation(rsaKP.getPublic()); // 2) ECIES Example: KeyPairGenerator ecKpg = KeyPairGenerator.getInstance("EC"); ecKpg.initialize(new ECGenParameterSpec("secp256r1")); KeyPair ecKP = ecKpg.generateKeyPair(); eciesEncapsulation(ecKP.getPublic()); // // 3) Kyber Example (Post-Quantum KEM): // KeyPairGenerator kyberKpg = KeyPairGenerator.getInstance("Kyber", "BCPQC"); // kyberKpg.initialize(KyberParameterSpec.kyber512); // KeyPair kyberKP = kyberKpg.generateKeyPair(); // kyberEncapsulate(kyberKP); // 4) Ephemeral ECDH Mimic KEM: // For demonstration, we use an EC key pair and mimic KEM by deriving a shared // secret. KeyPair ephemeralEC = ecKpg.generateKeyPair(); ephemeralECDHMimicKEM(ephemeralEC.getPublic()); } }