相关文章推荐
想出家的墨镜  ·  Using UI Automation ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm trying to authorize an old JBoss 5 running on JRockit 6 to access to a CAS server using a Let's encrypt certificate.

The problem is that Let's encrypt is not supported on JDK6 so I added the root certificate to the cacerts file.

Now the problem is that JDK 6 does not understand such big key ( java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive) ) so I tried to switch to Bouncy Castle JCE/JCA by adding bcprov-jdk15on-1.61.jar & bctls-jdk15on-1.61.jar to the $JAVA_HOME/jre/lib/ext folder & added org.bouncycastle.jce.provider.BouncyCastleProvider & org.bouncycastle.jsse.provider.BouncyCastleJsseProvider as first security providers in $JAVA_HOME/jre/lib/security/java.security file as explained partly here .

After a java.lang.ArrayIndexOutOfBoundsException: 64 I switched from SunX509 to X.509 value for ssl.KeyManagerFactory.algorithm key in java.security file.

Now I have the following error (I think the same as this thread on Oracle forum ):

java.security.NoSuchAlgorithmException: Algorithm ECDH not available
  javax.crypto.KeyAgreement.getInstance(DashoA13*..)
  org.bouncycastle.jcajce.util.DefaultJcaJceHelper.createKeyAgreement(Unknown Source)
  org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto.calculateKeyAgreement(Unknown Source)
  org.bouncycastle.tls.crypto.impl.jcajce.JceTlsECDomain.calculateECDHAgreement(Unknown Source)
  org.bouncycastle.tls.crypto.impl.jcajce.JceTlsECDH.calculateSecret(Unknown Source)
  org.bouncycastle.tls.TlsECDHEKeyExchange.generatePreMasterSecret(Unknown Source)
  org.bouncycastle.tls.TlsProtocol.establishMasterSecret(Unknown Source)
  org.bouncycastle.tls.TlsClientProtocol.handleHandshakeMessage(Unknown Source)
  org.bouncycastle.tls.TlsProtocol.processHandshakeQueue(Unknown Source)
  org.bouncycastle.tls.TlsProtocol.processRecord(Unknown Source)
  org.bouncycastle.tls.RecordStream.readRecord(Unknown Source)
  org.bouncycastle.tls.TlsProtocol.safeReadRecord(Unknown Source)
  org.bouncycastle.tls.TlsProtocol.blockForHandshake(Unknown Source)
  org.bouncycastle.tls.TlsClientProtocol.connect(Unknown Source)
  org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source)
  org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source)
  sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
  sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:167)
  sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1031)
  sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
  org.jasig.cas.client.validation.Saml11TicketValidator.retrieveResponseFromServer(Saml11TicketValidator.java:216)

But by looking at org.bouncycastle.jcajce.provider.asymmetric.EC's sources such KeyAgreement should be correctly set by org.bouncycastle.jce.provider.BouncyCastleProvider.

But effectively, as it is the org.bouncycastle.jsse.provider.BouncyCastleJsseProvider which is used when creating a https client, this provider doesn't register this algorithm and I don't know how to do this.

Someone knows how to workaround this?

I have also tried to declare those jars as dependencies to my war and explicitely instanciate them like this:

    static {
            org.bouncycastle.jce.provider.BouncyCastleProvider bcp = new org.bouncycastle.jce.provider.BouncyCastleProvider();
            java.security.Security.insertProviderAt(bcp, 1);
            org.bouncycastle.jsse.provider.BouncyCastleJsseProvider bcjp = new org.bouncycastle.jsse.provider.BouncyCastleJsseProvider(bcp);
            java.security.Security.insertProviderAt(bcjp, 1);

But then, I have this stack that seems to be linked to a problem in JBoss:

java.lang.SecurityException: JCE cannot authenticate the provider BC
    javax.crypto.Cipher.getInstance(DashoA13*..)
    org.bouncycastle.jcajce.util.ProviderJcaJceHelper.createCipher(Unknown Source)
    org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto.hasEncryptionAlgorithm(Unknown Source)
    org.bouncycastle.tls.TlsUtils.isSupportedCipherSuite(Unknown Source)
    org.bouncycastle.tls.TlsUtils.getSupportedCipherSuites(Unknown Source)
    org.bouncycastle.jsse.provider.ProvTlsClient.getSupportedCipherSuites(Unknown Source)
    org.bouncycastle.tls.AbstractTlsClient.init(Unknown Source)
    org.bouncycastle.tls.TlsClientProtocol.connect(Unknown Source)
    org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source)
    org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source)
    sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:167)
    sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1031)
    sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
    org.jasig.cas.client.validation.Saml11TicketValidator.retrieveResponseFromServer(Saml11TicketValidator.java:216)
