Ram*_*zan 5 java sockets ssl java-8
我正在尝试SSLServerSocket使用自定义密钥库/信任库打开并且仅TLSv1.2启用.这是我打开这样的套接字的相关代码:
SSLContext sslContext = null;
ServerSocket serverSocket = null;
KeyManagerFactory kmf = null;
KeyStore keystore = loadKeyStore(KEYSTORE_FILE);
if (keystore == null) {
// throw exception
}
char[] psw = System.console().readPassword("Enter password for the key materials in file \"%s\":", KEYSTORE_FILE);
try {
kmf = KeyManagerFactory.getInstance("PKIX");
kmf.init(keystore, psw);
} catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {
e.printStackTrace();
kmf = null;
// throw exception
}
try {
sslContext = SSLContext.getInstance("TLSv1.2");
System.out.println(kmf==null); // prints false
sslContext.init(kmf==null?null:kmf.getKeyManagers(), null, null);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
// throw exception
}
try {
serverSocket = sslContext.getServerSocketFactory().createServerSocket(PORT, BACKLOG, HOST);
((SSLServerSocket)serverSocket).setEnabledProtocols(new String[]{"TLSv1.2"});
} catch (IOException e) {
// throw exception
}
Run Code Online (Sandbox Code Playgroud)
该loadKeyStore功能是,
private static KeyStore loadKeyStore(String filename) {
KeyStore keystore = null;
FileInputStream fis = null;
try {
keystore = KeyStore.getInstance("JKS");
char[] psw = System.console().readPassword("Enter password for the KeyStore file \"%s\":", filename);
if (psw != null) {
fis = new FileInputStream(filename);
keystore.load(fis, psw);
}
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
keystore = null;
LogManager.getLogger().fatal("cannot load KeyStore from file \"" + filename + "\".", e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
LogManager.getLogger().error("cannot close file " + filename, e);
}
fis = null;
}
}
return keystore;
}
Run Code Online (Sandbox Code Playgroud)
我接受不同线程中的连接
while (!stopped) {
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (IOException e) {
if (!stopped) {
logger.error("exception while accepting connections.", e);
}
break;
}
// start new threads to handle this connection
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我在Firefox上输入https:// HOST:PORT时,它说:
Firefox无法保证数据在HOST上的安全性,因为它使用SSLv3,这是一种破坏的安全协议.高级信息:ssl_error_no_cypher_overlap
如何打开仅接受TLSv1.2连接的服务器套接字?
PS我尝试将代码中的"TLSv1.2"字符串逐个更改为"TLS",但没有任何改变.
编辑:我编辑了如下代码:
serverSocket = sslContext.getServerSocketFactory().createServerSocket(port, backlog, host);
((SSLServerSocket)serverSocket).setEnabledProtocols(new String[]{"TLSv1.2"});
for (String s: ((SSLServerSocket)serverSocket).getEnabledCipherSuites()) {
System.out.println(s);
}
Run Code Online (Sandbox Code Playgroud)
而输出是,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA TLS _ECDHE_ECDSA_WITH_RC4_128_SHA TLS_ECDHE_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_SHA TLS_ECDH_ECDSA_WITH_RC4_128_SHA TLS_ECDH_RSA_WITH_RC4_128_SHA SSL_RSA_WITH_RC4_128_MD5 TLS_EMPTY_RENEGOTIATION_INFO_SCSV
我不确定,但似乎问题不在于缺少启用的密码套件.对?
EDIT2:我试过了openssl s_client -connect HOST:PORT,结果是

(这里有一个非常相似的问题我在这里回答.)
实质上,SSLContext.getInstance("TLSv1.2")也可以返回支持其他协议的实例.
如果您想使用一组特定的协议,则需要使用setEnabledProtocols(...),这是您在第一次编辑后所做的.您现在可以获得一些名称以密码开头的密码套件SSL_,但这只是名称,这些密码套件仍然适用于TLS 1.2.正如JDK 8的Java密码体系结构标准算法名称文档所述:
一些JSSE密码套件名称是在TLSv1.0最终确定之前定义的,因此给出了SSL_前缀.前缀为TLS_的TLS RFC中提到的名称在功能上等同于前缀为SSL_的JSSE密码套件.
您的最后一个问题(" 没有可用的对等证书 ",以及握手失败)似乎表明在您尝试使用的密钥库中找不到证书(带有私钥).
实际上,虽然您提到的密码套件已启用,但如果无法使用它们,它们将自动禁用.所有这些都是RSA或DSS密码套件,这意味着他们需要具有RSA或DSA密钥的证书,其私钥可用.如果用私有密钥进入这样的证书不能在密钥库中找到,它不会被使用KeyManager和SSLContext.因此,当实际尝试握手时,它们将被禁用.这通常会导致在服务器端(" javax.net.ssl.SSLHandshakeException: no cipher suites in common")的握手过程中抛出异常,以及通过OpenSSL在客户端获得的错误消息.
| 归档时间: |
|
| 查看次数: |
11278 次 |
| 最近记录: |