Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sun jdk support #5

Open
nikhil32 opened this issue Aug 25, 2016 · 11 comments
Open

sun jdk support #5

nikhil32 opened this issue Aug 25, 2016 · 11 comments

Comments

@nikhil32
Copy link

nikhil32 commented Aug 25, 2016

When I ran the encryption code with open jdk 1.8 it is all working fine. But when I am running with sun jdk jdk1.8.0_20, it is trowing following exception

Exception in thread "main" java.security.InvalidKeyException: Not an EC key: ECDH
    at sun.security.ec.ECKeyFactory.checkKey(ECKeyFactory.java:121)
    at sun.security.ec.ECKeyFactory.toECKey(ECKeyFactory.java:90)
    at sun.security.ec.ECDHKeyAgreement.engineInit(ECDHKeyAgreement.java:67)
    at javax.crypto.KeyAgreement.implInit(KeyAgreement.java:341)
    at javax.crypto.KeyAgreement.chooseProvider(KeyAgreement.java:373)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:465)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:436)
    at nl.martijndwars.webpush.HttpEce.deriveDH(HttpEce.java:117)
    at nl.martijndwars.webpush.HttpEce.deriveKey(HttpEce.java:54)
    at nl.martijndwars.webpush.HttpEce.encrypt(HttpEce.java:166)
    at nl.martijndwars.webpush.PushService.encrypt(PushService.java:62)
@martijndwars
Copy link
Member

Try adding the following code to your initialisation. This installs the BouncyCastle security provider:

Security.addProvider(new BouncyCastleProvider());

@nikhil32
Copy link
Author

I added it without which it's not even working

@yaronshahverdi
Copy link

Any update on this issue? I've added the code snippet to add the BouncyCastleProvider but I'm still receiving the same exception: java.security.InvalidKeyException: Not an EC key: ECDH

@martijndwars
Copy link
Member

Sorry, no update. I can spend some time on this next weekend, but since I'm not able to reproduce the problem it's very hard to debug. What is your setup (operating system, Java runtime, etc)?

@yaronshahverdi
Copy link

Thank you Martijn! I'm running on Mac, Java 1.8 in a Spring application. It's happening on the pushService.send(notification) call.

@martijndwars
Copy link
Member

martijndwars commented May 25, 2017

If I recall correctly, Sun's implementation of Java Cryptography Extension (JCE), which is included in the JDK, does not support ECDH. That's the reason I added a dependency on BouncyCastle; they do provide the necessary encryption.

From the stack trace I infer that it is using Sun's implementation instead of BouncyCastle's implementation. I cannot explain why this is happening. Could you try to give BouncyCastle provider highest priority? Instead of just calling addProvider, you call insertProviderAt:

Security. insertProviderAt(new BouncyCastleProvider(), 1);

@yaronshahverdi
Copy link

The highest priority I was able to give the BouncyCastleProvider without crashing my app was 5, and I still received the same exception :/. It still came before the JCE provider.

For reference, here's the result I get from the Security.getProviders() call:
screen shot 2017-05-26 at 2 52 43 pm

@martijndwars
Copy link
Member

I did the same check and I get a similar result. It's not necessarily bad that it first tries Sun's implementation. In fact, that's what happens on my machine as well. While stepping through the code, the InvalidKeyException: Not an EC key: ECDH is thrown as well, but the KeyAgreement class catches the exception and goes on to the next provider (until it arrives at the BouncyCastle implementation).

Could you try stepping through the code and see if something similar happens (or where it goes wrong)?

@yaronshahverdi
Copy link

Found out the issue was that the JCE could not authenticate the BouncyCastleProvider, even when explicitly adding the provider via Security.addProvider(new BouncyCastleProvider()) or Security.insertProviderAt(new BouncyCastleProvider(),1).

The solution that worked for me can be found here: https://stackoverflow.com/a/17400821, which was to manually add the BouncyCastle jars to the directory: $JAVA_HOME/jre/lib/ext/. Those jars can just be downloaded from the BouncyCastle website: https://www.bouncycastle.org/latest_releases.html

@martijndwars
Copy link
Member

martijndwars commented Jun 8, 2017

I came across this issue as well when I created a fat JAR (a.k.a. uber JAR, shadow JAR). The BouncyCastle JAR is signed and if you create a fat JAR the contents of the BouncyCastle JAR are extracted and put in the fat JAR which breaks the signature. I suspect something similar was happening to you.

When I realised this I updated the build.gradle to exclude BouncyCastle from the fat JAR and add ../../lib/bcprov-jdk15on-154.jar to the Class-Path definition MANIFEST.MF. That way, when you run the generated fat JAR, it adds BouncyCastle to the classpath. Unfortunately, I had to commit lib/bcprov-jdk15on-154.jar into git.

In practice, developers will be using this project as a library and not as a fat JAR, so they will have to change their build to provide BouncyCastle at runtime. There are many ways to do this:

  1. Put bcprov-jdk15on-154.jar in $JAVA_HOME/jre/lib/ext, like you suggested. The downside of this approach is that if you need to repeat this if you update your JRE.
  2. Adapt the build system to add BouncyCastle at runtime (similar to how I adapted the gradle.build to add a Class-Path to the MANIFEST.MF). The downside is that you need to commit bcprov-jdk15on-154.jar into git.
  3. Use a custom class loader that is able to load nested JARs. That way you can put the BouncyCastle JAR in a fat JAR without breaking the signature. The downside is that you need to create and use a custom classloader (Spring Boot provides one, though).

I will update the README with instructions. Thanks for your investigation and feedback!

@bsarkar6990
Copy link

After some hit and trial I am able to resolve it.

Issue: When I was working with JDK 1.8 and bcprov-jdk15on-164.jar which is the latest bouncy castle for JDK 1.5 - JDK 1.11, it was working awesome. But bcprov-jdk15on-164.jar doesn't work for JDK 1.7.0_80 and getting "java.security.InvalidKeyException: Not an EC key: ECDH" error.

Solution: While working with JDK 1.7.0_80 please use bcprov-jdk15to18-164.jar provider which is for JDK 1.5 - JDK 1.8.

frmans added a commit to frmans/webpush-java that referenced this issue May 9, 2023
Since there already is a dependency to BouncyCastle in Utils.java it doesn't add any more restrictions doing this, also this solves the following issue web-push-libs#5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants