为 tls 握手指定密码套件
specify ciphersuite for tls handshake
在我的需求规格中写着:
支持这些安全框架的 TLS 实现应至少实现以下密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Java 表示它在 Java7.
的 TLSv1.2 中提供了此密码套件的实现
我是安全新手,所以不知道如何使用它。
在我的客户端,我正在使用:
sslcontext = SSLContexts.custom()
.loadTrustMaterial(..)
.loadKeyMaterial(..)
.useProtocol("TLSv1.2")
.build();
我从 google 中学到的是,客户端为服务器提供了一系列选项,而服务器需要从中挑选。如有错误请指正
现在我想在服务器端指定它,我不知道该怎么做如果我使用带安全连接器的码头:
<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>
会报错:
executing requestGET https://localhost:8443/ HTTP/1.1 Exception in
thread "main" javax.net.ssl.SSLHandshakeException: Server chose
TLSv1.1, but that protocol version is not enabled or not supported by
the client.
但如果我只允许 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>
我得到以下异常:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote
host closed connection during handshake at
sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:912) at
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1294)
at
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1321)
at
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1305)
at
org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
at
org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
at
org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
at
org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
at
org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at
org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at
org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at
org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at
org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at
org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at client.ClientCustomSSL.main(ClientCustomSSL.java:69) Caused by:
java.io.EOFException: SSL peer shut down incorrectly at
sun.security.ssl.InputRecord.read(InputRecord.java:352) at
sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893) ...
16 more
接下来我尝试在客户端使用工厂:
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>
这意味着码头支持一些密码套件,而有些则不支持。
是这样吗?我们有这样的清单吗?或者有没有其他方法可以做到。请指导。
我想用这个密码套件来握手,但我不知道怎么做。
如前所述,我需要启用密码套件 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,它不起作用但 TLS_RSA_WITH_AES_128_CBC_SHA256 有效。
进一步研究,我知道这可能是因为用于创建证书的密钥算法。
我使用 RSA 作为 keyalg 在 keytool 中创建证书,它不支持 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
在我的需求规格中写着:
支持这些安全框架的 TLS 实现应至少实现以下密码套件:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Java 表示它在 Java7.
的 TLSv1.2 中提供了此密码套件的实现我是安全新手,所以不知道如何使用它。
在我的客户端,我正在使用:
sslcontext = SSLContexts.custom()
.loadTrustMaterial(..)
.loadKeyMaterial(..)
.useProtocol("TLSv1.2")
.build();
我从 google 中学到的是,客户端为服务器提供了一系列选项,而服务器需要从中挑选。如有错误请指正
现在我想在服务器端指定它,我不知道该怎么做如果我使用带安全连接器的码头:
<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>
会报错:
executing requestGET https://localhost:8443/ HTTP/1.1 Exception in thread "main" javax.net.ssl.SSLHandshakeException: Server chose TLSv1.1, but that protocol version is not enabled or not supported by the client.
但如果我只允许 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>
我得到以下异常:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:912) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1294) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1321) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1305) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) at client.ClientCustomSSL.main(ClientCustomSSL.java:69) Caused by: java.io.EOFException: SSL peer shut down incorrectly at sun.security.ssl.InputRecord.read(InputRecord.java:352) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893) ... 16 more
接下来我尝试在客户端使用工厂:
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>
这意味着码头支持一些密码套件,而有些则不支持。
是这样吗?我们有这样的清单吗?或者有没有其他方法可以做到。请指导。 我想用这个密码套件来握手,但我不知道怎么做。
如前所述,我需要启用密码套件 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,它不起作用但 TLS_RSA_WITH_AES_128_CBC_SHA256 有效。
进一步研究,我知道这可能是因为用于创建证书的密钥算法。
我使用 RSA 作为 keyalg 在 keytool 中创建证书,它不支持 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