Files
codeql/java/ql/test/experimental/library-tests/quantum/jca/EllipticCurve2.java
2025-10-06 10:46:09 -04:00

273 lines
10 KiB
Java

package com.example.crypto.algorithms;
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* EllipticCurve2 demonstrates real-world uses of elliptic curve algorithms,
* including key pair generation, key agreement (ECDH), digital signatures
* (ECDSA, EdDSA), and a simple simulation of ECIES (using ECDH + AES-GCM).
*
* Curve types shown include: - NIST (e.g., secp256r1) - SEC (e.g., secp256k1) -
* Brainpool (e.g., brainpoolP256r1) - CURVE25519 (for X25519 key agreement) -
* ES (e.g., Ed25519 for signatures) - Other fallback (e.g., secp256r1 for
* "OtherEllipticCurveType")
*
* Best practices: - Use ephemeral keys and a strong RNG. - Use proper key
* agreement (with a KDF if needed) and digital signature schemes. - Avoid
* static key reuse or using weak curves.
*
* SAST/CBOM considerations: - Secure implementations use ephemeral keys and
* modern curves. - Insecure practices (e.g., static keys or reusing keys) must
* be flagged.
*/
public class EllipticCurve2 {
// static {
// // Register BouncyCastle provider for additional curves and algorithms.
// Security.addProvider(new BouncyCastleProvider());
// }
// ----------------------------
// 1. Key Pair Generation Examples
// ----------------------------
/**
* Generates a key pair using a NIST curve (secp256r1).
*/
public KeyPair generateNISTKeyPair() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());
return kpg.generateKeyPair();
}
/**
* Generates a key pair using a SEC curve (secp256k1).
*/
public KeyPair generateSECCurveKeyPair() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(new ECGenParameterSpec("secp256k1"), new SecureRandom());
return kpg.generateKeyPair();
}
/**
* Generates a key pair using a Brainpool curve (brainpoolP256r1).
*/
public KeyPair generateBrainpoolKeyPair() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(new ECGenParameterSpec("brainpoolP256r1"), new SecureRandom());
return kpg.generateKeyPair();
}
/**
* Generates an X25519 key pair.
*/
public KeyPair generateX25519KeyPair() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("X25519", "BC");
return kpg.generateKeyPair();
}
/**
* Generates an Ed25519 key pair (used for signatures).
*/
public KeyPair generateEd25519KeyPair() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519", "BC");
return kpg.generateKeyPair();
}
/**
* Generates a key pair for "OtherEllipticCurveType" as a fallback (using
* secp256r1).
*/
public KeyPair generateOtherEllipticCurveKeyPair() throws Exception {
return generateNISTKeyPair();
}
// ----------------------------
// 2. Key Agreement (ECDH) Examples
// ----------------------------
/**
* Performs ECDH key agreement using two ephemeral NIST key pairs. Secure
* Example: Uses ephemeral keys and a strong RNG.
*
* @return The shared secret.
*/
public byte[] performECDHKeyAgreement() throws Exception {
KeyPair aliceKP = generateNISTKeyPair();
KeyPair bobKP = generateNISTKeyPair();
KeyAgreement ka = KeyAgreement.getInstance("ECDH", "BC");
ka.init(aliceKP.getPrivate());
ka.doPhase(bobKP.getPublic(), true);
return ka.generateSecret();
}
/**
* Insecure ECDH Example: Uses a static key pair for both parties. SAST:
* Reusing the same key pair eliminates forward secrecy and is insecure.
*
* @return The (insecure) shared secret.
*/
public byte[] insecureECDHKeyAgreement() throws Exception {
KeyPair staticKP = generateNISTKeyPair();
KeyAgreement ka = KeyAgreement.getInstance("ECDH", "BC");
ka.init(staticKP.getPrivate());
ka.doPhase(staticKP.getPublic(), true);
return ka.generateSecret();
}
// ----------------------------
// 3. Digital Signature Examples
// ----------------------------
/**
* Generates an ECDSA signature using a NIST key pair. Secure Example.
*
* @param message The message to sign.
* @return The signature.
*/
public byte[] generateECDSASignature(byte[] message) throws Exception {
KeyPair kp = generateNISTKeyPair();
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
signature.initSign(kp.getPrivate());
signature.update(message);
return signature.sign();
}
/**
* Verifies an ECDSA signature using the corresponding NIST key pair.
*
* @param message The original message.
* @param signatureBytes The signature to verify.
* @param kp The key pair used for signing.
* @return True if the signature is valid.
*/
public boolean verifyECDSASignature(byte[] message, byte[] signatureBytes, KeyPair kp) throws Exception {
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
signature.initVerify(kp.getPublic());
signature.update(message);
return signature.verify(signatureBytes);
}
/**
* Generates an Ed25519 signature. Secure Example: Ed25519 is a modern,
* high-performance signature scheme.
*
* @param message The message to sign.
* @return The signature.
*/
public byte[] generateEd25519Signature(byte[] message) throws Exception {
KeyPair kp = generateEd25519KeyPair();
Signature signature = Signature.getInstance("Ed25519", "BC");
signature.initSign(kp.getPrivate());
signature.update(message);
return signature.sign();
}
/**
* Verifies an Ed25519 signature.
*
* @param message The original message.
* @param signatureBytes The signature to verify.
* @param kp The key pair used for signing.
* @return True if the signature is valid.
*/
public boolean verifyEd25519Signature(byte[] message, byte[] signatureBytes, KeyPair kp) throws Exception {
Signature signature = Signature.getInstance("Ed25519", "BC");
signature.initVerify(kp.getPublic());
signature.update(message);
return signature.verify(signatureBytes);
}
// ----------------------------
// 4. ECIES-like Encryption (ECDH + AES-GCM)
// ----------------------------
/**
* A simple simulation of ECIES using ECDH for key agreement and AES-GCM for
* encryption. Secure Example: Uses ephemeral ECDH key pairs, a KDF to
* derive a symmetric key, and AES-GCM with a random nonce.
*
* @param plaintext The plaintext to encrypt.
* @return The concatenation of the ephemeral public key, IV, and ciphertext
* (Base64-encoded).
* @throws Exception if encryption fails.
*/
public String eciesEncryptionExample(byte[] plaintext) throws Exception {
// Generate ephemeral key pairs for two parties.
KeyPair senderKP = generateNISTKeyPair();
KeyPair receiverKP = generateNISTKeyPair();
// Perform ECDH key agreement.
KeyAgreement ka = KeyAgreement.getInstance("ECDH", "BC");
ka.init(senderKP.getPrivate());
ka.doPhase(receiverKP.getPublic(), true);
byte[] sharedSecret = ka.generateSecret();
// Derive a symmetric key from the shared secret using SHA-256 (first 16 bytes
// for AES-128).
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] derivedKey = digest.digest(sharedSecret);
derivedKey = Arrays.copyOf(derivedKey, 16);
SecretKey aesKey = new SecretKeySpec(derivedKey, "AES");
// Encrypt plaintext using AES-GCM with a random nonce.
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = new byte[12];
new SecureRandom().nextBytes(iv);
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, aesKey, spec);
byte[] ciphertext = cipher.doFinal(plaintext);
// For ECIES, include the sender's ephemeral public key with the output.
byte[] senderPub = senderKP.getPublic().getEncoded();
byte[] output = concatenate(senderPub, concatenate(iv, ciphertext));
return Base64.getEncoder().encodeToString(output);
}
// ----------------------------
// 5. Main Method for Demonstration
// ----------------------------
public static void main(String[] args) {
try {
EllipticCurve2 test = new EllipticCurve2();
// Key Agreement Example:
byte[] sharedSecret = test.performECDHKeyAgreement();
System.out.println("ECDH Shared Secret (Base64): " + Base64.getEncoder().encodeToString(sharedSecret));
// ECDSA Signature Example:
byte[] message = "Test message for ECDSA".getBytes();
KeyPair nistKP = test.generateNISTKeyPair();
byte[] ecdsaSig = test.generateECDSASignature(message);
boolean validSig = test.verifyECDSASignature(message, ecdsaSig, nistKP);
System.out.println("ECDSA Signature valid? " + validSig);
// Ed25519 Signature Example:
byte[] edSig = test.generateEd25519Signature(message);
KeyPair edKP = test.generateEd25519KeyPair();
boolean validEdSig = test.verifyEd25519Signature(message, edSig, edKP);
System.out.println("Ed25519 Signature valid? " + validEdSig);
// ECIES-like Encryption Example:
String eciesOutput = test.eciesEncryptionExample("Secret ECIES Message".getBytes());
System.out.println("ECIES-like Encrypted Output (Base64): " + eciesOutput);
} catch (Exception e) {
e.printStackTrace();
}
}
private byte[] concatenate(byte[] a, byte[] b) {
byte[] result = new byte[a.length + b.length];
System.arraycopy(a, 0, result, 0, a.length);
System.arraycopy(b, 0, result, a.length, b.length);
return result;
}
}