Skip to content

Commit a6b5895

Browse files
committed
Added builder carrying provider names to CompositePrivateKey.
1 parent dcfeab8 commit a6b5895

File tree

3 files changed

+115
-18
lines changed

3 files changed

+115
-18
lines changed

prov/src/main/java/org/bouncycastle/jcajce/CompositePrivateKey.java

Lines changed: 92 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.io.IOException;
44
import java.security.PrivateKey;
5+
import java.security.Provider;
6+
import java.security.Security;
57
import java.util.ArrayList;
68
import java.util.Collections;
79
import java.util.List;
@@ -29,7 +31,50 @@
2931
public class CompositePrivateKey
3032
implements PrivateKey
3133
{
34+
public static class Builder
35+
{
36+
private final AlgorithmIdentifier algorithmIdentifier;
37+
private final PrivateKey[] keys = new PrivateKey[2];
38+
private final Provider[] providers = new Provider[2];
39+
40+
private int count = 0;
41+
42+
private Builder(AlgorithmIdentifier algorithmIdentifier)
43+
{
44+
this.algorithmIdentifier = algorithmIdentifier;
45+
}
46+
47+
public Builder addPrivateKey(PrivateKey key, String providerName)
48+
{
49+
return addPrivateKey(key, Security.getProvider(providerName));
50+
}
51+
52+
public Builder addPrivateKey(PrivateKey key, Provider provider)
53+
{
54+
if (count == keys.length)
55+
{
56+
throw new IllegalStateException("only " + keys.length + " allowed in composite");
57+
}
58+
59+
keys[count] = key;
60+
providers[count++] = provider;
61+
62+
return this;
63+
}
64+
65+
public CompositePrivateKey build()
66+
{
67+
return new CompositePrivateKey(algorithmIdentifier, keys, providers);
68+
}
69+
}
70+
71+
public static Builder builder(ASN1ObjectIdentifier compAlgOid)
72+
{
73+
return new Builder(new AlgorithmIdentifier(compAlgOid));
74+
}
75+
3276
private final List<PrivateKey> keys;
77+
private final List<Provider> providers;
3378

3479
private AlgorithmIdentifier algorithmIdentifier;
3580

@@ -69,17 +114,44 @@ public CompositePrivateKey(AlgorithmIdentifier algorithmIdentifier, PrivateKey..
69114
List<PrivateKey> keyList = new ArrayList<PrivateKey>(keys.length);
70115
for (int i = 0; i < keys.length; i++)
71116
{
72-
if (keys[i] instanceof MLDSAPrivateKey)
73-
{
74-
// TODO: we don't insist on seed but we try to accommodate it - the debate continues
75-
keyList.add(((MLDSAPrivateKey)keys[i]).getPrivateKey(true));
76-
}
77-
else
78-
{
79-
keyList.add(keys[i]);
80-
}
117+
keyList.add(processKey(keys[i]));
81118
}
82119
this.keys = Collections.unmodifiableList(keyList);
120+
this.providers = null;
121+
}
122+
123+
private PrivateKey processKey(PrivateKey key)
124+
{
125+
// we assume this also means BCKey
126+
if (key instanceof MLDSAPrivateKey)
127+
{
128+
// TODO: we don't insist on seed but we try to accommodate it - the debate continues
129+
return ((MLDSAPrivateKey)key).getPrivateKey(true);
130+
}
131+
else
132+
{
133+
return key;
134+
}
135+
}
136+
137+
private CompositePrivateKey(AlgorithmIdentifier algorithmIdentifier, PrivateKey[] keys, Provider[] providers)
138+
{
139+
this.algorithmIdentifier = algorithmIdentifier;
140+
141+
if (keys.length != 2)
142+
{
143+
throw new IllegalArgumentException("two keys required for composite private key");
144+
}
145+
146+
List<PrivateKey> keyList = new ArrayList<PrivateKey>(keys.length);
147+
List<Provider> providerList = new ArrayList<Provider>(providers.length);
148+
for (int i = 0; i < keys.length; i++)
149+
{
150+
providerList.add(providers[i]);
151+
keyList.add(processKey(keys[i]));
152+
}
153+
this.keys = Collections.unmodifiableList(keyList);
154+
this.providers = Collections.unmodifiableList(providerList);
83155
}
84156

85157
/**
@@ -111,6 +183,7 @@ public CompositePrivateKey(PrivateKeyInfo keyInfo)
111183
}
112184

113185
this.keys = privateKeyFromFactory.getPrivateKeys();
186+
this.providers = null;
114187
this.algorithmIdentifier = privateKeyFromFactory.getAlgorithmIdentifier();
115188
}
116189

@@ -124,6 +197,16 @@ public List<PrivateKey> getPrivateKeys()
124197
return keys;
125198
}
126199

200+
/**
201+
* Return a list of the providers supporting the component private keys.
202+
*
203+
* @return an immutable list of Provider objects.
204+
*/
205+
public List<Provider> getProviders()
206+
{
207+
return providers;
208+
}
209+
127210
public String getAlgorithm()
128211
{
129212
return CompositeIndex.getAlgorithmName(this.algorithmIdentifier.getAlgorithm());

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/compositesignatures/SignatureSpi.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.security.InvalidParameterException;
99
import java.security.Key;
1010
import java.security.PrivateKey;
11+
import java.security.Provider;
1112
import java.security.PublicKey;
1213
import java.security.SecureRandom;
1314
import java.security.Signature;
@@ -133,7 +134,7 @@ protected void engineInitVerify(PublicKey publicKey)
133134
{
134135
throw new InvalidKeyException("Provided composite public key cannot be used with the composite signature algorithm.");
135136
}
136-
createComponentSignatures(compositePublicKey.getPublicKeys());
137+
createComponentSignatures(compositePublicKey.getPublicKeys(), null);
137138

138139
sigInitVerify();
139140
}
@@ -164,24 +165,34 @@ protected void engineInitSign(PrivateKey privateKey)
164165
{
165166
throw new InvalidKeyException("Provided composite private key cannot be used with the composite signature algorithm.");
166167
}
167-
createComponentSignatures(compositePrivateKey.getPrivateKeys());
168+
createComponentSignatures(compositePrivateKey.getPrivateKeys(), compositePrivateKey.getProviders());
168169

169170
sigInitSign();
170171
}
171172

