Skip to content

Commit e0ff863

Browse files
committed
Support additional JCA algorithms and tests
Extend the experimental JCA model to recognize additional symmetric ciphers and padding/mode types (ARIA, Camellia, Twofish, SEED, Salsa20, LRW, PKCS1Padding, PSS) and fix DES/DESEDE classification ordering. Add test coverage with AdditionalSymmetricAlgorithms.java and expand existing tests: EllipticCurve1 (Ed448 and NIST P-256/P-384/P-521 key generation) and SymmetricModesTest (3DES ECB, DES CFB/OFB). Update standardization logic and test expectations (node_edges, node_properties, nodes) to reflect the new algorithm mappings.
1 parent 480ae61 commit e0ff863

8 files changed

Lines changed: 715 additions & 17 deletions

File tree

java/ql/lib/experimental/quantum/JCA.qll

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ module JCAModel {
2727
predicate cipher_names(string algo) {
2828
algo.toUpperCase()
2929
.matches([
30-
"AES", "AESWrap", "AESWrapPad", "ARCFOUR", "Blowfish", "ChaCha20", "ChaCha20-Poly1305",
31-
"DES", "DESede", "DESedeWrap", "ECIES", "PBEWith%", "RC2", "RC4", "RC5", "RSA",
32-
"Skipjack", "Idea"
30+
"AES", "AESWrap", "AESWrapPad", "ARCFOUR", "ARIA", "Blowfish", "Camellia",
31+
"ChaCha20", "ChaCha20-Poly1305", "DES", "DESede", "DESedeWrap", "ECIES",
32+
"PBEWith%", "RC2", "RC4", "RC5", "RSA", "Salsa20", "SEED", "Skipjack", "Idea",
33+
"Twofish"
3334
].toUpperCase())
3435
}
3536

@@ -189,6 +190,8 @@ module JCAModel {
189190
type = KeyOpAlg::PCBC() and name = "PCBC"
190191
or
191192
type = KeyOpAlg::KWP() and name = "KWP"
193+
or
194+
type = KeyOpAlg::LRW() and name = "LRW"
192195
}
193196

194197
bindingset[name]
@@ -197,13 +200,31 @@ module JCAModel {
197200
upper.matches("AES%") and
198201
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::AES())
199202
or
200-
// NOTE: there is DES and DESede
201-
upper.matches("DES%") and
203+
// NOTE: DESede (TripleDES) must be matched before DES% to avoid misclassification
204+
upper.matches("DESEDE%") and
205+
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::TRIPLE_DES())
206+
or
207+
not upper.matches("DESEDE%") and upper.matches("DES%") and
202208
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::DES())
203209
or
204210
upper = "TRIPLEDES" and
205211
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::TRIPLE_DES())
206212
or
213+
upper = "ARIA" and
214+
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::ARIA())
215+
or
216+
upper = "CAMELLIA" and
217+
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::CAMELLIA())
218+
or
219+
upper = "TWOFISH" and
220+
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::TWOFISH())
221+
or
222+
upper = "SEED" and
223+
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::SEED())
224+
or
225+
upper = "SALSA20" and
226+
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::SALSA20())
227+
or
207228
upper = "IDEA" and
208229
type = KeyOpAlg::TSymmetricCipher(KeyOpAlg::IDEA())
209230
or
@@ -363,6 +384,10 @@ module JCAModel {
363384
type instanceof KeyOpAlg::PKCS7 and name = ["PKCS5Padding", "PKCS7Padding"] // TODO: misnomer in the JCA?
364385
or
365386
type instanceof KeyOpAlg::OAEP and name.matches("OAEP%") // TODO: handle OAEPWith%
387+
or
388+
type instanceof KeyOpAlg::PKCS1_V1_5 and name = "PKCS1Padding"
389+
or
390+
type instanceof KeyOpAlg::PSS and name = "PSS"
366391
}
367392

