Skip to content

Commit f8915d9

Browse files
Update KeyAgreement classes to support Generic secret generation (#573)
The engineGenerateSecret(String) method in KeyAgreement classes currently only supports "TlsPremasterSecret", but the expectation starting in Java 25 is that "Generic" should be accepted as well. This change accomplishes that. Additional test cases to verify said behaviour are added. Signed-off-by: Kostas Tsiounis <[email protected]>
1 parent fe0d1c0 commit f8915d9

File tree

6 files changed

+83
-17
lines changed

6 files changed

+83
-17
lines changed

src/main/java/com/ibm/crypto/plus/provider/DHKeyAgreement.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright IBM Corp. 2023, 2024
2+
* Copyright IBM Corp. 2023, 2025
33
*
44
* This code is free software; you can redistribute it and/or modify it
55
* under the terms provided by IBM in the LICENSE file that accompanied
@@ -201,9 +201,11 @@ protected SecretKey engineGenerateSecret(String algorithm)
201201
throw new NoSuchAlgorithmException("null algorithm");
202202
}
203203

204-
if (!algorithm.equalsIgnoreCase("TlsPremasterSecret") && !AllowKDF.VALUE) {
204+
if (!(algorithm.equalsIgnoreCase("TlsPremasterSecret")
205+
|| algorithm.equalsIgnoreCase("Generic"))
206+
&& !AllowKDF.VALUE) {
205207
throw new NoSuchAlgorithmException(
206-
"Unsupported secret key " + "algorithm: " + algorithm);
208+
"Unsupported secret key algorithm: " + algorithm);
207209
}
208210

209211
byte[] secret = engineGenerateSecret();
@@ -229,12 +231,15 @@ protected SecretKey engineGenerateSecret(String algorithm)
229231
throw new InvalidKeyException("Key material is too short");
230232
}
231233
return skey;
232-
} else if (algorithm.equals("TlsPremasterSecret")) {
234+
} else if (algorithm.equalsIgnoreCase("TlsPremasterSecret")) {
233235
// remove leading zero bytes per RFC 5246 Section 8.1.2
234-
return new SecretKeySpec(KeyUtil.trimZeroes(secret), "TlsPremasterSecret");
236+
return new SecretKeySpec(
237+
KeyUtil.trimZeroes(secret), "TlsPremasterSecret");
238+
} else if (algorithm.equalsIgnoreCase("Generic")) {
239+
return new SecretKeySpec(secret, algorithm);
235240
} else {
236241
throw new NoSuchAlgorithmException(
237-
"Unsupported secret key " + "algorithm: " + algorithm);
242+
"Unsupported secret key algorithm: " + algorithm);
238243
}
239244
}
240245

src/main/java/com/ibm/crypto/plus/provider/ECDHKeyAgreement.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright IBM Corp. 2023, 2024
2+
* Copyright IBM Corp. 2023, 2025
33
*
44
* This code is free software; you can redistribute it and/or modify it
55
* under the terms provided by IBM in the LICENSE file that accompanied
@@ -203,10 +203,12 @@ protected SecretKey engineGenerateSecret(String algorithm)
203203
if (algorithm == null) {
204204
throw new NoSuchAlgorithmException("Algorithm must not be null");
205205
}
206-
if (!(algorithm.equals("TlsPremasterSecret"))) {
207-
throw new NoSuchAlgorithmException("Only supported for algorithm TlsPremasterSecret");
206+
if (!(algorithm.equalsIgnoreCase("TlsPremasterSecret")
207+
|| algorithm.equalsIgnoreCase("Generic"))) {
208+
throw new NoSuchAlgorithmException(
209+
"Unsupported secret key algorithm: " + algorithm);
208210
}
209-
return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
211+
return new SecretKeySpec(engineGenerateSecret(), algorithm);
210212
}
211213

212214
@Override

src/main/java/com/ibm/crypto/plus/provider/XDHKeyAgreement.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright IBM Corp. 2023, 2024
2+
* Copyright IBM Corp. 2023, 2025
33
*
44
* This code is free software; you can redistribute it and/or modify it
55
* under the terms provided by IBM in the LICENSE file that accompanied
@@ -150,9 +150,12 @@ protected SecretKey engineGenerateSecret(String algorithm)
150150
throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException {
151151
if (algorithm == null)
152152
throw new NoSuchAlgorithmException("Algorithm must not be null");
153-
if (!(algorithm.equals("TlsPremasterSecret")))
154-
throw new NoSuchAlgorithmException("Only supported for algorithm TlsPremasterSecret");
155-
return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
153+
if (!(algorithm.equalsIgnoreCase("TlsPremasterSecret")
154+
|| algorithm.equalsIgnoreCase("Generic"))) {
155+
throw new NoSuchAlgorithmException(
156+
"Unsupported secret key algorithm: " + algorithm);
157+
}
158+
return new SecretKeySpec(engineGenerateSecret(), algorithm);
156159
}
157160

158161
@Override

src/test/java/ibm/jceplus/junit/base/BaseTestDH.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright IBM Corp. 2023, 2024
2+
* Copyright IBM Corp. 2023, 2025
33
*
44
* This code is free software; you can redistribute it and/or modify it
55
* under the terms provided by IBM in the LICENSE file that accompanied
@@ -17,10 +17,12 @@
1717
import java.security.NoSuchProviderException;
1818
import java.security.spec.AlgorithmParameterSpec;
1919
import java.util.Arrays;
20+
import java.util.List;
2021
import javax.crypto.KeyAgreement;
2122
import javax.crypto.spec.DHParameterSpec;
2223
import org.junit.jupiter.api.BeforeEach;
2324
import org.junit.jupiter.api.Test;
25+
import static org.junit.jupiter.api.Assertions.assertEquals;
2426
import static org.junit.jupiter.api.Assertions.assertTrue;
2527