Caused by: java.util.jar.JarException: Cannot parse jar:file:/opt/jboss-5.1.0.GA/server/default/deploy/myapp.war/WEB-INF/lib/bcprov-jdk15on-1.61.jar!/
    javax.crypto.SunJCE_c.a(DashoA13*..)
    javax.crypto.SunJCE_b.b(DashoA13*..)
    javax.crypto.SunJCE_b.a(DashoA13*..)
    javax.crypto.Cipher.getInstance(DashoA13*..)
    org.bouncycastle.jcajce.util.ProviderJcaJceHelper.createCipher(Unknown Source)
    org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto.hasEncryptionAlgorithm(Unknown Source)
    org.bouncycastle.tls.TlsUtils.isSupportedCipherSuite(Unknown Source)
    org.bouncycastle.tls.TlsUtils.getSupportedCipherSuites(Unknown Source)
    org.bouncycastle.jsse.provider.ProvTlsClient.getSupportedCipherSuites(Unknown Source)
    org.bouncycastle.tls.AbstractTlsClient.init(Unknown Source)
    org.bouncycastle.tls.TlsClientProtocol.connect(Unknown Source)
    org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source)
    org.bouncycastle.jsse.provider.ProvSSLSocketDirect.startHandshake(Unknown Source)
    sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:167)
    sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1031)
    sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
    org.jasig.cas.client.validation.Saml11TicketValidator.retrieveResponseFromServer(Saml11TicketValidator.java:216)

In case, I have opened the issue #514 on BouncyCastle GitHub.

What you are seeing is consistent with the BouncyCastle JCE Provider not being registered. Hence the search for the ECDH Agreement is not finding it in the JCE search path.

To register the Provider dynamically simply add the following lines to your code

Security.addProvider(new BouncyCastleProvider());
Security.addProvider(new BouncyCastleJsseProvider());

as per the BouncyCastle Specifications section 6.1 and the test sample code BouncyCastle JSSE Test Code

I suspect that you are not correctly initiating the environment

Thank you for your answer, I tested the Security.addProvider already, both with Security.addProvider(new BouncyCastleJsseProvider()); (for which I had NoSuchAlgorithmException: Algorithm ECDH not available problem) & Security.addProvider(new BouncyCastleJsseProvider(new BouncyCastleProvider())); for which I had JCE cannot authenticate the provider BC... :/ – Anthony O. May 7, 2019 at 21:13 My apologies. I did not fully read the steps that you had already tried. From the above comments 1) fails because BC provider is not registered and 2) also does not register BC - try Security.addProvider(new BouncyCastleProvider()); If this still gets the authentication error, then that is your actual problem. As a workaround to this you could try using openJDK 12 to bypass authentication if this is a possibility in tour environment – Scimitar May 8, 2019 at 0:52 No I also tried your solution without any more succes (with your solution I still have the Algorithm ECDH not available problem, which I think is logic because BouncyCastleJsseProvider is used when I try to access an HTTPS URL, and it actually does not declare such algorithm and as far I have understood JCE when a provider is used, it can't access to things declared by other providers...). In my problem, I can't upgrade the JDK version because I'm stuck with JBoss 5.1 which can't run with anything newer than JDK 6... – Anthony O. May 9, 2019 at 9:29 @AnthonyO. In fact providers can "access things declared by other providers". In particular, BouncyCastleJsseProvider asks for "ECDH" via the provider mechanism, and relies on some other provider (e.g. BouncyCastleProvider) to "provide" it. It appears the issue here may be as simple as not registering BOTH providers. – Peter Dettman May 14, 2019 at 10:17 @PeterDettman well perhaps it is a bug but it doesn't seem to work like that, at least with JDK6: BouncyCastleJsseProvider doesn't manage to access ECDH provider provided by BouncyCastleProvider (I do register both providers & tested to register them in my webapp libs or in the JRE security system like explained in my question: both technics ended up with the same error message) – Anthony O. May 14, 2019 at 11:19

This problem was solved in https://github.com/bcgit/bc-java/issues/514 by anthony-o as it was caused by a re-packaging issue.

However, that solution did not work for me as my bouncycastle jars are not repackaged into shade/fat jars

Here is how I solved the issue: https://stackoverflow.com/a/59845413/497378

(I am not sure of the etiquette of posting link to answers from another stackoverflow question so please delete if not appropriate)

java.lang.SecurityException: JCE cannot authenticate the provider BC

I get the same error (and the JAR was directly from Maven, no repackaging was in place), I think because starting in BC 1.61 release JARs are signed using a more recent signature algorithm (or root certificate) that Java 6 is unable to verify.

By downgrading BC to 1.60 I managed to connect to a SNI-enabled TLS server (which wasn't reachable usually by Java 6). I used the following Maven dependency:

<dependency groupId="org.bouncycastle" artifactId="bctls-jdk15on" version="1.60"/>
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.