如何连接到 Java 中不发送证书的 SSL 服务器?
How to connect to an SSL Server in Java that doesn't send a certificate?
我有一个 Open SSL 服务器 运行 没有证书的情况,如下所示:
openssl s_server -accept 4443 -nocert
如何使用 Java 连接到此服务器?另外,如何在 Java 中启动我的服务器以不接受证书?
我附上了我一直在使用的 Client.java 和 Server.java 的代码。
运行 客户端附加代码时出错:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077)
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)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at Client.main(Client.java:27)
服务器端错误:
ERROR
140387701290656:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1358:
shutting down SSL
CONNECTION CLOSED
ACCEPT
Client.java
public class Client {
public static void main(String[] arstring) {
try {
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", 4443);
//sslsocket.setEnabledCipherSuites(sslsocket.getSupportedCipherSuites());
sslsocket.setEnabledCipherSuites(new String[] { "TLS_DH_anon_WITH_AES_128_CBC_SHA" }); //Added upon suggestion from Steffan
boolean test = sslsocket.isConnected();
System.out.println(test);
InputStream inputstream = sslsocket.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
System.out.println("1");
OutputStream outputstream = sslsocket.getOutputStream();
System.out.println("2");
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream,"UTF-8");
String str = "hello\n";
outputstreamwriter.write(str,0,str.length());
//outputstreamwriter.flush();
BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
String string = null;
int count = 0;
string = bufferedreader.readLine();
while (true) {
System.out.println(string);
System.out.flush();
System.out.println(++count);
string = bufferedreader.readLine();
if (inputstream.available()==0)
break;
else{
System.out.print("StreamData:");
System.out.println(inputstream.available());
}
}
System.out.println("Out");
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
Server.java
public class Server {
public static void main(String[] arstring) {
try {
SSLServerSocketFactory sslServersocketFactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket =
(SSLServerSocket) sslServersocketFactory.createServerSocket(4443);
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
if (sslSocket.isConnected())
System.out.println("Connected to a client");
InputStream inputStream = sslSocket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String command = "";
String response = "";
while ((command = bufferedReader.readLine()) != null) {
System.out.println("Command Recieved: "+command);
if (command.toLowerCase().compareTo("hello")==0)
response = "Bingo !! You got it write!\n";
else
response = "Type Hello to see a response\n";
OutputStream outputStream = sslSocket.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream,"UTF-8");
outputStreamWriter.write(response, 0, response.length());
outputStreamWriter.flush();
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
编辑:
我想我需要使用匿名 DH 密码,但它仍然无法正常工作。可能是我做错了。代码也已编辑。
How to connect to an SSL Server in Java that doesn't send a certificate?
如果它不发送证书,那么它可能使用 (1) 预共享密钥密码套件之一,如 TLS-SRP 或 TLS-PSK,或 (2) 使用匿名 Diffie-Hellman。
通常选择预共享密钥密码套件,因为它们提供相互身份验证和通道绑定。
匿名 Diffie-Hellman 通常是一个糟糕的选择,因为它缺少服务器身份验证。
I have a situation where an Open SSL server is running without a certificate as follows : openssl s_server -accept 4443 -nocert
好了,给你了。
How do I connect to this server using Java? Also, how do I start my server in Java to accept no certificate?
使用包含匿名交换的密码套件,例如:
- ADH-DES-CBC3-SHA
- ADH-AES128-SHA
- ADH-AES256-SHA
- ADH-CAMELLIA128-SHA
- ADH-CAMELLIA256-SHA
- ADH-SEED-SHA
- ADH-AES128-SHA256
- ADH-AES256-SHA256
- ADH-AES128-GCM-SHA256
- ADH-AES256-GCM-SHA384
您可以在 openssl ciphers 手册页中获取 ADH-AES128-SHA
到 TLS_DH_anon_WITH_AES_128_CBC_SHA
的映射。
您可以尝试以下命令:
openssl s_server -accept 4443 -tls1 -nocert -cipher "HIGH"
通过启用 TLS1,您可以避免任何潜在的问题,即一方或另一方禁用 SSLv2 和 SSLv3(这是一件好事),但您只提供 SSLv3(这是一件坏事)。
密码套件列表字符串 "HIGH"
默认包含 ADH(在生产中,通常您会 "HIGH:!ADH:!RC4:!MD5..."
)。
我有一个 Open SSL 服务器 运行 没有证书的情况,如下所示: openssl s_server -accept 4443 -nocert
如何使用 Java 连接到此服务器?另外,如何在 Java 中启动我的服务器以不接受证书?
我附上了我一直在使用的 Client.java 和 Server.java 的代码。
运行 客户端附加代码时出错:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077)
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)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at Client.main(Client.java:27)
服务器端错误:
ERROR
140387701290656:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1358:
shutting down SSL
CONNECTION CLOSED
ACCEPT
Client.java
public class Client {
public static void main(String[] arstring) {
try {
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", 4443);
//sslsocket.setEnabledCipherSuites(sslsocket.getSupportedCipherSuites());
sslsocket.setEnabledCipherSuites(new String[] { "TLS_DH_anon_WITH_AES_128_CBC_SHA" }); //Added upon suggestion from Steffan
boolean test = sslsocket.isConnected();
System.out.println(test);
InputStream inputstream = sslsocket.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
System.out.println("1");
OutputStream outputstream = sslsocket.getOutputStream();
System.out.println("2");
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream,"UTF-8");
String str = "hello\n";
outputstreamwriter.write(str,0,str.length());
//outputstreamwriter.flush();
BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
String string = null;
int count = 0;
string = bufferedreader.readLine();
while (true) {
System.out.println(string);
System.out.flush();
System.out.println(++count);
string = bufferedreader.readLine();
if (inputstream.available()==0)
break;
else{
System.out.print("StreamData:");
System.out.println(inputstream.available());
}
}
System.out.println("Out");
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
Server.java
public class Server {
public static void main(String[] arstring) {
try {
SSLServerSocketFactory sslServersocketFactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket =
(SSLServerSocket) sslServersocketFactory.createServerSocket(4443);
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
if (sslSocket.isConnected())
System.out.println("Connected to a client");
InputStream inputStream = sslSocket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String command = "";
String response = "";
while ((command = bufferedReader.readLine()) != null) {
System.out.println("Command Recieved: "+command);
if (command.toLowerCase().compareTo("hello")==0)
response = "Bingo !! You got it write!\n";
else
response = "Type Hello to see a response\n";
OutputStream outputStream = sslSocket.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream,"UTF-8");
outputStreamWriter.write(response, 0, response.length());
outputStreamWriter.flush();
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
编辑:
我想我需要使用匿名 DH 密码,但它仍然无法正常工作。可能是我做错了。代码也已编辑。
How to connect to an SSL Server in Java that doesn't send a certificate?
如果它不发送证书,那么它可能使用 (1) 预共享密钥密码套件之一,如 TLS-SRP 或 TLS-PSK,或 (2) 使用匿名 Diffie-Hellman。
通常选择预共享密钥密码套件,因为它们提供相互身份验证和通道绑定。
匿名 Diffie-Hellman 通常是一个糟糕的选择,因为它缺少服务器身份验证。
I have a situation where an Open SSL server is running without a certificate as follows : openssl s_server -accept 4443 -nocert
好了,给你了。
How do I connect to this server using Java? Also, how do I start my server in Java to accept no certificate?
使用包含匿名交换的密码套件,例如:
- ADH-DES-CBC3-SHA
- ADH-AES128-SHA
- ADH-AES256-SHA
- ADH-CAMELLIA128-SHA
- ADH-CAMELLIA256-SHA
- ADH-SEED-SHA
- ADH-AES128-SHA256
- ADH-AES256-SHA256
- ADH-AES128-GCM-SHA256
- ADH-AES256-GCM-SHA384
您可以在 openssl ciphers 手册页中获取 ADH-AES128-SHA
到 TLS_DH_anon_WITH_AES_128_CBC_SHA
的映射。
您可以尝试以下命令:
openssl s_server -accept 4443 -tls1 -nocert -cipher "HIGH"
通过启用 TLS1,您可以避免任何潜在的问题,即一方或另一方禁用 SSLv2 和 SSLv3(这是一件好事),但您只提供 SSLv3(这是一件坏事)。
密码套件列表字符串 "HIGH"
默认包含 ADH(在生产中,通常您会 "HIGH:!ADH:!RC4:!MD5..."
)。