【问题标题】:specify ciphersuite for tls handshake为 tls 握手指定密码套件
【发布时间】:2015-06-25 08:36:30
【问题描述】:

在我的需求规范中是这样写的:

支持这些安全框架的 TLS 实现应至少实现以下密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256

Java 表示它在 Java7 的 TLSv1.2 中提供了此密码套件的实现。

我是安全新手,所以不知道如何使用它。

在我的客户端,我正在使用:

sslcontext = SSLContexts.custom()
                    .loadTrustMaterial(..)
                   .loadKeyMaterial(..)
                   .useProtocol("TLSv1.2")
                    .build();

我从谷歌了解到的是,客户端为服务器提供了一系列选项,服务器需要从中挑选。如果我错了,请纠正我。

现在我想在服务器端指定它,我不知道该怎么做如果我使用带有安全连接器的码头:

<Call name="addConnector">
     <Arg>
       <New class="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
         <Arg>
           <New class="org.eclipse.jetty.http.ssl.SslContextFactory">
             <Set name="KeyStore">./etc/keystores/server.jks</Set>
             <Set name="KeyStorePassword">password</Set>
             <Set name="KeyManagerPassword">password</Set>
             <Set name="TrustStore">./etc/keystores/trust_store.jks</Set>
             <Set name="TrustStorePassword">password</Set>
             <Set name="wantClientAuth">true</Set>
             <Set name="needClientAuth">true</Set>
           </New>
         </Arg>
         <Set name="port">8443</Set>
         <Set name="maxIdleTime">30000</Set>
       </New>
     </Arg>
</Call> 

有效,

如果我添加以下内容,这将启用 TLSv1.1:

<Set name="excludeProtocols">
      <Array type="java.lang.String">
        <Item>SSLv3</Item>
        <Item>TLSv1.2</Item>
        <Item>TLSv1</Item>
        <Item>SSLv2Hello</Item>
      </Array>
     </Set>

会报错:

执行 requestGET https://localhost:8443/ HTTP/1.1 中的异常 线程“主”javax.net.ssl.SSLHandshakeException:服务器选择 TLSv1.1,但该协议版本未启用或不受支持 客户。

但如果我只允许 TLSv1.2,它会运行:

<Set name="excludeProtocols">
          <Array type="java.lang.String">
            <Item>SSLv3</Item>
            <Item>TLSv1.1</Item>
            <Item>TLSv1</Item>
            <Item>SSLv2Hello</Item>
          </Array>
         </Set>

但是在这里,如果我指定协议和密码套件规范:

 <Set name="IncludeCipherSuites">
    <Array type="java.lang.String">
      <Item>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</Item>
    </Array>
  </Set>

我得到以下异常:

线程“主”javax.net.ssl.SSLHandshakeException 中的异常:远程 握手期间主机关闭连接 sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:912) 在 sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1294) 在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1321) 在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1305) 在 org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394) 在 org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353) 在 org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134) 在 org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) 在 org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380) 在 org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) 在 org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) 在 org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) 在 org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) 在 org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) 在 org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) 在 org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) 在 client.ClientCustomSSL.main(ClientCustomSSL.java:69) 引起: java.io.EOFException:SSL 对等点在 sun.security.ssl.InputRecord.read(InputRecord.java:352) 在 sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893) ... 还有 16 个

接下来我尝试在客户端使用工厂:

SSLConnectionSocketFactory factory=new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"},sslcontext.getDefaultSSLParameters().getCipherSuites(), SSLConnectionSocketFactory.getDefaultHostnameVerifier());

我已经在我的屏幕上打印了这些密码套件。

sslcontext.getDefaultSSLParameters().getCipherSuites()

然后我排除了除 "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" 之外的所有密码套件,它给了我错误

<Set name="ExcludeCipherSuites">
        <Array type="java.lang.String">
           <Item>...</Item>

                  <!--
            <Item>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</Item>
              -->
            </Array>
      </Set>

但如果我排除除 "TLS_RSA_WITH_AES_128_CBC_SHA256" 之外的所有内容,它就起作用了。

<Set name="ExcludeCipherSuites">
        <Array type="java.lang.String">
          <Item>...</Item>
          <!--
            <Item>TLS_RSA_WITH_AES_128_CBC_SHA256</Item>
             -->
                </Array>
      </Set>

表示jetty支持一些密码套件,而另一些不支持。

是这样吗?我们有这样的清单吗?或者有没有其他方法可以做到这一点。请指导。 我想在这次握手中使用这个密码套件,但我不知道该怎么做。

【问题讨论】:

  • 可能想要启用 Java SSL 调试并查看客户端和/或服务器是否按照您的预期进行。将 -Djavax.net.debug=all 添加到您的客户端 java 命令行。
  • 感谢您的回复,但我无法理解其输出。
  • 但是我想在这里补充一点,我已经更改了密码套件并且它起作用了。是否有任何列表,例如码头支持哪些套房,哪些不支持。我已经用它更新了我的问题
  • @HimanshuR Jetty 不支持密码套件。支持密码套件的是 JSSE,它们都列出了here。

标签: java security ssl encryption jetty


【解决方案1】:

如前所述,我需要启用密码套件 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,但 TLS_RSA_WITH_AES_128_CBC_SHA256 有效。

在进一步研究中,我知道这可能是因为用于创建证书的密钥算法。

我在 keytool 中使用 RSA 作为密钥创建证书,它不支持 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 但支持 TLS_RSA_WITH_AES_128_CBC_SHA256。

所以,我使用 EC 作为支持 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 的 keyalg

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    相关资源
    最近更新 更多