Java SSLSocket 问题
Issue with Java SSLSocket
我目前正在从事客户端-服务器项目。
出于安全原因,我决定使用 SSL。
我尝试将所有 Socket
和 ServerSocket
对象转换为它们的 SSL 变体,但无济于事。
当我使用 SSLServerSocket
并连接到它时,服务器端的套接字输出在 outputstream.write(byte[])
.
中间冻结
这是我用来创建 SSL 套接字的函数,
ContextController.CONTEXT
是 SSLContext
而 Constants.DEBUG
是我切换 SSL 的快速方法:
public static ServerSocket server(int port, int backlog) throws IOException {
return Constants.DEBUG ? new ServerSocket(port, backlog) : CONTEXT.getServerSocketFactory().createServerSocket(port, backlog);
}
public static Socket client(InetSocketAddress address) throws IOException {
return Constants.DEBUG ? new Socket(address.getHostName(), address.getPort())
: ContextController.CONTEXT.getSocketFactory().createSocket(address.getHostName(), address.getPort());
}
public static Socket client() throws IOException {
return Constants.DEBUG ? new Socket() : ContextController.CONTEXT.getSocketFactory().createSocket();
}
当 Constants.DEBUG = true
(即 SSL 关闭)时,它可以工作,但是当 SSL 打开时,它在无限期地发送一些数据后如上所述冻结。我该如何解决这个问题?
编辑:
这是ContextController.CONTEXT
的来源:
(注意,我知道我应该使用实际的 TrustManager
但首先我希望它起作用)
if (server) {// load the keystore
try (FileInputStream fis = new FileInputStream(ks)) {
CONTEXT = SSLContext.getInstance("SSL");
// load the keystore from the file
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(fis, PASSWORD);
// setup the KeyManagerFactory (used by the server)
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keystore, PASSWORD);
CONTEXT.init(kmf.getKeyManagers(), null, null);
}
catch (Exception e) {
}
}
else {
CONTEXT = SSLContext.getInstance("SSL");
CONTEXT.init(null, new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} }, null);
}
编辑 2:
这是它冻结位置的堆栈跟踪,请注意它不会崩溃,它会挂起:
Thread [ClientExecThread #0] (Suspended)
owns: AppOutputStream (id=54)
owns: ByteArrayOutputStream (id=55)
SocketOutputStream.socketWrite0(FileDescriptor, byte[], int, int) line: not available [native method]
SocketOutputStream.socketWrite(byte[], int, int) line: 111
SocketOutputStream.write(byte[], int, int) line: 155
OutputRecord.writeBuffer(OutputStream, byte[], int, int, int) line: 431
OutputRecord.write(OutputStream, boolean, ByteArrayOutputStream) line: 417
SSLSocketImpl.writeRecordInternal(OutputRecord, boolean) line: 876
SSLSocketImpl.writeRecord(OutputRecord, boolean) line: 847
AppOutputStream.write(byte[], int, int) line: 123
ByteArrayOutputStream.writeTo(OutputStream) line: 167
SocketStream.streamPacket(Packet) line: 181
ClientThread.lambda(Group) line: 150
1427646530.run(Object) line: not available
ClientThread.execute() line: 444
ClientThread$ClientExecThread.run() line: 261
我在 SocketStream.streamPacket(Packet) 181
之后的行中放置了一个断点,但它从未到达它。
我真的不知道为什么会这样,我不需要 SSL 的所有方面(只有加密部分,所以我没有实现 TrustManager
)所以我决定实现一个取而代之的是 Diffie Hellman。
这按预期工作并且结合了 DH 和 AES 我根据我的要求加密了流量。
谢谢大家的帮助!
我目前正在从事客户端-服务器项目。
出于安全原因,我决定使用 SSL。
我尝试将所有 Socket
和 ServerSocket
对象转换为它们的 SSL 变体,但无济于事。
当我使用 SSLServerSocket
并连接到它时,服务器端的套接字输出在 outputstream.write(byte[])
.
这是我用来创建 SSL 套接字的函数,
ContextController.CONTEXT
是 SSLContext
而 Constants.DEBUG
是我切换 SSL 的快速方法:
public static ServerSocket server(int port, int backlog) throws IOException {
return Constants.DEBUG ? new ServerSocket(port, backlog) : CONTEXT.getServerSocketFactory().createServerSocket(port, backlog);
}
public static Socket client(InetSocketAddress address) throws IOException {
return Constants.DEBUG ? new Socket(address.getHostName(), address.getPort())
: ContextController.CONTEXT.getSocketFactory().createSocket(address.getHostName(), address.getPort());
}
public static Socket client() throws IOException {
return Constants.DEBUG ? new Socket() : ContextController.CONTEXT.getSocketFactory().createSocket();
}
当 Constants.DEBUG = true
(即 SSL 关闭)时,它可以工作,但是当 SSL 打开时,它在无限期地发送一些数据后如上所述冻结。我该如何解决这个问题?
编辑:
这是ContextController.CONTEXT
的来源:
(注意,我知道我应该使用实际的 TrustManager
但首先我希望它起作用)
if (server) {// load the keystore
try (FileInputStream fis = new FileInputStream(ks)) {
CONTEXT = SSLContext.getInstance("SSL");
// load the keystore from the file
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(fis, PASSWORD);
// setup the KeyManagerFactory (used by the server)
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keystore, PASSWORD);
CONTEXT.init(kmf.getKeyManagers(), null, null);
}
catch (Exception e) {
}
}
else {
CONTEXT = SSLContext.getInstance("SSL");
CONTEXT.init(null, new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
} }, null);
}
编辑 2:
这是它冻结位置的堆栈跟踪,请注意它不会崩溃,它会挂起:
Thread [ClientExecThread #0] (Suspended)
owns: AppOutputStream (id=54)
owns: ByteArrayOutputStream (id=55)
SocketOutputStream.socketWrite0(FileDescriptor, byte[], int, int) line: not available [native method]
SocketOutputStream.socketWrite(byte[], int, int) line: 111
SocketOutputStream.write(byte[], int, int) line: 155
OutputRecord.writeBuffer(OutputStream, byte[], int, int, int) line: 431
OutputRecord.write(OutputStream, boolean, ByteArrayOutputStream) line: 417
SSLSocketImpl.writeRecordInternal(OutputRecord, boolean) line: 876
SSLSocketImpl.writeRecord(OutputRecord, boolean) line: 847
AppOutputStream.write(byte[], int, int) line: 123
ByteArrayOutputStream.writeTo(OutputStream) line: 167
SocketStream.streamPacket(Packet) line: 181
ClientThread.lambda(Group) line: 150
1427646530.run(Object) line: not available
ClientThread.execute() line: 444
ClientThread$ClientExecThread.run() line: 261
我在 SocketStream.streamPacket(Packet) 181
之后的行中放置了一个断点,但它从未到达它。
我真的不知道为什么会这样,我不需要 SSL 的所有方面(只有加密部分,所以我没有实现 TrustManager
)所以我决定实现一个取而代之的是 Diffie Hellman。
这按预期工作并且结合了 DH 和 AES 我根据我的要求加密了流量。
谢谢大家的帮助!