HttpClient SSLException

时间:2014-11-06 00:39:32

标签: java ssl https httpclient

我尝试将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.<init>(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.<init>(ECDHCrypt.java:75)
    ... 72 more

5 个答案:

答案 0 :(得分:14)

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

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

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

<exclusions>
    <exclusion>
        <groupId>bouncycastle</groupId>
        <artifactId>bcmail-jdk14</artifactId>
    </exclusion>
    <exclusion>
        <groupId>bouncycastle</groupId>
        <artifactId>bcprov-jdk14</artifactId>
    </exclusion>
    <exclusion>
        <groupId>bouncycastle</groupId>
        <artifactId>bctsp-jdk14</artifactId>
    </exclusion>
<exclusions>

如果您无法将其删除,我建议您更新到jdk15库。

链接文章的解释:

  

Java 1.5引入了对椭圆曲线加密API的更改。   如果您使用Java密码术扩展(JCE)&gt;提供程序   Java 1.4或更早版本它将不支持这种新的API更改   使用SSL时,使用基于Diffie-Hellman的密码可能会出错。该   SSL实现尝试设置椭圆曲线加密   使用ECGenParameterSpec对象。直到Java 1.5才添加此对象:   http://docs.oracle.com/javase/7/docs/api/java/security/spec/ECGenParameterSpec.html   (注意从线以来)。

     

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

答案 1 :(得分:4)

我有一段时间这个问题..升级后我的工作正常 bcprov-jdk14bcprov-jdk15

答案 2 :(得分:0)

我遇到了这个问题并且无法使用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中删除等),并设置(至少为此错误)。

答案 3 :(得分:0)

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

问题: 我们有一个使用google api进行google翻译的通用API,并且该API曾经向google API发出了https请求,因为赏金城堡还被注册为JCE提供者之一,并被用于加密,因此我们经常得到确切的错误。

我通过以下几个步骤解决了这个问题,而无需升级赏金城堡的罐子。 在执行https调用之前,我从安全提供者列表中删除了赏金城堡,并执行了https调用,以便使用Sun的JCE提供者进行加密。这对我来说很好。 在运行时通过以下代码从服务提供商列表中删除Bounty城堡,在删除它之前,我拿了Bounty Castle提供商实例,并在完成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;
}

答案 4 :(得分:0)

添加此

<dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.54</version>
 </dependency>