Files
codeql/java/ql/test/experimental/library-tests/quantum/jca/Encryption2.java
2025-10-03 13:32:02 -04:00

199 lines
8.5 KiB
Java

package com.example.crypto.algorithms;
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;
import java.util.Arrays;
import javax.crypto.Mac;
/**
* This class demonstrates encryption schemes using elliptic-curve
* Diffie-Hellman (ECDH)
* and hybrid encryption methods, including a post-quantum hybrid scheme.
*
* SAST/CBOM Classification:
*
* 1. EC Key Generation & ECDH Key Agreement:
* - Parent Classification: Asymmetric Key Generation / Key Agreement.
* - SAST: Secure when using established curves (secp256r1) and reputable
* providers (BouncyCastle).
*
* 2. ECDH Hybrid Encryption:
* - Parent Classification: Hybrid Cryptosystem (ECDH + AEAD).
* - SAST: Uses ECDH for key agreement and AES/GCM for encryption. However, the
* derivation of an AES key
* by applying a single SHA-256 hash to the shared secret may be flagged as a
* weak key derivation method.
* A dedicated KDF (e.g., HKDF) is recommended.
*
* 3. Post-Quantum Hybrid Encryption:
* - Parent Classification: Hybrid Cryptosystem (Classical ECDH + Post-Quantum
* Secret + KDF + AEAD).
* - SAST: Combining classical and post-quantum components is advanced and
* secure if implemented properly.
* The custom HKDF expand function provided here is simplistic and may be
* flagged in a CBOM analysis;
* a standard HKDF library should be used in production.
*/
public class Encryption2 {
// static {
// Security.addProvider(new BouncyCastleProvider());
// }
/**
* Generates an Elliptic Curve (EC) key pair using the secp256r1 curve.
*
* SAST/CBOM Notes:
* - Algorithm: EC key pair generation.
* - Parent Classification: Asymmetric Key Generation.
* - SAST: Considered secure when using strong randomness and a reputable
* provider.
*
* @return an EC KeyPair.
*/
public KeyPair generateECKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
keyPairGenerator.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());
return keyPairGenerator.generateKeyPair();
}
/**
* Derives a shared secret using Elliptic Curve Diffie-Hellman (ECDH).
*
* SAST/CBOM Notes:
* - Algorithm: ECDH key agreement.
* - Parent Classification: Asymmetric Key Agreement.
* - SAST: Secure when both parties use strong EC keys and proper randomness.
*
* @param privateKey the private key of one party.
* @param publicKey the public key of the other party.
* @return the derived shared secret as a byte array.
*/
public byte[] deriveSharedSecret(PrivateKey privateKey, PublicKey publicKey) throws Exception {
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
return keyAgreement.generateSecret();
}
/**
* Performs hybrid encryption using ECDH to derive a shared secret, then derives
* an AES key
* by hashing the shared secret with SHA-256, and finally encrypts the data with
* AES-GCM.
*
* SAST/CBOM Notes:
* - Parent Classification: Hybrid Cryptosystem (ECDH + AES-GCM).
* - SAST: While ECDH and AES-GCM are secure, the key derivation method here (a
* single SHA-256 hash)
* is not as robust as using a dedicated KDF. This approach may be flagged and
* is recommended for
* improvement.
*
* @param recipientPublicKey the recipient's public EC key.
* @param data the plaintext data to encrypt.
*/
public void ecdhHybridEncryption(PublicKey recipientPublicKey, String data) throws Exception {
// Generate an ephemeral EC key pair for the sender.
KeyPair senderKeyPair = generateECKeyPair();
// Derive the shared secret using ECDH.
byte[] sharedSecret = deriveSharedSecret(senderKeyPair.getPrivate(), recipientPublicKey);
// Derive an AES key by hashing the shared secret with SHA-256.
// SAST Note: Using a direct hash for key derivation is simplistic and may be
// flagged.
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
byte[] aesKeyBytes = sha256.digest(sharedSecret);
// Use the first 16 bytes (128 bits) as the AES key.
SecretKey aesKey = new SecretKeySpec(aesKeyBytes, 0, 16, "AES");
// Encrypt the data using AES-GCM.
Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = new byte[12]; // 12-byte IV recommended for GCM.
new SecureRandom().nextBytes(iv);
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv); // 128-bit authentication tag.
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey, gcmSpec);
byte[] encryptedData = aesCipher.doFinal(data.getBytes());
System.out.println(
"ECDH Hybrid Encryption - Encrypted Data: " + Base64.getEncoder().encodeToString(encryptedData));
}
/**
* Performs post-quantum hybrid encryption by combining a classical ECDH-derived
* secret with a
* post-quantum shared secret. The two secrets are combined using a custom HKDF
* expansion, and the
* derived key is used to encrypt data with AES-GCM.
*
* SAST/CBOM Notes:
* - Parent Classification: Hybrid Cryptosystem (Classical ECDH + Post-Quantum
* Secret + KDF + AES-GCM).
* - SAST: The combination of classical and post-quantum secrets is a modern
* approach. However, the
* custom HKDF expand function is simplistic and may be flagged as insecure. Use
* a standard HKDF
* implementation in production.
*
* @param ecPublicKey the recipient's EC public key.
* @param pqSharedSecret the post-quantum shared secret from a separate
* algorithm.
*/
public void postQuantumHybridEncryption(PublicKey ecPublicKey, byte[] pqSharedSecret) throws Exception {
// Step 1: Perform classical ECDH key agreement to derive a shared secret.
byte[] ecdhSharedSecret = deriveSharedSecret(generateECKeyPair().getPrivate(), ecPublicKey);
// Step 2: Combine the ECDH secret and the post-quantum secret using a
// simplified HKDF expansion.
// SAST Note: This custom HKDF implementation is minimal and does not follow the
// full HKDF spec.
byte[] combinedSecret = hkdfExpand(ecdhSharedSecret, pqSharedSecret, 32);
// Use the first 16 bytes as the AES key (128-bit key).
SecretKey aesKey = new SecretKeySpec(combinedSecret, 0, 16, "AES");
// Step 3: Encrypt the data using AES-GCM.
Cipher aesCipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = new byte[12]; // 12-byte IV recommended for GCM.
new SecureRandom().nextBytes(iv);
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey, gcmSpec);
byte[] encryptedData = aesCipher.doFinal("Post-Quantum Hybrid Encryption Data".getBytes());
System.out.println("Post-Quantum Hybrid Encryption - Encrypted Data: "
+ Base64.getEncoder().encodeToString(encryptedData));
}
/**
* A simplified HKDF expansion function that uses HMAC-SHA256 to derive a key of
* a desired length.
*
* SAST/CBOM Notes:
* - Parent Classification: Key Derivation Function (KDF).
* - SAST: Custom KDF implementations are risky if not thoroughly vetted. This
* simple HKDF expand
* function lacks the full HKDF mechanism (e.g., multiple iterations, info, and
* context parameters)
* and may be flagged. It is recommended to use a standardized HKDF library.
*
* @param inputKey the input key material.
* @param salt a salt value (here, the post-quantum shared secret is used as
* the salt).
* @param length the desired length of the derived key.
* @return a derived key of the specified length.
*/
private byte[] hkdfExpand(byte[] inputKey, byte[] salt, int length) throws Exception {
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKey secretKey = new SecretKeySpec(salt, "HmacSHA256");
hmac.init(secretKey);
byte[] extractedKey = hmac.doFinal(inputKey);
return Arrays.copyOf(extractedKey, length);
}
}