mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Crypto: Add jca unit tests.
This commit is contained in:
115
java/ql/test/experimental/library-tests/quantum/jca/Nonce.java
Normal file
115
java/ql/test/experimental/library-tests/quantum/jca/Nonce.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package com.example.crypto.artifacts;
|
||||
|
||||
// import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.Cipher;
|
||||
import java.security.*;
|
||||
import java.util.Base64;
|
||||
import java.util.Random;
|
||||
|
||||
public class Nonce {
|
||||
|
||||
// static {
|
||||
// Security.addProvider(new BouncyCastleProvider()); // Ensure BouncyCastle is available
|
||||
// }
|
||||
|
||||
/**
|
||||
* Simple Case: Generates a secure nonce and uses it in HMAC.
|
||||
*/
|
||||
public void simpleNonceUsage() throws Exception {
|
||||
byte[] nonce = secureNonce(16);
|
||||
SecretKey key = generateHmacKey();
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(key);
|
||||
mac.update(nonce);
|
||||
byte[] macResult = mac.doFinal("Simple Test Data".getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Incorrect: Hardcoded, reused nonce in encryption, leading to predictable
|
||||
* output.
|
||||
*/
|
||||
public void hardcodedNonceReuse() throws Exception {
|
||||
byte[] nonce = "BADNONCEBADNONCE".getBytes(); // HARDCODED NONCE REUSED!
|
||||
SecretKey key = generateHmacKey();
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(key);
|
||||
mac.update(nonce);
|
||||
byte[] macResult = mac.doFinal("Sensitive Data".getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Incorrect: Reusing a nonce with AES-GCM, which can lead to catastrophic
|
||||
* security failures.
|
||||
*/
|
||||
public void insecureNonceReuseGCM(SecretKey key, byte[] plaintext) throws Exception {
|
||||
byte[] nonce = getReusedNonce(12); // SAME NONCE REUSED!
|
||||
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, nonce);
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec);
|
||||
byte[] ciphertext = cipher.doFinal(plaintext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Secure Case: Proper unique nonce usage in AES-GCM.
|
||||
*/
|
||||
public void secureNonceUsageGCM(SecretKey key, byte[] plaintext) throws Exception {
|
||||
byte[] nonce = secureNonce(12);
|
||||
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, nonce);
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec);
|
||||
byte[] ciphertext = cipher.doFinal(plaintext);
|
||||
}
|
||||
|
||||
public void complexNonceFlow() {
|
||||
byte[] nonce = useSecureMethod() ? secureNonce(16) : insecureNonce(16);
|
||||
processNonce(nonce);
|
||||
try {
|
||||
useNonceInMac(nonce, generateHmacKey(), "HmacSHA256");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void useNonceInMac(byte[] nonce, SecretKey key, String macAlgorithm) throws Exception {
|
||||
Mac mac = Mac.getInstance(macAlgorithm);
|
||||
mac.init(key);
|
||||
mac.update(nonce);
|
||||
byte[] macResult = mac.doFinal("Sensitive Data".getBytes());
|
||||
}
|
||||
|
||||
private boolean useSecureMethod() {
|
||||
return System.currentTimeMillis() % 2 == 0;
|
||||
}
|
||||
|
||||
private void processNonce(byte[] nonce) {
|
||||
String nonceBase64 = Base64.getEncoder().encodeToString(nonce);
|
||||
}
|
||||
|
||||
private SecretKey generateHmacKey() throws NoSuchAlgorithmException {
|
||||
KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256");
|
||||
return keyGen.generateKey();
|
||||
}
|
||||
|
||||
private byte[] secureNonce(int length) {
|
||||
byte[] nonce = new byte[length];
|
||||
new SecureRandom().nextBytes(nonce);
|
||||
return nonce;
|
||||
}
|
||||
|
||||
private byte[] insecureNonce(int length) {
|
||||
byte[] nonce = new byte[length];
|
||||
new Random().nextBytes(nonce);
|
||||
return nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Incorrect: A nonce that is stored and reused across multiple encryptions.
|
||||
*/
|
||||
private byte[] getReusedNonce(int length) {
|
||||
return "BADNONCEBADNONCE".getBytes(); // Fixed nonce reuse across calls
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user