368393
override KeyOpAlg::PaddingSchemeType getPaddingType() {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package com.example.crypto.algorithms;
2+
3+
import java.security.*;
4+
import javax.crypto.Cipher;
5+
import javax.crypto.KeyGenerator;
6+
import javax.crypto.SecretKey;
7+
import javax.crypto.spec.IvParameterSpec;
8+
9+
/**
10+
* Demonstrates symmetric encryption using cipher algorithms beyond the
11+
* standard JCA defaults, typically available through BouncyCastle.
12+
*
13+
* Algorithms covered: Twofish, ARIA, Camellia, Salsa20, SEED, Blowfish.
14+
*/
15+
public class AdditionalSymmetricAlgorithms {
16+
17+
/**
18+
* Twofish in CBC mode with PKCS5 padding.
19+
*/
20+
public byte[] twofishEncrypt(byte[] plaintext) throws Exception {
21+
KeyGenerator keyGen = KeyGenerator.getInstance("Twofish");
22+
keyGen.init(256);
23+
SecretKey key = keyGen.generateKey();
24+
Cipher cipher = Cipher.getInstance("Twofish/CBC/PKCS5Padding");
25+
byte[] iv = new byte[16];
26+
new SecureRandom().nextBytes(iv);
27+
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
28+
return cipher.doFinal(plaintext);
29+
}
30+
31+
/**
32+
* ARIA in CBC mode with PKCS5 padding.
33+
*/
34+
public byte[] ariaEncrypt(byte[] plaintext) throws Exception {
35+
KeyGenerator keyGen = KeyGenerator.getInstance("ARIA");
36+
keyGen.init(256);
37+
SecretKey key = keyGen.generateKey();
38+
Cipher cipher = Cipher.getInstance("ARIA/CBC/PKCS5Padding");
39+
byte[] iv = new byte[16];
40+
new SecureRandom().nextBytes(iv);
41+
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
42+
return cipher.doFinal(plaintext);
43+
}
44+
45+
/**
46+
* Camellia in CBC mode with no padding.
47+
*/
48+
public byte[] camelliaEncrypt(byte[] plaintext) throws Exception {
49+
KeyGenerator keyGen = KeyGenerator.getInstance("Camellia");
50+
keyGen.init(256);
51+
SecretKey key = keyGen.generateKey();
52+
Cipher cipher = Cipher.getInstance("Camellia/CBC/NoPadding");
53+
byte[] iv = new byte[16];
54+
new SecureRandom().nextBytes(iv);
55+
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
56+
return cipher.doFinal(plaintext);
57+
}
58+
59+
/**
60+
* Salsa20 stream cipher.
61+
*/
62+
public byte[] salsa20Encrypt(byte[] plaintext) throws Exception {
63+
KeyGenerator keyGen = KeyGenerator.getInstance("Salsa20");
64+
keyGen.init(256);
65+
SecretKey key = keyGen.generateKey();
66+
Cipher cipher = Cipher.getInstance("Salsa20");
67+
cipher.init(Cipher.ENCRYPT_MODE, key);
68+
return cipher.doFinal(plaintext);
69+
}
70+
71+
/**
72+
* SEED in CBC mode with PKCS5 padding.
73+
*/
74+
public byte[] seedEncrypt(byte[] plaintext) throws Exception {
75+
KeyGenerator keyGen = KeyGenerator.getInstance("SEED");
76+
keyGen.init(128);
77+
SecretKey key = keyGen.generateKey();
78+
Cipher cipher = Cipher.getInstance("SEED/CBC/PKCS5Padding");
79+
byte[] iv = new byte[16];
80+
new SecureRandom().nextBytes(iv);
81+
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
82+
return cipher.doFinal(plaintext);
83+
}
84+
85+
/**
86+
* Blowfish in CBC mode with PKCS5 padding.
87+
*/
88+
public byte[] blowfishEncrypt(byte[] plaintext) throws Exception {
89+
KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
90+
keyGen.init(128);
91+
SecretKey key = keyGen.generateKey();
92+
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
93+
byte[] iv = new byte[8];
94+
new SecureRandom().nextBytes(iv);
95+
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
96+
return cipher.doFinal(plaintext);
97+
}
98+
}

java/ql/test/experimental/library-tests/quantum/jca/EllipticCurve1.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,41 @@ public KeyPair generateESKeyPair() throws Exception {
115115
return kpg.generateKeyPair();
116116
}
117117

118+
/**
119+
* Generates an Ed448 key pair (for signatures).
120+
*/
121+
public KeyPair generateEd448KeyPair() throws Exception {
122+
KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed448");
123+
return kpg.generateKeyPair();
124+
}
125+
126+
/**
127+
* Generates a key pair using the NIST P-256 alias for secp256r1.
128+
*/
129+
public KeyPair generateNISTP256KeyPair() throws Exception {
130+
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
131+
kpg.initialize(new java.security.spec.ECGenParameterSpec("P-256"));
132+
return kpg.generateKeyPair();
133+
}
134+
135+
/**
136+
* Generates a key pair using the NIST P-384 alias for secp384r1.
137+
*/
138+
public KeyPair generateNISTP384KeyPair() throws Exception {
139+
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
140+
kpg.initialize(new java.security.spec.ECGenParameterSpec("P-384"));
141+
return kpg.generateKeyPair();
142+
}
143+
144+
/**
145+
* Generates a key pair using the NIST P-521 alias for secp521r1.
146+
*/
147+
public KeyPair generateNISTP521KeyPair() throws Exception {
148+
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
149+
kpg.initialize(new java.security.spec.ECGenParameterSpec("P-521"));
150+
return kpg.generateKeyPair();
151+
}
152+
118153
/**
119154
* Generates a key pair for an "Other" elliptic curve type.
120155
* This serves as a fallback example (using secp256r1).

java/ql/test/experimental/library-tests/quantum/jca/SymmetricModesTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,38 @@ public SecretKey generateAESKey() throws Exception {
128128
kg.init(256, new SecureRandom());
129129
return kg.generateKey();
130130
}
131+
132+
// ---------------------------
133+
// DESede and DES Mode Variants
134+
// ---------------------------
135+
/**
136+
* DESede (TripleDES) in ECB mode.
137+
*/
138+
public byte[] tripleDesEcbEncrypt(SecretKey key, byte[] plaintext) throws Exception {
139+
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
140+
cipher.init(Cipher.ENCRYPT_MODE, key);
141+
return cipher.doFinal(plaintext);
142+
}
143+
144+
/**
145+
* DES in CFB mode.
146+
*/
147+
public byte[] desCfbEncrypt(SecretKey key, byte[] plaintext) throws Exception {
148+
Cipher cipher = Cipher.getInstance("DES/CFB/NoPadding");
149+
byte[] iv = new byte[8];
150+
new SecureRandom().nextBytes(iv);
151+
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
152+
return cipher.doFinal(plaintext);
153+
}
154+
155+
/**
156+
* DES in OFB mode.
157+
*/
158+
public byte[] desOfbEncrypt(SecretKey key, byte[] plaintext) throws Exception {
159+
Cipher cipher = Cipher.getInstance("DES/OFB/NoPadding");
160+
byte[] iv = new byte[8];
161+
new SecureRandom().nextBytes(iv);
162+
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
163+
return cipher.doFinal(plaintext);
164+
}
131165
}

0 commit comments

Comments
 (0)