Skip to content

Commit ed53532

Browse files
committed
conflict resolution
2 parents 98a0fbe + 8dce487 commit ed53532

File tree

18 files changed

+2034
-61
lines changed

18 files changed

+2034
-61
lines changed

pkix/src/main/java/org/bouncycastle/operator/DefaultSignatureAlgorithmIdentifierFinder.java

+16-8
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@
2626
import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
2727
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
2828
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
29+
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.CompositeSignaturesConstants;
2930
import org.bouncycastle.util.Strings;
3031

3132
public class DefaultSignatureAlgorithmIdentifierFinder
32-
implements SignatureAlgorithmIdentifierFinder
33+
implements SignatureAlgorithmIdentifierFinder
3334
{
3435
private static Map algorithms = new HashMap();
3536
private static Set noParams = new HashSet();
@@ -234,6 +235,13 @@ public class DefaultSignatureAlgorithmIdentifierFinder
234235
algorithms.put("SHA3-512WITHPICNIC", BCObjectIdentifiers.picnic_with_sha3_512);
235236
algorithms.put("SHAKE256WITHPICNIC", BCObjectIdentifiers.picnic_with_shake256);
236237

238+
//Load composite signatures
239+
for (ASN1ObjectIdentifier oid : CompositeSignaturesConstants.supportedIdentifiers)
240+
{
241+
algorithms.put(CompositeSignaturesConstants.ASN1IdentifierAlgorithmNameMap.get(oid).toUpperCase(), oid);
242+
algorithms.put(oid.toString(), oid);
243+
}
244+
237245
//
238246
// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
239247
// The parameters field SHALL be NULL for RSA based signature algorithms.
@@ -519,7 +527,7 @@ public class DefaultSignatureAlgorithmIdentifierFinder
519527
digestOids.put(BCObjectIdentifiers.sphincsPlus_sha2_256f, NISTObjectIdentifiers.id_sha256);
520528
digestOids.put(BCObjectIdentifiers.sphincsPlus_shake_256s, NISTObjectIdentifiers.id_shake256);
521529
digestOids.put(BCObjectIdentifiers.sphincsPlus_shake_256f, NISTObjectIdentifiers.id_shake256);
522-
530+
523531
// digestOids.put(GMObjectIdentifiers.sm2sign_with_rmd160, TeleTrusTObjectIdentifiers.ripemd160);
524532
// digestOids.put(GMObjectIdentifiers.sm2sign_with_sha1, OIWObjectIdentifiers.idSHA1);
525533
// digestOids.put(GMObjectIdentifiers.sm2sign_with_sha224, NISTObjectIdentifiers.id_sha224);
@@ -537,16 +545,16 @@ public class DefaultSignatureAlgorithmIdentifierFinder
537545
private static RSASSAPSSparams createPSSParams(AlgorithmIdentifier hashAlgId, int saltSize)
538546
{
539547
return new RSASSAPSSparams(
540-
hashAlgId,
541-
new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId),
542-
new ASN1Integer(saltSize),
543-
new ASN1Integer(1));
548+
hashAlgId,
549+
new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, hashAlgId),
550+
new ASN1Integer(saltSize),
551+
new ASN1Integer(1));
544552
}
545553

