Skip to content

Commit 67a2f3a

Browse files
author
gefeili
committed
Merge branch 'main' into pg-synchronize-bc_csharp
# Conflicts: # pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java # pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcImplProvider.java # pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPContentSignerBuilder.java # pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPContentVerifierBuilderProvider.java
2 parents d50e8bd + 0520ebc commit 67a2f3a

File tree

16 files changed

+429
-87
lines changed

16 files changed

+429
-87
lines changed

CONTRIBUTORS.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@
547547
<li>Seung Yeon &lt;https://github.com/seungyeonpark&gt; - addition of Memoable method implementations to CertPathValidationContext and CertificatePoliciesValidation.</li>
548548
<li>yuhh0328 &lt;https://github.com/yuhh0328&gt; - initial patch for adding ML-KEM support to TLS.</li>
549549
<li>Jan Oupick&yacute; &lt;https://github.com/Honzaik&gt; - update to draft 13 of composite PQC signatures.</li>
550+
<li>Karsten Otto &lt;https://github.com/ottoka&gt; - finished the support for jdk.tls.server.defaultDHEParameters.</li>
550551
</ul>
551552
</body>
552553
</html>

core/src/main/java/org/bouncycastle/pqc/crypto/crystals/dilithium/DilithiumEngine.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -536,14 +536,7 @@ public boolean signVerify(byte[] sig, int siglen, byte[] msg, int msglen, byte[]
536536
// Helper.printByteArray(c2);
537537

538538

539-
for (int i = 0; i < DilithiumCTilde; ++i)
540-
{
541-
if (c[i] != c2[i])
542-
{
543-
return false;
544-
}
545-
}
546-
return true;
539+
return Arrays.constantTimeAreEqual(c, c2);
547540
}
548541

549542
public boolean signOpen(byte[] msg, byte[] signedMsg, int signedMsglen, byte[] rho, byte[] t1)

core/src/main/java/org/bouncycastle/pqc/crypto/lms/HSSPublicKeyParameters.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public LMSContext generateLMSContext(byte[] sigEnc)
136136

137137
public boolean verify(LMSContext context)
138138
{
139-
boolean failed = false;
139+
boolean passed = true;
140140

141141
LMSSignedPubKey[] sigKeys = context.getSignedPubKeys();
142142

@@ -151,13 +151,10 @@ public boolean verify(LMSContext context)
151151
{
152152
LMSSignature sig = sigKeys[i].getSignature();
153153
byte[] msg = sigKeys[i].getPublicKey().toByteArray();
154-
if (!LMS.verifySignature(key, sig, msg))
155-
{
156-
failed = true;
157-
}
154+
passed &= LMS.verifySignature(key, sig, msg);
158155
key = sigKeys[i].getPublicKey();
159156
}
160157

161-
return !failed & key.verify(context);
158+
return passed & key.verify(context);
162159
}
163160
}

core/src/main/java/org/bouncycastle/pqc/crypto/sphincs/SPHINCS256Signer.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,13 +406,12 @@ boolean verify(HashFunctions hs, byte[] m, byte[] sm, byte[] pk)
406406
smlen -= SPHINCS256Config.SUBTREE_HEIGHT * SPHINCS256Config.HASH_BYTES;
407407
}
408408

409+
// Because we use custom offsets on tpk, rather than incurring an
410+
// expensive copy, we use a manual constant time comparison.
409411
boolean verified = true;
410412
for (i = 0; i < SPHINCS256Config.HASH_BYTES; i++)
411413
{
412-
if (root[i] != tpk[i + Horst.N_MASKS * SPHINCS256Config.HASH_BYTES])
413-
{
414-
verified = false;
415-
}
414+
verified &= root[i] == tpk[i + Horst.N_MASKS * SPHINCS256Config.HASH_BYTES];
416415
}
417416

418417
return verified;

docs/releasenotes.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ <h2>1.0 Introduction</h2>
1919
<h2>2.0 Release History</h2>
2020

2121
<a id="r1rv79"><h3>2.1.1 Version</h3></a>
22+
Release: 1.79<br/>
2223
Date:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2024, TBD.
2324
<h3>2.1.2 Defects Fixed</h3>
2425
<ul>
2526
</ul>
27+
<h3>2.1.3 Additional Features and Functionality</h3>
28+
<ul>
29+
<li>BCJSSE: Added support for security property "jdk.tls.server.defaultDHEParameters" (disabled in FIPS mode).</li>
30+
</ul>
2631

