Skip to content

Commit e4ff2c1

Browse files
committed
Merge branch 'main' of gitlab.cryptoworkshop.com:root/bc-java
2 parents 8837d91 + acd8f6d commit e4ff2c1

File tree

10 files changed

+314
-39
lines changed

10 files changed

+314
-39
lines changed

core/src/main/java/org/bouncycastle/crypto/signers/DSTU4145Signer.java

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public BigInteger[] generateSignature(byte[] message)
9191
{
9292
do
9393
{
94-
e = generateRandomInteger(n, random);
94+
e = BigIntegers.createRandomInRange(BigInteger.ONE, n.subtract(BigInteger.ONE), random);
9595
Fe = basePointMultiplier.multiply(ec.getG(), e).normalize().getAffineXCoord();
9696
}
9797
while (Fe.isZero());
@@ -148,23 +148,6 @@ protected ECMultiplier createBasePointMultiplier()
148148
return new FixedPointCombMultiplier();
149149
}
150150

151-
/**
152-
* Generates random integer such that its value is less than that of n
153-
*/
154-
private static BigInteger generateRandomInteger(BigInteger n, SecureRandom random)
155-
{
156-
int nBitLength = n.bitLength();
157-
158-
BigInteger k;
159-
do
160-
{
161-
k = BigIntegers.createRandomBigInteger(nBitLength, random);
162-
}
163-
while (k.equals(BigIntegers.ZERO) || k.compareTo(n) >= 0);
164-
165-
return k;
166-
}
167-
168151
private static ECFieldElement hash2FieldElement(ECCurve curve, byte[] hash)
169152
{
170153
byte[] data = Arrays.reverse(hash);

prov/src/main/jdk25/org/bouncycastle/jcajce/provider/kdf/hkdf/HKDFSpi.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
import java.security.InvalidAlgorithmParameterException;
1616
import java.security.NoSuchAlgorithmException;
1717
import java.security.spec.AlgorithmParameterSpec;
18+
import java.util.ArrayList;
1819
import java.util.List;
20+
import org.bouncycastle.util.Arrays;
1921

2022
class HKDFSpi
2123
extends KDFSpi
@@ -67,7 +69,6 @@ protected byte[] engineDeriveData(AlgorithmParameterSpec derivationSpec)
6769
throw new InvalidAlgorithmParameterException("Invalid AlgorithmParameterSpec provided");
6870
}
6971

70-
// TODO: deal with the multi ikm/salt thing
7172
HKDFParameters hkdfParameters = null;
7273
int derivedDataLength = 0;
7374
if (derivationSpec instanceof HKDFParameterSpec.ExtractThenExpand)
@@ -77,7 +78,10 @@ protected byte[] engineDeriveData(AlgorithmParameterSpec derivationSpec)
7778
List<SecretKey> ikms = spec.ikms();
7879
List<SecretKey> salts = spec.salts();
7980

80-
hkdfParameters = new HKDFParameters(ikms.get(0).getEncoded(), salts.get(0).getEncoded(), spec.info());
81+
byte[] salt = flattenSecretKeys(salts);
82+
byte[] ikm = flattenSecretKeys(ikms);
83+
84+
hkdfParameters = new HKDFParameters(ikm, salt, spec.info());
8185
derivedDataLength = spec.length();
8286

8387
hkdf.init(hkdfParameters);
@@ -94,7 +98,10 @@ else if (derivationSpec instanceof HKDFParameterSpec.Extract)
9498
List<SecretKey> ikms = spec.ikms();
9599
List<SecretKey> salts = spec.salts();
96100