172-
private void createComponentSignatures(List keys)
173+
private void createComponentSignatures(List keys, List<Provider> providers)
173174
{
174175
try
175176
{
176-
for (int i = 0; i != componentSignatures.length; i++)
177+
if (providers == null)
177178
{
178-
if (keys.get(i) instanceof BCKey)
179+
for (int i = 0; i != componentSignatures.length; i++)
179180
{
180-
componentSignatures[i] = Signature.getInstance(algs[i], "BC");
181+
if (keys.get(i) instanceof BCKey)
182+
{
183+
componentSignatures[i] = Signature.getInstance(algs[i], "BC");
184+
}
185+
else
186+
{
187+
componentSignatures[i] = Signature.getInstance(algs[i]);
188+
}
181189
}
182-
else
190+
}
191+
else
192+
{
193+
for (int i = 0; i != componentSignatures.length; i++)
183194
{
184-
componentSignatures[i] = Signature.getInstance(algs[i]);
195+
componentSignatures[i] = Signature.getInstance(algs[i], providers.get(i));
185196
}
186197
}
187198
}

prov/src/test/java/org/bouncycastle/jcajce/provider/test/CompositeSignaturesTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,10 @@ public void testMixedComposition()
333333
KeyPair ecKp = ecKpGen.generateKeyPair();
334334

335335
CompositePublicKey compPublicKey = new CompositePublicKey(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256, mldsaKp.getPublic(), ecKp.getPublic());
336-
CompositePrivateKey compPrivateKey = new CompositePrivateKey(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256, mldsaKp.getPrivate(), ecKp.getPrivate());
336+
CompositePrivateKey compPrivateKey = CompositePrivateKey.builder(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256)
337+
.addPrivateKey(mldsaKp.getPrivate(), "BC")
338+
.addPrivateKey(ecKp.getPrivate(), "SunEC")
339+
.build();
337340

338341
Signature signature = Signature.getInstance(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256.getId(), "BC");
339342
signature.initSign(compPrivateKey);

0 commit comments

Comments
 (0)