2628
public class BaseTestDH extends BaseTestJunit5 {
@@ -212,6 +214,23 @@ public void testDH_DHSpec() throws Exception {
212214

213215
}
214216

217+
@Test
218+
public void test_engineGenerateSecret() throws Exception {
219+
try {
220+
KeyPairGenerator g = KeyPairGenerator.getInstance("DH", getProviderName());
221+
KeyPair kp1 = g.generateKeyPair();
222+
KeyPair kp2 = g.generateKeyPair();
223+
KeyAgreement ka = KeyAgreement.getInstance("DH", getProviderName());
224+
for (String alg : List.of("TlsPremasterSecret", "Generic")) {
225+
ka.init(kp1.getPrivate());
226+
ka.doPhase(kp2.getPublic(), true);
227+
assertEquals(ka.generateSecret(alg).getAlgorithm(), alg);
228+
}
229+
} catch (Exception e) {
230+
throw e;
231+
}
232+
}
233+
215234
void compute_dh_key(String idString, AlgorithmParameterSpec algParameterSpec)
216235
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException,
217236
NoSuchProviderException, InvalidKeyException {

src/test/java/ibm/jceplus/junit/base/BaseTestECDH.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright IBM Corp. 2023, 2024
2+
* Copyright IBM Corp. 2023, 2025
33
*
44
* This code is free software; you can redistribute it and/or modify it
55
* under the terms provided by IBM in the LICENSE file that accompanied
@@ -25,9 +25,11 @@
2525
import java.security.spec.EllipticCurve;
2626
import java.security.spec.InvalidParameterSpecException;
2727
import java.util.Arrays;
28+
import java.util.List;
2829
import javax.crypto.KeyAgreement;
2930
import org.junit.jupiter.api.BeforeEach;
3031
import org.junit.jupiter.api.Test;
32+
import static org.junit.jupiter.api.Assertions.assertEquals;
3133
import static org.junit.jupiter.api.Assertions.assertNotNull;
3234
import static org.junit.jupiter.api.Assertions.assertTrue;
3335
import static org.junit.jupiter.api.Assertions.fail;
@@ -301,6 +303,23 @@ public void testEC_engineInit_AlgorithmParameterSpec_paramSpec() throws Exceptio
301303
fail("InvalidParameterSpecException expected but no exception was thrown");
302304
}
303305

306+
@Test
307+
public void test_engineGenerateSecret() throws Exception {
308+
try {
309+
KeyPairGenerator g = KeyPairGenerator.getInstance("DH", getProviderName());
310+
KeyPair kp1 = g.generateKeyPair();
311+
KeyPair kp2 = g.generateKeyPair();
312+
KeyAgreement ka = KeyAgreement.getInstance("DH", getProviderName());
313+
for (String alg : List.of("TlsPremasterSecret", "Generic")) {
314+
ka.init(kp1.getPrivate());
315+
ka.doPhase(kp2.getPublic(), true);
316+
assertEquals(ka.generateSecret(alg).getAlgorithm(), alg);
317+
}
318+
} catch (Exception e) {
319+
throw e;
320+
}
321+
}
322+
304323
void compute_ecdh_key_with_global_key(String idString, AlgorithmParameterSpec algParameterSpec)
305324
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException,
306325
NoSuchProviderException, InvalidKeyException {

src/test/java/ibm/jceplus/junit/base/BaseTestXDH.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright IBM Corp. 2023, 2024
2+
* Copyright IBM Corp. 2023, 2025
33
*
44
* This code is free software; you can redistribute it and/or modify it
55
* under the terms provided by IBM in the LICENSE file that accompanied
@@ -29,6 +29,7 @@
2929
import java.security.spec.XECPrivateKeySpec;
3030
import java.security.spec.XECPublicKeySpec;
3131
import java.util.Arrays;
32+
import java.util.List;
3233
import javax.crypto.KeyAgreement;
3334
import org.junit.jupiter.api.Test;
3435
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -90,6 +91,23 @@ public void testXDH_runCurveMixTest() throws Exception {
9091
runCurveMixTest();
9192
}
9293

94+
@Test
95+
public void test_engineGenerateSecret() throws Exception {
96+
try {
97+
KeyPairGenerator g = KeyPairGenerator.getInstance("DH", getProviderName());
98+
KeyPair kp1 = g.generateKeyPair();
99+
KeyPair kp2 = g.generateKeyPair();
100+
KeyAgreement ka = KeyAgreement.getInstance("DH", getProviderName());
101+
for (String alg : List.of("TlsPremasterSecret", "Generic")) {
102+
ka.init(kp1.getPrivate());
103+
ka.doPhase(kp2.getPublic(), true);
104+
assertEquals(ka.generateSecret(alg).getAlgorithm(), alg);
105+
}
106+
} catch (Exception e) {
107+
throw e;
108+
}
109+
}
110+
93111
void compute_xdh_key(String idString, NamedParameterSpec algParameterSpec)
94112
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException,
95113
NoSuchProviderException, InvalidKeyException {

0 commit comments

Comments
 (0)