97-
return hkdf.extractPRK(salts.get(0).getEncoded(), ikms.get(0).getEncoded());
101+
byte[] salt = flattenSecretKeys(salts);
102+
byte[] ikm = flattenSecretKeys(ikms);
103+
104+
return hkdf.extractPRK(salt, ikm);
98105
}
99106
else if (derivationSpec instanceof org.bouncycastle.jcajce.spec.HKDFParameterSpec)
100107
{
@@ -126,6 +133,33 @@ private static KDFParameters requireNull(KDFParameters kdfParameters,
126133
return null;
127134
}
128135

136+
private byte[] flattenSecretKeys(List<SecretKey> keys)
137+
{
138+
if (keys.size() == 1)
139+
{
140+
return keys.get(0).getEncoded();
141+
}
142+
int len = 0;
143+
int off = 0;
144+
145+
List<byte[]> encoding = new ArrayList<byte[]>();
146+
for (int i = 0; i < keys.size(); i++)
147+
{
148+
encoding.add(keys.get(i).getEncoded());
149+
len += encoding.get(i).length;
150+
}
151+
byte[] res = new byte[len];
152+
for (int i = 0; i < encoding.size(); i++)
153+
{
154+
System.arraycopy(encoding.get(i), 0, res, off, encoding.get(i).length);
155+
off += encoding.get(i).length;
156+
}
157+
158+
encoding.clear();
159+
160+
return res;
161+
}
162+
129163
public static class HKDFwithSHA256 extends HKDFSpi
130164
{
131165
public HKDFwithSHA256(KDFParameters kdfParameters) throws InvalidAlgorithmParameterException

prov/src/test/jdk25/org/bouncycastle/jcajce/provider/kdf/test/HKDFTest.java

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.security.NoSuchProviderException;
1919
import java.security.SecureRandom;
2020
import java.security.Security;
21-
import java.security.spec.KeySpec;
2221

2322
import static org.bouncycastle.util.Arrays.areEqual;
2423

@@ -46,7 +45,7 @@ public void testKDF()
4645
byte[] okm = Hex.decode("2124ffb29fac4e0fbbc7d5d87492bff3");
4746
byte[] genOkm;
4847
HKDFParameterSpec.ExtractThenExpand hkdfParams1 = HKDFParameterSpec.ofExtract().addIKM(ikm)
49-
.addSalt(salt).thenExpand(info, okm.length);
48+
.addSalt(salt).thenExpand(info, okm.length);
5049

5150
genOkm = kdfHkdf.deriveData(hkdfParams1);
5251

@@ -77,12 +76,13 @@ public void testKDF()
7776
//kdf.init(new KDFParameter(new SHA1Digest()));
7877
//kdf.deriveData(hkdfParams);
7978
}
79+
8080
private boolean doComparison(String algorithm, byte[] ikm, byte[] salt, byte[] info)
8181
throws Exception
8282
{
8383
KDF kdf = KDF.getInstance(algorithm, "BC");
8484
HKDFParameterSpec.ExtractThenExpand spec = HKDFParameterSpec.ofExtract().addIKM(ikm)
85-
.addSalt(salt).thenExpand(info, ikm.length);
85+
.addSalt(salt).thenExpand(info, ikm.length);
8686

8787
org.bouncycastle.jcajce.spec.HKDFParameterSpec pre25spec = new org.bouncycastle.jcajce.spec.HKDFParameterSpec(ikm, salt, info, ikm.length);
8888
byte[] kdfSecret = kdf.deriveData(spec);
@@ -97,7 +97,7 @@ public void testSecretKeyFactoryComparison()
9797
throws Exception
9898
{
9999
setUp();
100-
String[] algorithms = new String[] {
100+
String[] algorithms = new String[]{
101101
"HKDF-SHA256",
102102
"HKDF-SHA384",
103103
"HKDF-SHA512",
@@ -106,12 +106,12 @@ public void testSecretKeyFactoryComparison()
106106
byte[] salt = new byte[16];
107107
byte[] info = new byte[16];
108108
SecureRandom random = new SecureRandom();
109-
for (String algorithm: algorithms)
109+
for (String algorithm : algorithms)
110110
{
111111
random.nextBytes(ikm);
112112
random.nextBytes(salt);
113113
random.nextBytes(info);
114-
if(!doComparison(algorithm, ikm, salt, info))
114+
if (!doComparison(algorithm, ikm, salt, info))
115115
{
116116
fail("failed to generate same secret using kdf and secret key factory for: " + algorithm);
117117
}
@@ -183,6 +183,79 @@ public void testExceptionHandling()
183183
// }
184184
}
185185

186+
public void testExtractWithConcatenatedIKMAndSalts()
187+
throws Exception
188+
{
189+
setUp();
190+
KDF kdfHkdf = KDF.getInstance("HKDF-SHA256", "BC");
191+
192+
byte[][] ikms = new byte[][]
193+
{
194+
Hex.decode("000102030405060708090a0b0c0d0e0f"),
195+
Hex.decode("101112131415161718191a1b1c1d1e1f"),
196+
Hex.decode("202122232425262728292a2b2c2d2e2f"),
197+
Hex.decode("303132333435363738393a3b3c3d3e3f"),
198+
Hex.decode("404142434445464748494a4b4c4d4e4f"),
199+
};
200+
201+
byte[][] salts = new byte[][]
202+
{
203+
Hex.decode("606162636465666768696a6b6c6d6e6f"),
204+
Hex.decode("707172737475767778797a7b7c7d7e7f"),
205+
Hex.decode("808182838485868788898a8b8c8d8e8f"),
206+
Hex.decode("909192939495969798999a9b9c9d9e9f"),
207+
Hex.decode("a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"),
208+
};
209+
byte[] info = Hex.decode("b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
210+
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
211+
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
212+
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
213+
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
214+
byte[] okm = Hex.decode(
215+
"b11e398dc80327a1c8e7f78c596a4934" +
216+
"4f012eda2d4efad8a050cc4c19afa97c" +
217+
"59045a99cac7827271cb41c65e590e09" +
218+
"da3275600c2f09b8367793a9aca3db71" +
219+
"cc30c58179ec3e87c14c01d5c1f3434f" +
220+
"1d87");
221+
222+
HKDFParameterSpec.ExtractThenExpand hkdfParams1 = HKDFParameterSpec.ofExtract()
223+
.addIKM(ikms[0]).addIKM(ikms[1]).addIKM(ikms[2]).addIKM(ikms[3]).addIKM(ikms[4])
224+
.addSalt(salts[0]).addSalt(salts[1]).addSalt(salts[2]).addSalt(salts[3]).addSalt(salts[4])
225+
.thenExpand(info, okm.length);
226+
227+
byte[] genOkm = kdfHkdf.deriveData(hkdfParams1);
228+
229+
if (!areEqual(genOkm, okm))
230+
{
231+
fail("HKDF failed for multiple ikms/salts");
232+
}
233+
234+
HKDFParameterSpec.Extract hkdfParams2 = HKDFParameterSpec.ofExtract()
235+
.addIKM(ikms[0]).addIKM(ikms[1]).addIKM(ikms[2]).addIKM(ikms[3]).addIKM(ikms[4])
236+
.addSalt(salts[0]).addSalt(salts[1]).addSalt(salts[2]).addSalt(salts[3]).addSalt(salts[4])
237+
.extractOnly();
238+
239+
okm = Hex.decode("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244");
240+
genOkm = kdfHkdf.deriveData(hkdfParams2);
241+
242+
if (!areEqual(genOkm, okm))
243+
{
244+
fail("HKDF failed for multiple ikms/salts");
245+
}
246+
}
247+
248+
/**
249+
* Helper method to concatenate two byte arrays.
250+
*/
251+
private byte[] concatenate(byte[] first, byte[] second)
252+
{
253+
byte[] result = new byte[first.length + second.length];
254+
System.arraycopy(first, 0, result, 0, first.length);
255+
System.arraycopy(second, 0, result, first.length, second.length);
256+
return result;
257+
}
258+
186259
private static class InvalidKDFParameters
187260
implements KDFParameters
188261
{

tls/src/main/java/org/bouncycastle/jsse/BCSSLParameters.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ private static <T> List<T> copyList(Collection<T> list)
4444
private String[] signatureSchemes = null;
4545
private String[] signatureSchemesCert = null;
4646
private String[] namedGroups = null;
47+
private String[] earlyNamedGroups = null;
4748

4849
public BCSSLParameters()
4950
{
@@ -326,4 +327,34 @@ public void setNamedGroups(String[] namedGroups)
326327

327328
this.namedGroups = check;
328329
}
330+
331+
public String[] getEarlyNamedGroups()
332+
{
333+
return TlsUtils.clone(earlyNamedGroups);
334+
}
335+
336+
public void setEarlyNamedGroups(String[] earlyNamedGroups)
337+
{
338+
String[] check = null;
339+
340+
if (earlyNamedGroups != null)
341+
{
342+
check = TlsUtils.clone(earlyNamedGroups);
343+
HashSet<String> seenEntries = new HashSet<String>();
344+
for (String entry : check)
345+
{
346+
if (TlsUtils.isNullOrEmpty(entry))
347+
{
348+
throw new IllegalArgumentException("'earlyNamedGroups' entries cannot be null or empty strings");
349+
}
350+
351+
if (!seenEntries.add(entry))
352+
{
353+
throw new IllegalArgumentException("'earlyNamedGroups' contains duplicate entry: " + entry);
354+
}
355+
}
356+
}
357+
358+
this.earlyNamedGroups = check;
359+
}
329360
}

0 commit comments

Comments
 (0)