546554
public AlgorithmIdentifier find(String sigAlgName)
547555
{
548556
String algorithmName = Strings.toUpperCase(sigAlgName);
549-
ASN1ObjectIdentifier sigOID = (ASN1ObjectIdentifier)algorithms.get(algorithmName);
557+
ASN1ObjectIdentifier sigOID = (ASN1ObjectIdentifier) algorithms.get(algorithmName);
550558
if (sigOID == null)
551559
{
552560
throw new IllegalArgumentException("Unknown signature type requested: " + sigAlgName);
@@ -559,7 +567,7 @@ public AlgorithmIdentifier find(String sigAlgName)
559567
}
560568
else if (params.containsKey(algorithmName))
561569
{
562-
sigAlgId = new AlgorithmIdentifier(sigOID, (ASN1Encodable)params.get(algorithmName));
570+
sigAlgId = new AlgorithmIdentifier(sigOID, (ASN1Encodable) params.get(algorithmName));
563571
}
564572
else
565573
{

pkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentSignerBuilder.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ public JcaContentSignerBuilder setSecureRandom(SecureRandom random)
118118
public ContentSigner build(PrivateKey privateKey)
119119
throws OperatorCreationException
120120
{
121-
if (privateKey instanceof CompositePrivateKey)
121+
//Use this legacy method only for composite private keys (they have that identifier)
122+
if (privateKey instanceof CompositePrivateKey && ((CompositePrivateKey)privateKey).getAlgorithmIdentifier().equals(MiscObjectIdentifiers.id_composite_key))
122123
{
123124
return buildComposite((CompositePrivateKey)privateKey);
124125
}

pkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ public ContentVerifier get(AlgorithmIdentifier algorithm)
143143
return createCompositeVerifier(algorithm, publicKey);
144144
}
145145

146-
if (publicKey instanceof CompositePublicKey)
146+
//Use this legacy method only for composite public keys (they have that identifier)
147+
if (publicKey instanceof CompositePublicKey && ((CompositePublicKey)publicKey).getAlgorithmIdentifier().equals(MiscObjectIdentifiers.id_composite_key))
147148
{
148149
List<PublicKey> keys = ((CompositePublicKey)publicKey).getPublicKeys();
149150

pkix/src/test/java/org/bouncycastle/cert/test/CertTest.java

+140-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.ByteArrayInputStream;
44
import java.io.ByteArrayOutputStream;
5+
import java.io.InputStreamReader;
56
import java.io.IOException;
67
import java.io.ObjectInputStream;
78
import java.io.ObjectOutputStream;
@@ -60,6 +61,7 @@
6061
import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
6162
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
6263
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
64+
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
6365
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
6466
import org.bouncycastle.asn1.x500.X500Name;
6567
import org.bouncycastle.asn1.x500.X500NameBuilder;
@@ -102,6 +104,7 @@
102104
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
103105
import org.bouncycastle.jcajce.CompositePrivateKey;
104106
import org.bouncycastle.jcajce.CompositePublicKey;
107+
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.CompositeSignaturesConstants;
105108
import org.bouncycastle.jcajce.spec.CompositeAlgorithmSpec;
106109
import org.bouncycastle.jce.X509KeyUsage;
107110
import org.bouncycastle.jce.interfaces.ECPointEncoder;
@@ -112,10 +115,12 @@
112115
import org.bouncycastle.jce.spec.ECPublicKeySpec;
113116
import org.bouncycastle.jce.spec.GOST3410ParameterSpec;
114117
import org.bouncycastle.math.ec.ECCurve;
118+
import org.bouncycastle.openssl.PEMParser;
115119
import org.bouncycastle.operator.ContentSigner;
116120
import org.bouncycastle.operator.ContentVerifierProvider;
117121
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
118122
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
123+
import org.bouncycastle.operator.OperatorCreationException;
119124
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
120125
import org.bouncycastle.operator.bc.BcRSAContentVerifierProviderBuilder;
121126
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
@@ -137,6 +142,7 @@
137142
import org.bouncycastle.util.encoders.Base64;
138143
import org.bouncycastle.util.encoders.Hex;
139144
import org.bouncycastle.util.test.SimpleTest;
145+
import org.bouncycastle.util.test.TestFailedException;
140146

141147
public class CertTest
142148
extends SimpleTest
@@ -2953,7 +2959,7 @@ public void checkCRLCompositeCreation()
29532959
// null comp test
29542960
try
29552961
{
2956-
crl.verify(new CompositePublicKey(null, null));
2962+
crl.verify(new CompositePublicKey(new PublicKey[]{null, null}));
29572963
}
29582964
catch (InvalidKeyException e)
29592965
{
@@ -4567,7 +4573,7 @@ public void checkCreationComposite()
45674573
{
45684574
vProv = new JcaContentVerifierProviderBuilder()
45694575
.setProvider(BC)
4570-
.build(new CompositePublicKey(null, null));
4576+
.build(new CompositePublicKey(new PublicKey[]{null, null}));
45714577

45724578
certHldr.isSignatureValid(vProv);
45734579
}
@@ -4596,7 +4602,7 @@ public void checkCreationComposite()
45964602
// null comp test
45974603
try
45984604
{
4599-
cert.verify(new CompositePublicKey(null, null));
4605+
cert.verify(new CompositePublicKey(new PublicKey[]{null, null}));
46004606
}
46014607
catch (InvalidKeyException e)
46024608
{
@@ -5417,6 +5423,132 @@ private void checkSerialisation()
54175423
doSerialize(attrHolder);
54185424
}
54195425

5426+
// TESTS REGARDING COMPOSITES https://www.ietf.org/archive/id/draft-ounsworth-pq-composite-sigs-13.html
5427+
private static String[] compositeSignaturesOIDs = {
5428+
"2.16.840.1.114027.80.8.1.1", //id-MLDSA44-RSA2048-PSS-SHA256
5429+
"2.16.840.1.114027.80.8.1.2", //id-MLDSA44-RSA2048-PKCS15-SHA256
5430+
"2.16.840.1.114027.80.8.1.3", //id-MLDSA44-Ed25519-SHA512
5431+
"2.16.840.1.114027.80.8.1.4", //id-MLDSA44-ECDSA-P256-SHA256
5432+
"2.16.840.1.114027.80.8.1.5", //id-MLDSA44-ECDSA-brainpoolP256r1-SHA256
5433+
"2.16.840.1.114027.80.8.1.6", //id-MLDSA65-RSA3072-PSS-SHA512
5434+
"2.16.840.1.114027.80.8.1.7", //id-MLDSA65-RSA3072-PKCS15-SHA512
5435+
"2.16.840.1.114027.80.8.1.8", //id-MLDSA65-ECDSA-P256-SHA512
5436+
"2.16.840.1.114027.80.8.1.9", //id-MLDSA65-ECDSA-brainpoolP256r1-SHA512
5437+
"2.16.840.1.114027.80.8.1.10", //id-MLDSA65-Ed25519-SHA512
5438+
"2.16.840.1.114027.80.8.1.11", //id-MLDSA87-ECDSA-P384-SHA512
5439+
"2.16.840.1.114027.80.8.1.12", //id-MLDSA87-ECDSA-brainpoolP384r1-SHA512
5440+
"2.16.840.1.114027.80.8.1.13", //id-MLDSA87-Ed448-SHA512
5441+
// Falcon composites below were excluded from the draft. See MiscObjectIdentifiers for details.
5442+
"2.16.840.1.114027.80.8.1.14", //id-Falcon512-ECDSA-P256-SHA256
5443+
"2.16.840.1.114027.80.8.1.15", //id-Falcon512-ECDSA-brainpoolP256r1-SHA256
5444+
"2.16.840.1.114027.80.8.1.16", //id-Falcon512-Ed25519-SHA512
5445+
};
5446+
5447+
private void checkCompositeSignatureCertificateCreation()
5448+
{
5449+
try
5450+
{
5451+
for (String oid : compositeSignaturesOIDs)
5452+
{
5453+
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(oid, "BC");
5454+
KeyPair keyPair = keyPairGenerator.generateKeyPair();
5455+
5456+
String subjectName = "CN=ROOT CA";
5457+
X500Name issuer = new X500Name(subjectName);
5458+
BigInteger serial = BigInteger.valueOf(5);
5459+
Date notBefore = new Date();
5460+
Date notAfter = new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 365L);
5461+
X500Name subject = new X500Name(subjectName);
5462+
5463+
JcaX509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(issuer, serial, notBefore, notAfter, subject, keyPair.getPublic());
5464+
X509CertificateHolder certHolder = certificateBuilder.build(new JcaContentSignerBuilder(oid).build(keyPair.getPrivate()));
5465+
X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certHolder);
5466+
5467+
isEquals(oid, cert.getSigAlgOID());
5468+
CompositePublicKey compositePublicKey = (CompositePublicKey) cert.getPublicKey();
5469+
isEquals(CompositeSignaturesConstants.ASN1IdentifierAlgorithmNameMap.get(new ASN1ObjectIdentifier(oid)), compositePublicKey.getAlgorithm());
5470+
5471+
isEquals(subjectName, cert.getSubjectX500Principal().getName());
5472+
5473+
cert.verify(cert.getPublicKey());
5474+
5475+
}
5476+
}
5477+
catch (NoSuchAlgorithmException | NoSuchProviderException | CertificateException | OperatorCreationException |
5478+
SignatureException | InvalidKeyException | TestFailedException e)
5479+
{
5480+
fail("checkCompositeSignatureCertificateCreation failed: " + e.getMessage());
5481+
}
5482+
}
5483+
5484+
private void checkParseCompositePublicKey()
5485+
{
5486+
try
5487+
{
5488+
//compositePublicKeyExampleRFC.pem contains the sample public key from https://www.ietf.org/archive/id/draft-ounsworth-pq-composite-sigs-13.html
5489+
PEMParser pemParser = new PEMParser(new InputStreamReader(this.getClass().getResourceAsStream("compositePublicKeyExampleRFC.pem")));
5490+
SubjectPublicKeyInfo subjectPublicKeyInfo = (SubjectPublicKeyInfo) pemParser.readObject();
5491+
isEquals(subjectPublicKeyInfo.getAlgorithm().getAlgorithm(), MiscObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256);
5492+
5493+
CompositePublicKey compositePublicKey = new CompositePublicKey(subjectPublicKeyInfo);
5494+
5495+
isEquals(compositePublicKey.getPublicKeys().get(0).getAlgorithm(), "DILITHIUM2");
5496+
isEquals(compositePublicKey.getPublicKeys().get(1).getAlgorithm(), "ECDSA");
5497+
}
5498+
catch (Exception e)
5499+
{
5500+
fail("checkParseCompositePublicKey failed: " + e.getMessage());
5501+
}
5502+
}
5503+
5504+
private void checkParseCompositePrivateKey()
5505+
{
5506+
try
5507+
{
5508+
//compositePrivateKeyExample.pem does NOT contain the sample private key from https://www.ietf.org/archive/id/draft-ounsworth-pq-composite-sigs-13.html
5509+
//because the at this moment, the Dilithium private key formats don't match.
5510+
//this sample was generated from this BC implementation
5511+
PEMParser pemParser = new PEMParser(new InputStreamReader(this.getClass().getResourceAsStream("compositePrivateKeyExample.pem")));
5512+
PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) pemParser.readObject();
5513+
5514+
isEquals(privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm(), MiscObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256);
5515+
5516+
CompositePrivateKey compositePrivateKey = new CompositePrivateKey(privateKeyInfo);
5517+
5518+
isEquals(compositePrivateKey.getPrivateKeys().get(0).getAlgorithm(), "DILITHIUM2");
5519+
isEquals(compositePrivateKey.getPrivateKeys().get(1).getAlgorithm(), "ECDSA");
5520+
}
5521+
catch (Exception e)
5522+
{
5523+
fail("checkParseCompositePrivateKey failed: " + e.getMessage());
5524+
}
5525+
}
5526+
5527+
private void checkParseAndVerifyCompositeCertificate()
5528+
{
5529+
try
5530+
{
5531+
//compositeCertificateExampleRFC.pem contains the sample certificate from https://www.ietf.org/archive/id/draft-ounsworth-pq-composite-sigs-13.html
5532+
PEMParser pemParser = new PEMParser(new InputStreamReader(this.getClass().getResourceAsStream("compositeCertificateExampleRFC.pem")));
5533+
X509CertificateHolder certificateHolder = (X509CertificateHolder) pemParser.readObject();
5534+
JcaX509CertificateConverter x509Converter = new JcaX509CertificateConverter().setProvider("BC");
5535+
X509Certificate certificate = x509Converter.getCertificate(certificateHolder);
5536+
5537+
isEquals(certificate.getSigAlgOID(), MiscObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256.toString());
5538+
5539+
CompositePublicKey compositePublicKey = (CompositePublicKey) certificate.getPublicKey();
5540+
5541+
isEquals(compositePublicKey.getPublicKeys().get(0).getAlgorithm(), "DILITHIUM2");
5542+
isEquals(compositePublicKey.getPublicKeys().get(1).getAlgorithm(), "ECDSA");
5543+
5544+
certificate.verify(compositePublicKey);
5545+
}
5546+
catch (Exception e)
5547+
{
5548+
fail("checkParseAndVerifyCompositeCertificate failed: " + e.getMessage());
5549+
}
5550+
}
5551+
54205552
private void doSerialize(Serializable encodable)
54215553
throws Exception
54225554
{
@@ -5565,6 +5697,11 @@ public void performTest()
55655697
zeroDataTest();
55665698

55675699
checkSerialisation();
5700+
5701+
checkCompositeSignatureCertificateCreation();
5702+
checkParseCompositePublicKey();
5703+
checkParseCompositePrivateKey();
5704+
checkParseAndVerifyCompositeCertificate();
55685705
}
55695706

55705707
private Extensions generateExtensions(Vector oids, Vector values)

0 commit comments

Comments
 (0)