bcgit / bc-java

Bouncy Castle Java Distribution (Mirror)
https://www.bouncycastle.org/java.html
MIT License
2.31k stars 1.14k forks source link

PEM-encoded EC Private Key results into a ECDSA-key when read #1829

Closed kimmerin closed 1 month ago

kimmerin commented 1 month ago

Hi,

I've sent that as mail to the dev-crypto mailling list but am not sure if that list is still in wide use, so I try this approach in parallel.

I'm currently having a problem with a Jetty server not providing an EC-certificate if the browser requests one even if they are available. I'm using my own key manager to provide these keys and certificates that are read from a database instead of e.g. a file system. Further investigation shows me that the culprit actually is BouncyCastle (the PEMReader or -Writer to be specific).

I've attached a JUnit-test-class showing the problem. It contains two methods, where testConnectWithGeneratedKeys is trying to establish a TLS-connection using "freshly" generated keys and certificates as material for the key manager and testConnectWithPEMCopiedKeysthat first creates copies of the key and certificate using PEMWriter and PEMReader before attempting the same.

testConnectWithGeneratedKeys runs through, testConnectWithPEMCopiedKeys fails. Reason is that the private key that PEMReader creates returns "ECDSA" as algorithm instead of "EC". During the handshake the server classes of the JSSE check the usability of a provided key/certificate by checking the algorithm and because the browser requests "EC" and the private key now is "ECDSA", the key is dismissed:

javax.net.ssl|DEBUG|0F|Thread-0|2024-09-07 17:50:00.691 CEST|
  X509Authentication.java:328|
  alias private or public key is not of EC algorithm

Is that a bug? Am I doing something wrong? Is there a workaround (e.g. being able to "tell" a private key what algorithm should be returned)? I'm always assuming a PEBKAC but have difficulties to see where exactly that could be in this particular case 😉

After sending the mail I've continued and came up with a workaround that is quite ugly but works. This is tried in method testConnectWithFrankensteinedKeys. Not suggesting that to be an official workaround but it shows that it really is just the wrong algorithm name being returned that prevents the server from using that key for the TLS handshake.

__Test_TLSConnect.zip

For the sake of completeness: Zulu JDK 11.54.23-ca-jdk11.0.14 and BC 1.78.1

dghgit commented 1 month ago

See the latest in https://www.bouncycastle.org/betas there's now a setAlgorithmMapping() on the JcaPEMKeyConverter class which will allow you to the key type to EC instead of ECDSA (the current default), e.g.

KeyPair pair = new JcaPEMKeyConverter()
                               .setProvider("BC")
                               .setAlgorithmMapping(X9ObjectIdentifiers.id_ecPublicKey, "EC").getKeyPair(pemPair);

Where pemPair is the PEMKeyPair.

kimmerin commented 1 month ago

@dghgit Thanks for the response. That means that at the moment - without the use of beta releases - only my frankensteining of keys is a "solution"? Is there an estimate when this will be available as regular release?

dghgit commented 1 month ago

Hoping in the next month - we're really just waiting on the PQC algorithm testing to become stable. Trying to stay "ready to go" otherwise.

Feel free to copy the class in the meanwhile, I think that particular utility is almost stand alone - it should be easy to clone.

kimmerin commented 1 month ago

Feel free to copy the class in the meanwhile,

Thanks for the offer ;-) I'll stick with my frankensteinian solution until the release is out. I think that my question is answered and we can close this issue.