From 33aa6c94df17cf294f1b93b81d78c5e34d3c6f67 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 20 Aug 2025 13:21:18 -0400 Subject: [PATCH 1/3] Crypto: Adding tests for reuse nonce query for JAVA/JCA. --- .../quantum/NonceReuse/NonceReuse.expected | 4 + .../quantum/NonceReuse/NonceReuse.qlref | 1 + .../query-tests/quantum/NonceReuse/Test.java | 108 ++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected create mode 100644 java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.qlref create mode 100644 java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java diff --git a/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected b/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected new file mode 100644 index 000000000000..7afd24f0dfb7 --- /dev/null +++ b/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected @@ -0,0 +1,4 @@ +| Test.java:48:47:48:52 | Nonce | Reuse with nonce $@ | Test.java:57:47:57:52 | Nonce | Nonce | +| Test.java:57:47:57:52 | Nonce | Reuse with nonce $@ | Test.java:48:47:48:52 | Nonce | Nonce | +| Test.java:85:48:85:54 | Nonce | Reuse with nonce $@ | Test.java:91:49:91:55 | Nonce | Nonce | +| Test.java:91:49:91:55 | Nonce | Reuse with nonce $@ | Test.java:85:48:85:54 | Nonce | Nonce | diff --git a/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.qlref b/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.qlref new file mode 100644 index 000000000000..bfe67a6c2e8e --- /dev/null +++ b/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.qlref @@ -0,0 +1 @@ +experimental/quantum/Analysis/ReusedNonce.ql \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java b/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java new file mode 100644 index 000000000000..cfb4c2e4fda4 --- /dev/null +++ b/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java @@ -0,0 +1,108 @@ +package com.example.crypto.artifacts; +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.GCMParameterSpec; +import java.security.*; +import java.util.Base64; +import java.util.random.*; +import java.util.Properties; +import java.util.Random; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Arrays; + +public class Test { + + public static SecretKey generateAESKey()throws Exception { + KeyGenerator keyGen = KeyGenerator.getInstance("AES"); + keyGen.init(256); + return keyGen.generateKey(); + } + + + private static byte[] getRandomWrapper1()throws Exception { + byte[] val = new byte[16]; + new SecureRandom().nextBytes(val); + return val; + } + + private static byte[] getRandomWrapper2A()throws Exception { + byte[] val; + val = getRandomWrapper1(); + funcA1(val); + return val; + } + + private static byte[] getRandomWrapper2b()throws Exception { + byte[] val; + val = getRandomWrapper1(); + return val; + } + + private static void funcA1(byte[] iv)throws Exception { + IvParameterSpec ivSpec = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKey key = generateAESKey(); + cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); // BAD: Reuse of `iv` in funcB1 + byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); + } + + private static void funcB1()throws Exception { + byte[] iv = getRandomWrapper2A(); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKey key = generateAESKey(); + cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); // BAD: Reuse of `iv` in funcA1 + byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); + } + + private static void funcA2()throws Exception { + byte[] iv = getRandomWrapper2b(); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKey key = generateAESKey(); + cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); // GOOD + byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); + } + + private static void funcB2()throws Exception { + byte[] iv = getRandomWrapper2b(); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKey key = generateAESKey(); + cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); // GOOD + byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); + } + + + private static void funcA3() throws Exception { + byte[] iv = getRandomWrapper2b(); + IvParameterSpec ivSpec1 = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKey key1 = generateAESKey(); + cipher.init(Cipher.ENCRYPT_MODE, key1, ivSpec1); // BAD: reuse of `iv` below + byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); + + IvParameterSpec ivSpec2 = new IvParameterSpec(iv); + Cipher cipher2 = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKey key2 = generateAESKey(); + cipher2.init(Cipher.ENCRYPT_MODE, key2, ivSpec2); // BAD: Reuse of `iv` above + byte[] ciphertext2 = cipher2.doFinal("Simple Test Data".getBytes()); + } + + + + + public static void main(String[] args) { + try{ + funcA2(); + funcB1(); + funcB2(); + } + catch(Exception e) { + e.printStackTrace(); + } + } +} From 30a07763e8de5588394fb3b6d97e053889d506d8 Mon Sep 17 00:00:00 2001 From: "REDMOND\\brodes" Date: Wed, 20 Aug 2025 13:28:28 -0400 Subject: [PATCH 2/3] Crypto: Copilot suggested code changes. --- .../query-tests/quantum/NonceReuse/NonceReuse.expected | 8 ++++---- .../experimental/query-tests/quantum/NonceReuse/Test.java | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected b/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected index 7afd24f0dfb7..7372722c2f57 100644 --- a/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected +++ b/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected @@ -1,4 +1,4 @@ -| Test.java:48:47:48:52 | Nonce | Reuse with nonce $@ | Test.java:57:47:57:52 | Nonce | Nonce | -| Test.java:57:47:57:52 | Nonce | Reuse with nonce $@ | Test.java:48:47:48:52 | Nonce | Nonce | -| Test.java:85:48:85:54 | Nonce | Reuse with nonce $@ | Test.java:91:49:91:55 | Nonce | Nonce | -| Test.java:91:49:91:55 | Nonce | Reuse with nonce $@ | Test.java:85:48:85:54 | Nonce | Nonce | +| Test.java:47:47:47:52 | Nonce | Reuse with nonce $@ | Test.java:56:47:56:52 | Nonce | Nonce | +| Test.java:56:47:56:52 | Nonce | Reuse with nonce $@ | Test.java:47:47:47:52 | Nonce | Nonce | +| Test.java:84:48:84:54 | Nonce | Reuse with nonce $@ | Test.java:90:49:90:55 | Nonce | Nonce | +| Test.java:90:49:90:55 | Nonce | Reuse with nonce $@ | Test.java:84:48:84:54 | Nonce | Nonce | diff --git a/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java b/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java index cfb4c2e4fda4..2f3aab5b6ef3 100644 --- a/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java +++ b/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java @@ -6,7 +6,6 @@ import javax.crypto.spec.GCMParameterSpec; import java.security.*; import java.util.Base64; -import java.util.random.*; import java.util.Properties; import java.util.Random; import java.io.FileInputStream; From 15e9bb9cc1346ac5cb1a6c97bebc83f856984a77 Mon Sep 17 00:00:00 2001 From: Nicolas Will Date: Mon, 6 Oct 2025 16:29:25 +0200 Subject: [PATCH 3/3] Format Test and update .expected --- .../quantum/NonceReuse/NonceReuse.expected | 8 ++-- .../query-tests/quantum/NonceReuse/Test.java | 40 +++++++------------ 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected b/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected index 7372722c2f57..38ba6187b595 100644 --- a/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected +++ b/java/ql/test/experimental/query-tests/quantum/NonceReuse/NonceReuse.expected @@ -1,4 +1,4 @@ -| Test.java:47:47:47:52 | Nonce | Reuse with nonce $@ | Test.java:56:47:56:52 | Nonce | Nonce | -| Test.java:56:47:56:52 | Nonce | Reuse with nonce $@ | Test.java:47:47:47:52 | Nonce | Nonce | -| Test.java:84:48:84:54 | Nonce | Reuse with nonce $@ | Test.java:90:49:90:55 | Nonce | Nonce | -| Test.java:90:49:90:55 | Nonce | Reuse with nonce $@ | Test.java:84:48:84:54 | Nonce | Nonce | +| Test.java:40:47:40:52 | Nonce | Reuse with nonce $@ | Test.java:49:47:49:52 | Nonce | Nonce | +| Test.java:49:47:49:52 | Nonce | Reuse with nonce $@ | Test.java:40:47:40:52 | Nonce | Nonce | +| Test.java:76:48:76:54 | Nonce | Reuse with nonce $@ | Test.java:82:49:82:55 | Nonce | Nonce | +| Test.java:82:49:82:55 | Nonce | Reuse with nonce $@ | Test.java:76:48:76:54 | Nonce | Nonce | diff --git a/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java b/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java index 2f3aab5b6ef3..1b65e324275b 100644 --- a/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java +++ b/java/ql/test/experimental/query-tests/quantum/NonceReuse/Test.java @@ -1,46 +1,39 @@ package com.example.crypto.artifacts; + +import java.security.*; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.GCMParameterSpec; -import java.security.*; -import java.util.Base64; -import java.util.Properties; -import java.util.Random; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Arrays; public class Test { - public static SecretKey generateAESKey()throws Exception { + public static SecretKey generateAESKey() throws Exception { KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(256); return keyGen.generateKey(); } - - private static byte[] getRandomWrapper1()throws Exception { + private static byte[] getRandomWrapper1() throws Exception { byte[] val = new byte[16]; new SecureRandom().nextBytes(val); return val; } - private static byte[] getRandomWrapper2A()throws Exception { + private static byte[] getRandomWrapper2A() throws Exception { byte[] val; - val = getRandomWrapper1(); + val = getRandomWrapper1(); funcA1(val); return val; } - private static byte[] getRandomWrapper2b()throws Exception { + private static byte[] getRandomWrapper2b() throws Exception { byte[] val; - val = getRandomWrapper1(); + val = getRandomWrapper1(); return val; } - private static void funcA1(byte[] iv)throws Exception { + private static void funcA1(byte[] iv) throws Exception { IvParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKey key = generateAESKey(); @@ -48,7 +41,7 @@ private static void funcA1(byte[] iv)throws Exception { byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); } - private static void funcB1()throws Exception { + private static void funcB1() throws Exception { byte[] iv = getRandomWrapper2A(); IvParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); @@ -57,7 +50,7 @@ private static void funcB1()throws Exception { byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); } - private static void funcA2()throws Exception { + private static void funcA2() throws Exception { byte[] iv = getRandomWrapper2b(); IvParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); @@ -66,7 +59,7 @@ private static void funcA2()throws Exception { byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); } - private static void funcB2()throws Exception { + private static void funcB2() throws Exception { byte[] iv = getRandomWrapper2b(); IvParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); @@ -75,7 +68,6 @@ private static void funcB2()throws Exception { byte[] ciphertext = cipher.doFinal("Simple Test Data".getBytes()); } - private static void funcA3() throws Exception { byte[] iv = getRandomWrapper2b(); IvParameterSpec ivSpec1 = new IvParameterSpec(iv); @@ -91,16 +83,12 @@ private static void funcA3() throws Exception { byte[] ciphertext2 = cipher2.doFinal("Simple Test Data".getBytes()); } - - - public static void main(String[] args) { - try{ + try { funcA2(); funcB1(); funcB2(); - } - catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); } }