我正在创建一个SSL服务器并尝试向其发送数据,但是当我创建它时,它会出现以下错误:javax.net.ssl.SSLHandshakeException: no cipher suites in common
这是我的完整代码:
Logger.ready("log.txt");
Logger.log("Logger is now ready!");
System.setProperty("javax.net.ssl.trustStore", "MyKeytool.keytool");
System.setProperty("javax.net.ssl.keyStorePassword", "MyPassword");
Logger.log("Properties are set!");
try {
SSLServerSocket server = (SSLServerSocket) SSLServerSocketFactory.getDefault().createServerSocket(9999);
server.setEnabledCipherSuites(new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});
Logger.log("Sever was created & is read to connect!");
while (true) {
new ServerThread(server.accept()).start();
}
} catch (IOException e) {
e.printStackTrace();
}
并且客户端支持它会出现以下错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
所以我的问题是:
Q1:这是完全错误的方式吗?如果这是多么糟糕的话呢?
Q2:我当前正在存储我的keytool(客户端,keytool是由java keygen生成的keytool文件)没有保存(与aot编译的jar在同一目录中),但这是保存还是Crackers可以做任何事情这个keytool喜欢从连接或类似的东西读取什么?
问题3:我应该如何解决我的问题(建立正确的连接),以便我可以发送数据?
答案 0 :(得分:0)
好消息是您的代码与SSL服务器连接,并尝试SSL握手。
SSL握手中发生的第一件事是,双方试图就双方都可接受的密码套件达成一致。密码套件是认证,加密,消息认证和密钥交换算法的命名组合。
通常,服务器有一个它理解并认为可接受安全的密码套件列表,而客户端有另一个列表。
例如,配置为仅支持TLS1及更高版本的OpenSSL服务器可能具有此密码套件列表:
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384
ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1
ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1
SRP-DSS-AES-256-CBC-SHA SSLv3 Kx=SRP Au=DSS Enc=AES(256) Mac=SHA1
SRP-RSA-AES-256-CBC-SHA SSLv3 Kx=SRP Au=RSA Enc=AES(256) Mac=SHA1
SRP-AES-256-CBC-SHA SSLv3 Kx=SRP Au=SRP Enc=AES(256) Mac=SHA1
DHE-DSS-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=DSS Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(256) Mac=SHA256
DHE-DSS-AES256-SHA256 TLSv1.2 Kx=DH Au=DSS Enc=AES(256) Mac=SHA256
DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1
DHE-DSS-AES256-SHA SSLv3 Kx=DH Au=DSS Enc=AES(256) Mac=SHA1
DHE-RSA-CAMELLIA256-SHA SSLv3 Kx=DH Au=RSA Enc=Camellia(256) Mac=SHA1
DHE-DSS-CAMELLIA256-SHA SSLv3 Kx=DH Au=DSS Enc=Camellia(256) Mac=SHA1
ECDH-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
ECDH-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
ECDH-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AES(256) Mac=SHA384
ECDH-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256) Mac=SHA384
ECDH-RSA-AES256-SHA SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(256) Mac=SHA1
ECDH-ECDSA-AES256-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256) Mac=SHA1
AES256-GCM-SHA384 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD
AES256-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA256
AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1
...等(我的系统共有80个)
客户端告诉服务器它支持哪些服务器。服务器在其支持的密码套件列表中选择一个,并响应告诉客户端使用哪个密码套件。
您已选择仅使用一个密码套件列表来配置客户端。似乎服务器不支持TLS_RSA_WITH_AES_128_CBC_SHA
,因此服务器响应了握手失败,包括一条有用的消息:no cipher suites in common
。
仅指定一个密码套件并不是一个好主意,因为您允许的密码越少,它在服务器列表中的可能性就越小。
除非您有充分的理由指定密码套件,否则您应该让客户端使用默认列表。
getSupportedCipherSuites()
将为您提供Java可以支持的所有密码套件 - 不启用所有这些密码套件,因为有很多功能在默认情况下被禁用。
getEnabledCipherSuites()
将为您提供默认值。如果默认值不符合您的需求,您可以从这些默认值开始,并根据需要添加/删除。
包含私钥的文件与任何其他文件一样安全 - 它不会通过SSLServerSocket
泄露。您应该考虑其他可能被阅读的方式 - 确保它被读取保护,等等。考虑将其加密,然后考虑如何保护密码。在便利性,成本和安全性之间选择了一个平衡点。有些系统需要人员在每次系统启动时输入密钥文件密码。其他系统接受风险,并拥有密码文件或未加密的密钥文件(信任操作系统文件权限,物理和网络安全性)。