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

132 lines
5.3 KiB
Java

package com.example.crypto.algorithms;
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.SecureRandom;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
/**
* SymmetricModesTest demonstrates the use of advanced cipher modes for
* symmetric encryption:
*
* 1. AES/KWP/NoPadding: Uses AES Key Wrap with Padding (KWP) to securely wrap
* (encrypt) a key. - Secure usage: Uses a randomly generated wrapping key.
*
* 2. AES/OFB8/NoPadding: Uses AES in Output Feedback mode with an 8-bit
* feedback size. - Secure usage: Uses a random IV for each encryption. -
* Insecure usage: Using a fixed IV (or nonce) in OFB mode compromises
* confidentiality.
*
* In production, algorithm parameters (such as mode, padding, and IV
* generation) should be externalized via configuration files to support crypto
* agility.
*/
public class SymmetricModesTest {
// static {
// // Register BouncyCastle provider for additional cipher modes.
// Security.addProvider(new BouncyCastleProvider());
// }
// ---------------------------
// AES/KWP/NoPadding Example
// ---------------------------
/**
* Securely wraps a target AES key using AES/KWP/NoPadding.
*
* Best Practice: - The wrapping key must be generated randomly. - AES/KWP
* provides key wrapping with padding, suitable for keys whose lengths are
* not multiples of the block size.
*
* @return The Base64-encoded wrapped key.
* @throws Exception if an error occurs during key wrapping.
*/
public String secureAESKWPWrap() throws Exception {
// Generate a random wrapping key (256-bit) for key wrapping.
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256, new SecureRandom());
SecretKey wrappingKey = kg.generateKey();
// Generate a target AES key to be wrapped (128-bit).
kg.init(128, new SecureRandom());
SecretKey targetKey = kg.generateKey();
// Use AES/KWP (Key Wrap with Padding) to wrap the target key.
Cipher cipher = Cipher.getInstance("AES/KWP/NoPadding", "BC");
cipher.init(Cipher.WRAP_MODE, wrappingKey);
byte[] wrappedKey = cipher.wrap(targetKey);
return Base64.getEncoder().encodeToString(wrappedKey);
}
// ---------------------------
// AES/OFB8/NoPadding Examples
// ---------------------------
/**
* Securely encrypts plaintext using AES in OFB mode with an 8-bit feedback
* size (AES/OFB8/NoPadding).
*
* Best Practice: - Use a fresh, random IV for each encryption operation.
*
* @param key The AES key.
* @param plaintext The plaintext to encrypt.
* @return The ciphertext (Base64-encoded) with the IV prepended.
* @throws Exception if encryption fails.
*/
public String secureAesOfb8Encryption(SecretKey key, byte[] plaintext) throws Exception {
Cipher cipher = Cipher.getInstance("AES/OFB8/NoPadding", "BC");
byte[] iv = new byte[16]; // IV size for AES block cipher (128-bit) even if feedback is 8-bit.
new SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] ciphertext = cipher.doFinal(plaintext);
// Prepend IV to ciphertext (as is common practice)
byte[] output = new byte[iv.length + ciphertext.length];
System.arraycopy(iv, 0, output, 0, iv.length);
System.arraycopy(ciphertext, 0, output, iv.length, ciphertext.length);
return Base64.getEncoder().encodeToString(output);
}
/**
* Insecurely encrypts plaintext using AES in OFB mode with an 8-bit
* feedback size (AES/OFB8/NoPadding) by using a fixed IV.
*
* Best Practice Violation: - Using a fixed IV (or nonce) with any
* encryption mode (including OFB) compromises the cipher's security.
*
* @param key The AES key.
* @param plaintext The plaintext to encrypt.
* @return The ciphertext (Base64-encoded) with the fixed IV prepended.
* @throws Exception if encryption fails.
*/
public String insecureAesOfb8Encryption(SecretKey key, byte[] plaintext) throws Exception {
Cipher cipher = Cipher.getInstance("AES/OFB8/NoPadding", "BC");
// Fixed IV: Insecure because it causes nonce/IV reuse.
byte[] fixedIV = new byte[16]; // All zeros.
IvParameterSpec ivSpec = new IvParameterSpec(fixedIV);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] ciphertext = cipher.doFinal(plaintext);
byte[] output = new byte[fixedIV.length + ciphertext.length];
System.arraycopy(fixedIV, 0, output, 0, fixedIV.length);
System.arraycopy(ciphertext, 0, output, fixedIV.length, ciphertext.length);
return Base64.getEncoder().encodeToString(output);
}
// ---------------------------
// Helper Methods
// ---------------------------
/**
* Generates a secure 256-bit AES key.
*
* @return A new AES SecretKey.
* @throws Exception if key generation fails.
*/
public SecretKey generateAESKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256, new SecureRandom());
return kg.generateKey();
}
}