2732
<a id="r1rv78d1"><h3>2.2.1 Version</h3></a>
33+
Release: 1.78.1<br/>
2834
Date:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2024, 18th April.
2935
<h3>2.2.2 Defects Fixed</h3>
3036
<ul>

pg/src/main/java/org/bouncycastle/openpgp/PGPSignature.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.bouncycastle.bcpg.SignatureSubpacket;
2020
import org.bouncycastle.bcpg.TrustPacket;
2121
import org.bouncycastle.math.ec.rfc8032.Ed25519;
22+
import org.bouncycastle.math.ec.rfc8032.Ed448;
2223
import org.bouncycastle.openpgp.operator.PGPContentVerifier;
2324
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilder;
2425
import org.bouncycastle.openpgp.operator.PGPContentVerifierBuilderProvider;
@@ -454,8 +455,19 @@ else if (getKeyAlgorithm() == PublicKeyAlgorithmTags.EDDSA_LEGACY)
454455
{
455456
byte[] a = BigIntegers.asUnsignedByteArray(sigValues[0].getValue());
456457
byte[] b = BigIntegers.asUnsignedByteArray(sigValues[1].getValue());
457-
//TODO: distinguish Ed25519 and Ed448
458-
signature = Arrays.concatenate(a, b);
458+
if (a.length + b.length == Ed25519.SIGNATURE_SIZE)
459+
{
460+
signature = new byte[Ed25519.SIGNATURE_SIZE];
461+
System.arraycopy(a, 0, signature, Ed25519.PUBLIC_KEY_SIZE - a.length, a.length);
462+
System.arraycopy(b, 0, signature, Ed25519.SIGNATURE_SIZE - b.length, b.length);
463+
}
464+
else
465+
{
466+
signature = new byte[Ed448.SIGNATURE_SIZE];
467+
System.arraycopy(a, 0, signature, Ed448.PUBLIC_KEY_SIZE - a.length, a.length);
468+
System.arraycopy(b, 0, signature, Ed448.SIGNATURE_SIZE - b.length, b.length);
469+
}
470+
459471
}
460472
else
461473
{

pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPContentSignerBuilder.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ public PGPContentSigner build(final int signatureType, final long keyID, final P
9898

9999
if (keyAlgorithm == PublicKeyAlgorithmTags.EDDSA_LEGACY && privateKey.getAlgorithm().equals("Ed448"))
100100
{
101-
// Try my best to solve Ed448Legacy issue
102101
signature = helper.createSignature("Ed448");
103102
}
104103
else

pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPContentVerifierBuilderProvider.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import java.security.SignatureException;
99
import java.security.interfaces.RSAPublicKey;
1010

11-
import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
12-
import org.bouncycastle.bcpg.EdDSAPublicBCPGKey;
1311
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
1412
import org.bouncycastle.jcajce.io.OutputStreamFactory;
1513
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
@@ -73,22 +71,19 @@ public JcaPGPContentVerifierBuilder(int keyAlgorithm, int hashAlgorithm)
7371
public PGPContentVerifier build(final PGPPublicKey publicKey)
7472
throws PGPException
7573
{
76-
final Signature signature;
74+
final PGPDigestCalculator digestCalculator = digestCalculatorProviderBuilder.build().get(hashAlgorithm);
75+
final PublicKey jcaKey = keyConverter.getPublicKey(publicKey);
7776

78-
if (keyAlgorithm == PublicKeyAlgorithmTags.EDDSA_LEGACY
79-
&& ((EdDSAPublicBCPGKey)publicKey.getPublicKeyPacket().getKey()).getCurveOID().equals(EdECObjectIdentifiers.id_Ed448))
77+
final Signature signature;
78+
if (keyAlgorithm == PublicKeyAlgorithmTags.EDDSA_LEGACY && jcaKey.getAlgorithm().equals("Ed448"))
8079
{
81-
// Try my best to solve Ed448Legacy issue
82-
signature = helper.createSignature("Ed448");
80+
signature = helper.createSignature(PublicKeyAlgorithmTags.Ed448, hashAlgorithm);
8381
}
8482
else
8583
{
8684
signature = helper.createSignature(keyAlgorithm, hashAlgorithm);
8785
}
8886

89-
final PGPDigestCalculator digestCalculator = digestCalculatorProviderBuilder.build().get(hashAlgorithm);
90-
final PublicKey jcaKey = keyConverter.getPublicKey(publicKey);
91-
9287
try
9388
{
9489
signature.initVerify(jcaKey);

pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JcaPGPKeyConverter.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -366,22 +366,13 @@ else if (ecdhK.getCurveOID().equals(EdECObjectIdentifiers.id_X448))
366366
// Modern Ed25519 (1.3.6.1.4.1.11591.15.1 & 1.3.101.112)
367367
case PublicKeyAlgorithmTags.Ed25519:
368368
{
369-
BCPGKey key = publicPk.getKey();
370-
if (key instanceof Ed25519PublicBCPGKey)
371-
{
372-
return implGetPublicKeyX509(BigIntegers.asUnsignedByteArray(new BigInteger(1, publicPk.getKey().getEncoded())),
373-
0, EdECObjectIdentifiers.id_Ed25519, "EdDSA");
374-
}
375-
else
376-
{
377-
return implGetPublicKeyX509(BigIntegers.asUnsignedByteArray(((EdDSAPublicBCPGKey)publicPk.getKey()).getEncodedPoint()),
369+
return implGetPublicKeyX509(publicPk.getKey().getEncoded(),
378370
0, EdECObjectIdentifiers.id_Ed25519, "EdDSA");
379-
}
380371
}
381372
// Modern Ed448 (1.3.101.113)
382373
case PublicKeyAlgorithmTags.Ed448:
383374
{
384-
return implGetPublicKeyX509(BigIntegers.asUnsignedByteArray(new BigInteger(1, publicPk.getKey().getEncoded())),
375+
return implGetPublicKeyX509(publicPk.getKey().getEncoded(),
385376
0, EdECObjectIdentifiers.id_Ed448, "EdDSA");
386377
}
387378
case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT:
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package org.bouncycastle.openpgp.test;
2+
3+
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
4+
import org.bouncycastle.bcpg.test.AbstractPacketTest;
5+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
6+
import org.bouncycastle.openpgp.PGPException;
7+
import org.bouncycastle.openpgp.PGPKeyPair;
8+
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter;
9+
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
10+
import org.bouncycastle.util.encoders.Hex;
11+
12+
import java.security.*;
13+
import java.security.spec.*;
14+
import java.util.Date;
15+
16+
public class EdDSAKeyConversionWithLeadingZeroTest
17+
extends AbstractPacketTest
18+
{
19+
@Override
20+
public String getName()
21+
{
22+
return "EdDSALeadingZero";
23+
}
24+
25+
private static final String ED448_KEY_WITH_LEADING_ZERO = "308183020101300506032b6571043b0439fe2c82fd07b0e8b5da002ee4964e55a357bfdd2192fe43a40b150e6c5a8f8202f140dd34ede17dc10fef9a98bf8188425c14bd1a76a308cfb7813a0000728cbb07c590e2cb282834cc22d7a1f775f729986c4754e7035695dee34057403e98e94cf5012007c3236f4894af039e668acb746fcf8a00";
26+
private static final String ED448_PUB_WITH_LEADING_ZERO = "3043300506032b6571033a0000728cbb07c590e2cb282834cc22d7a1f775f729986c4754e7035695dee34057403e98e94cf5012007c3236f4894af039e668acb746fcf8a00";
27+
28+
private static final String ED25519_KEY_WITH_LEADING_ZERO = "3051020101300506032b65700422042077ee5931a6d454f85acd9cc28bb2fa8c340e10f7cbf0193f1f898a5c22e77f4281210000dcd38e8ec0978690a4bbc8ac7787d311e741c394ba839ad9cc15e9ba21deb1";
29+
private static final String ED25519_PUB_WITH_LEADING_ZERO = "302a300506032b657003210000dcd38e8ec0978690a4bbc8ac7787d311e741c394ba839ad9cc15e9ba21deb1";
30+
31+
@Override
32+
public void performTest()
33+
throws Exception
34+
{
35+
testWithEd448KeyWithLeadingZero();
36+
testWithEd25519KeyWithLeadingZero();
37+
}
38+
39+
private void testWithEd448KeyWithLeadingZero()
40+
throws NoSuchAlgorithmException, InvalidKeySpecException, PGPException, InvalidKeyException, SignatureException
41+
{
42+
JcaPGPKeyConverter jcaPGPKeyConverter = new JcaPGPKeyConverter().setProvider(new BouncyCastleProvider());
43+
44+
KeyFactory factory = KeyFactory.getInstance("EdDSA", new BouncyCastleProvider());
45+
46+
PublicKey pubKey = factory.generatePublic(new X509EncodedKeySpec(Hex.decode(ED448_PUB_WITH_LEADING_ZERO)));
47+
PrivateKey privKey = factory.generatePrivate(new PKCS8EncodedKeySpec(Hex.decode(ED448_KEY_WITH_LEADING_ZERO)));
48+
KeyPair keyPair = new KeyPair(pubKey, privKey);
49+
50+
Date creationDate = new Date();
51+
PGPKeyPair jcaPgpPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed448, keyPair, creationDate);
52+
isTrue("public key encoding before conversion MUST have leading 0",
53+
jcaPgpPair.getPublicKey().getPublicKeyPacket().getKey().getEncoded()[0] == 0); // leading 0
54+
55+
PublicKey cPubKey = jcaPGPKeyConverter.getPublicKey(jcaPgpPair.getPublicKey());
56+
PrivateKey cPrivKey = jcaPGPKeyConverter.getPrivateKey(jcaPgpPair.getPrivateKey());
57+
58+
testSignature(cPrivKey, pubKey, "Ed448");
59+
testSignature(privKey, cPubKey, "Ed448");
60+
61+
jcaPgpPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed448, new KeyPair(cPubKey, cPrivKey), creationDate);
62+
isTrue("public key encoding after conversion MUST have leading 0",
63+
jcaPgpPair.getPublicKey().getPublicKeyPacket().getKey().getEncoded()[0] == 0); // leading 0 is preserved
64+
}
65+
66+
67+
private void testWithEd25519KeyWithLeadingZero()
68+
throws NoSuchAlgorithmException, InvalidKeySpecException, PGPException, InvalidKeyException, SignatureException
69+
{
70+
JcaPGPKeyConverter jcaPGPKeyConverter = new JcaPGPKeyConverter().setProvider(new BouncyCastleProvider());
71+
72+
KeyFactory factory = KeyFactory.getInstance("EdDSA", new BouncyCastleProvider());
73+
74+
PublicKey pubKey = factory.generatePublic(new X509EncodedKeySpec(Hex.decode(ED25519_PUB_WITH_LEADING_ZERO)));
75+
PrivateKey privKey = factory.generatePrivate(new PKCS8EncodedKeySpec(Hex.decode(ED25519_KEY_WITH_LEADING_ZERO)));
76+
KeyPair keyPair = new KeyPair(pubKey, privKey);
77+
78+
Date creationDate = new Date();
79+
PGPKeyPair jcaPgpPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed25519, keyPair, creationDate);
80+
isTrue("public key encoding before conversion MUST have leading 0",
81+
jcaPgpPair.getPublicKey().getPublicKeyPacket().getKey().getEncoded()[0] == 0); // leading 0
82+
83+
PublicKey cPubKey = jcaPGPKeyConverter.getPublicKey(jcaPgpPair.getPublicKey());
84+
PrivateKey cPrivKey = jcaPGPKeyConverter.getPrivateKey(jcaPgpPair.getPrivateKey());
85+
86+
testSignature(cPrivKey, pubKey, "Ed25519");
87+
testSignature(privKey, cPubKey, "Ed25519");
88+
89+
jcaPgpPair = new JcaPGPKeyPair(PublicKeyAlgorithmTags.Ed25519, new KeyPair(cPubKey, cPrivKey), creationDate);
90+
isTrue("public key encoding after conversion MUST have leading 0",
91+
jcaPgpPair.getPublicKey().getPublicKeyPacket().getKey().getEncoded()[0] == 0); // leading 0 is preserved
92+
}
93+
94+
private void testSignature(PrivateKey privateKey, PublicKey publicKey, String edAlgo)
95+
throws NoSuchAlgorithmException, SignatureException, InvalidKeyException
96+
{
97+
Signature signature = Signature.getInstance(edAlgo, new BouncyCastleProvider());
98+
signature.initSign(privateKey);
99+
signature.update("Hello, World!\n".getBytes());
100+
byte[] sig = signature.sign();
101+
102+
signature.initVerify(publicKey);
103+
signature.update("Hello, World!\n".getBytes());
104+
isTrue("Signature MUST verify", signature.verify(sig));
105+
}
106+
107+
public static void main(String[] args)
108+
{
109+
Security.addProvider(new BouncyCastleProvider());
110+
runTest(new EdDSAKeyConversionWithLeadingZeroTest());
111+
}
112+
}

0 commit comments

Comments
 (0)