HttpClient SSLException

我尝试将https请求发送到Web服务,并且在几次成功尝试之后,我开始一致地得到此错误。 这个错误意味着什么,为什么它会在第一次发生时发生。

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1842) at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1825) at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1751) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:127) at org.apache.http.impl.io.AbstractSessionOutputBuffer.flushBuffer(AbstractSessionOutputBuffer.java:131) at org.apache.http.impl.io.AbstractSessionOutputBuffer.flush(AbstractSessionOutputBuffer.java:138) at org.apache.http.impl.io.ContentLengthOutputStream.flush(ContentLengthOutputStream.java:102) at org.apache.http.entity.StringEntity.writeTo(StringEntity.java:94) at org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:96) at org.apache.http.impl.client.EntityEnclosingRequestWrapper$EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108) at org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:120) at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:263) at org.apache.http.impl.conn.AbstractClientConnAdapter.sendRequestEntity(AbstractClientConnAdapter.java:227) at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:255) at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123) at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:622) at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:454) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:941) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:919) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:910) at com.nim.service.push.exacttarget.ExactTargetPushService.sendMessageContacts(ExactTargetPushService.java:208) at com.nim.service.push.exacttarget.ExactTargetPushService.sendPushNotification(ExactTargetPushService.java:106) at com.nim.domain.push.PushManager.pushHelper(PushManager.java:91) at com.nim.domain.push.PushManager.pushEntitlementChange(PushManager.java:40) at com.nim.domain.push.PushManager.pushEntitlementChange(PushManager.java:36) at com.nim.domain.push.PushManager.pushEntitlementChange(PushManager.java:51) at com.nim.batch.entitlement.SubscriptionEntitlementWriter.pushClientNotifications(SubscriptionEntitlementWriter.java:161) at com.nim.batch.entitlement.SubscriptionEntitlementReader.retrievePage(SubscriptionEntitlementReader.java:71) at com.nim.batch.entitlement.SubscriptionEntitlementReader.retrievePage(SubscriptionEntitlementReader.java:1) at com.nim.batch.entitlement.EntitlementPagedDifferentialReader.read(EntitlementPagedDifferentialReader.java:96) at sun.reflect.GeneratedMethodAccessor96.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at com.sun.proxy.$Proxy77.read(Unknown Source) at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:90) at org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:87) at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:108) at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367) at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214) at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143) at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:103) at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:68) at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130) at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264) at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76) at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367) at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214) at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143) at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250) at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195) at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135) at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61) at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60) at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144) at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124) at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135) at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281) at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.RuntimeException: Could not generate DH keypair at sun.security.ssl.ECDHCrypt.(ECDHCrypt.java:80) at sun.security.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:692) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:274) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:878) at sun.security.ssl.Handshaker.process_record(Handshaker.java:814) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122) ... 64 more Caused by: java.security.InvalidAlgorithmParameterException: parameter object not a ECParameterSpec at org.bouncycastle.jce.provider.JDKKeyPairGenerator$EC.initialize(Unknown Source) at sun.security.ssl.ECDHCrypt.(ECDHCrypt.java:75) ... 72 more 

我有同样的问题。 这篇文章帮助了我: http : //iwang.github.io/support/2014/03/14/cxf-cause-https-error.html

本质上,问题是您使用的是Bouncy Castle JDK1.4库而不是最近的1.5库。

为了解决这个问题,我完全删除了Bouncy Castle。 我发现它被一个不相关的库拉入,所以我将以下内容添加到pom.xml文件中的依赖项中:

   bouncycastle bcmail-jdk14   bouncycastle bcprov-jdk14   bouncycastle bctsp-jdk14   

如果你无法删除它,我建议更新到jdk15库。

链接文章的解释:

Java 1.5引入了对椭圆曲线加密API的更改。 如果您使用适用于Java 1.4或更早版本的Java Cryptography Extension(JCE)>提供程序,则它将不支持此新API更改,并且在使用SSL时可能会出现基于Diffie-Hellman的密码错误。 SSL实现尝试使用ECGenParameterSpec对象设置椭圆曲线加密。 直到Java 1.5才添加此对象: http : //docs.oracle.com/javase/7/docs/api/java/security/spec/ECGenParameterSpec.html (注意Since行)。

例如,bcprov-jdk14-131-1.0.jar是Bouncy Castle,就是这样一个提供者。 此版本的提供程序适用于JDK 1.4。 Bouncy Castle为每个JDK级别提供不同的库。

我有一段时间这个问题..从bcprov-jdk14 bcprov-jdk15升级到bcprov-jdk15之后我才能正常工作

我遇到了这个问题并且无法使用BC15,因为我们仍然支持1.4个客户端(旧的unix OS客户端)。 鉴于此限制,我能够通过在java.security.spec包中包含ECGenParameterSpec.java类来解决此问题。 不要从1.5源复制Java; 它拥有Oracle版权。 这是Apache Licensed的示例实现。 正如您所看到的,课程并不十分复杂,我相信您可以编写自己的课程。

https://android.googlesource.com/platform/libcore/+/a47f800/luni/src/main/java/java/security/spec/ECGenParameterSpec.java

 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.security.spec; /** * The parameter specification used to generate elliptic curve domain parameters. */ public class ECGenParameterSpec implements AlgorithmParameterSpec { // Standard (or predefined) name for EC domain // parameters to be generated private final String name; /** * Creates a new {@code ECGenParameterSpec} with the specified standard or * predefined name of the to-be-generated domain parameter. * * @param name * the name of the elliptic curve domain parameter. */ public ECGenParameterSpec(String name) { this.name = name; if (this.name == null) { throw new NullPointerException(); } } /** * Returns the name (standard or predefined) of the to-be-generated elliptic * curve domain parameter. * * @return the name */ public String getName() { return name; } } 

将此文件包含在项目源中(如果需要,从proguard中排除等),并设置(至少为此错误)。

即使我遇到了同样的问题,但在我的应用程序中,我不允许升级赏金城堡的jar子。

问题:我们有一个使用谷歌API的谷歌翻译的通用API,并且该API用于对谷歌API进行https请求,因为赏金城堡也被注册为JCE提供商之一并用于加密,我们曾经准确错误。

我通过以下几个步骤解决了这个问题,而没有升级赏金城堡jar子。 在进行https调用之前,我所做的是从安全提供程序列表中删除了bounty城堡并执行了https调用,以便Sun的JCE提供程序用于加密。 这对我来说很好。 通过以下代码在运行时从服务提供者列表中删除Bounty城堡,在删除它之前,我获取了赏金城堡提供程序实例,并在完成https调用后再次添加它。

代码如下

 java.security.Provider provider = java.security.Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); java.security.Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME); int index = getProviderIndex(BouncyCastleProvider.PROVIDER_NAME); String url = "some https url"; org.apache.commons.httpclient.methods.GetMethod method = new org.apache.commons.httpclient.methods.GetMethod(url); int responseCode = HTTP_CLIENT.executeMethod(method); if(provider != null && index >= 0) java.security.Security.insertProviderAt(provider, (index+1)); private int getProviderIndex(String name) { final Provider[] providers = Security.getProviders(); /** * Just to log available providers */ for (int i = 0; i < providers.length; i++) { Provider provider = providers[i]; LOGGER.error(provider.getName() + " " + provider.getVersion() + ": " + provider.getInfo()); } for(int index = 0; index < providers.length; index++){ if (providers[index] != null && providers[index].getName() != null && providers[index].getName().equalsIgnoreCase(name)) { return index; } } return -1; }