Repository navigation
Description
Since 1.85, the BC provider's DH KeyPairGenerator rejects a DHParameterSpec whose private value length l equals the bit length of p. 1.84 accepted it, and the JDK's SunJCE provider still does. This breaks Oracle JDBC connections that use Oracle Native Network Encryption (NNE) in applications that register BC ahead of SunJCE.
The change is in 85b85e8 ("DH updates", 2026-06-19), which changed the check in DHParameters from l > p.bitLength() to l >= p.bitLength(). It's still on main and in 1.86, and I couldn't find it in the release notes.
Minimal reproduction (JDK 21, no Oracle needed):
import java.security.KeyPairGenerator;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class DhFullLengthL {
public static void main(String[] args) throws Exception {
// Any 2048-bit DH group; here the JDK's built-in one.
KeyPairGenerator sun = KeyPairGenerator.getInstance("DH", "SunJCE");
sun.initialize(2048);
DHParameterSpec group = ((DHPublicKey) sun.generateKeyPair().getPublic()).getParams();
// Private value length equal to the prime size, as Oracle's JDBC driver passes it.
DHParameterSpec spec = new DHParameterSpec(group.getP(), group.getG(), group.getP().bitLength());
KeyPairGenerator jdk = KeyPairGenerator.getInstance("DH", "SunJCE");
jdk.initialize(spec);
jdk.generateKeyPair();
System.out.println("SunJCE: OK");
KeyPairGenerator bc = KeyPairGenerator.getInstance("DH", new BouncyCastleProvider());
bc.initialize(spec);
bc.generateKeyPair();
System.out.println("BC: OK");
}
}Result on OpenJDK 21.0.13:
bcprov-jdk18on 1.84: SunJCE: OK, BC: OK
bcprov-jdk18on 1.85 and 1.86: SunJCE: OK, then
java.security.InvalidAlgorithmParameterException: when l value specified, it must be less than bitlength(p)
at org.bouncycastle.jcajce.provider.asymmetric.dh.KeyPairGeneratorSpi.initialize(Unknown Source)
How Oracle hits it: in ojdbc11 21.x (tested with 21.20.0.0 and 21.21.0.0), oracle.net.useJCEAPI defaults to true, so the driver's NNE key exchange calls KeyPairGenerator.getInstance("DiffieHellman") with no provider and initializes it with new DHParameterSpec(p, g, keyLength), using the prime and key length the database server sends. The server sends a 2048-bit prime and a key length equal to the prime size, so with BC at provider position 1 the connection fails with the exception above. We see it with Oracle Database 19c and reproduced it with 21c, with SQLNET.ENCRYPTION_SERVER = required.
Questions:
- Is rejecting
l == bitLength(p)intended? If the goal is to keep the generated private value belowp, could the JCAKeyPairGeneratorSpiaccept this case the way SunJCE does, for compatibility? - If the strict check stays, could it go in the release notes? As far as I can see there's no property to relax it;
org.bouncycastle.dh.allow_unsafe_p_valueonly applies to themcheck.
Activity
dghgit commentedon Nov 5, 2026
Hmmm. We might have overdone it. Try the release candidate in https://www.bouncycastle.org/betas and let me know how it goes.
dharmashivam-cb commentedon Nov 5, 2026
@dghgit Thanks, the 1.87 RC fixes it: the repro passes again, and Oracle NNE connection works with the RC jars.
dghgit commentedon Nov 5, 2026
We found a small gap in the update. I've dealt with that and confirmed there doesn't appear to be a regression but if you would retry the latest now I can make sure what winds up on Maven will work for you:
sha256sum d70aad6c26d6838a35acd5fd8ec7ef1a2f6c5b7a181fe45d1aea8210e4cc0f28 bcprov-jdk18on-1.87.jar
Up on https://www.bouncycastle.org/betas
dharmashivam-cb commentedon Nov 6, 2026
@dghgit the updated RC (bcprov sha256 d70aad6c...0f28) works for us.