ssl socket multithreaded server exception - java

I want to create an ssl socket for a multithreaded server, but when a second client is connected I get some exceptions.
Here is my server code:
public class Master implements Runnable{
public static SSLSocket sslSocket = null;
public static SSLServerSocket sslServerSocket =null;
public static SSLServerSocketFactory sslServerSocketfactory ;
Master(SSLSocket s) {
this.sslSocket = s;
}
public static void main(String args[]) throws Exception {
System.out.println("Listening");
sslServerSocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
sslServerSocket = (SSLServerSocket) sslServerSocketfactory.createServerSocket(7777);
while (true)
{
sslSocket = (SSLSocket) sslServerSocket.accept();
sslSocket.setEnabledCipherSuites(sslServerSocketfactory.getSupportedCipherSuites());
System.setProperty("javax.net.ssl.keyStore", "Master_keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "passwd1");
System.out.println("Connected");
new Thread(new Master(sslSocket)).start();
}
}
public void run() {
synchronized(this){
do{
try{
//here is the error
ObjectOutputStream objout = new ObjectOutputStream(sslSocket.getOutputStream());
ObjectInputStream objin = new ObjectInputStream(sslSocket.getInputStream());
/* code */
} catch (Exception ex) {
Logger.getLogger(Master.class.getName()).log(Level.SEVERE, null, ex);}
}while(true);
}
}
}
And my client code is the following
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", 7777);
sslsocket.setEnabledCipherSuites(sslsocketfactory.getSupportedCipherSuites());
System.setProperty("javax.net.ssl.keyStore", "Client_keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "passwd2");
try {
do {
ObjectOutputStream objout = new ObjectOutputStream(sslsocket.getOutputStream());
ObjectInputStream objin = new ObjectInputStream(sslsocket.getInputStream());
/* code*/
} while (true);
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
The exceptions I get are:
SEVERE: null
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1541)
at sun.security.ssl.SSLSocketImpl.checkWrite(SSLSocketImpl.java:1553)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:71)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1877)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1786)
at java.io.ObjectOutputStream.<init>(ObjectOutputStream.java:247)
at master.Master.run(Master.java:233)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:292)
at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:1035)
at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:738)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:221)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
... 5 more
can someone give me a solution?

public static SSLSocket sslSocket = null;
The problem is here. There is absolutely no reason for making this variable static. Don't use static unless you know exactly why you are doing so.

Related

How do I decrypt a ssl message?

I am sending an ssl message to my browser, the browser then returns with a message but i do not know how to decrypt it?
CODE:
import java.io.*;
import javax.net.ssl.*;
public class Server{
public static void main(String[] args) throws IOException{
int port = 8080;
System.setProperty("javax.net.ssl.keyStore", "keys2/newLocal.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.getProperty("java.net.debug", "all");
SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
while(true){
System.out.println("listening on port: " + port);
SSLSocket sslsocket = (SSLSocket) sslServerSocket.accept();
PrintStream out = new PrintStream(sslsocket.getOutputStream(), true);
var protocol = sslsocket.getSSLParameters();
System.out.println(protocol);
BufferedInputStream bufferedInputStream= new BufferedInputStream(sslsocket.getInputStream());
System.out.println(bufferedInputStream);
String msg = "Hello World";
out.println("HTTPS/1.0 200 OK");
out.println("Content-Type: text/html");
out.println();
out.print(msg);
out.close();
}
}
}
The Message returned is:
java.io.BufferedInputStream#1bce4f0a
I assume that i need to get the public key from the browser to decrypt.

SSLSocket.getInputStream() hangs when called Java 11

I am writing a test class for a networking module which establishes a SSL connection used for sending messages. The Junit 4 test class sets up a client side keystore and truststore along with a server side keystore. These variables are used in setting up client side and server side SSLContexts from which I get SSLServerSocket and SSLSocket necessary for setting up a connection through their respective factories.
The SSLServerSocket successfully accepts the connection of my SSLSocket on localhost at the same port. However when I call the SSLSocket.getInputStream() method on the server side socket it hangs whereas calling the SSLSocket.getOutputStream() mehtod on the client side is successful. I am aware that this stage is responsible for initiating the SSL handshake but through my search I have found little on what could be causing a single side to hand. Someone elses post on a separate site mentioned that is could be a reverse dns lookup hanging how would I prevent this? I also tried explicitly starting the handshake in the first of the two Callable threads which hung in a similar fashion. This is my test class:
public class ReceiverClientThreadTest {
// ADD REG AND A SINGLE NETWORK
// ESTABLISH A TLS CONNECTION BETWEEN TWO POINTS WITH
private final static String KEY_MANAGER = "SunX509";
private final static String TLS_VERSION = "TLSv1.2";
private final static String RNG_ALGORITHM = "DEFAULT";
private final static String RNG_PROVIDER = "BC";
private static final String PROVIDER = "BC";
private static final String KEYSTORE_TYPE = "PKCS12";
private static KeyStore keyStore1, keyStore2, trustStore2;
private SSLSocket serverSocket;
private SSLSocket clientSocket;
#BeforeClass
public static void setUp() throws SQLException, GeneralSecurityException, OperatorCreationException, IOException {
String name1 = "localhost", name2 = "client";
KeyPair kp1 = SecurityUtilities.generateKeyPair();
KeyPair kp2 = SecurityUtilities.generateKeyPair();
X509Certificate cert1 = SecurityUtilities.makeV1Certificate(kp1.getPrivate(), kp1.getPublic(), name1);
X509Certificate cert2 = SecurityUtilities.makeV1Certificate(kp2.getPrivate(), kp2.getPublic(), name2);
keyStore1 = KeyStore.getInstance(KEYSTORE_TYPE, PROVIDER);
keyStore2 = KeyStore.getInstance(KEYSTORE_TYPE, PROVIDER);
trustStore2 = KeyStore.getInstance(KEYSTORE_TYPE, PROVIDER);
keyStore1.load(null, null);
keyStore1.setKeyEntry(name1, kp1.getPrivate(), "relaypass".toCharArray(), new X509Certificate[]{cert1});
// keyStore2.load(null, null);
// keyStore2.setKeyEntry(name2, kp2.getPrivate(), null, new X509Certificate[]{cert2});
trustStore2.load(null, null);
trustStore2.setCertificateEntry(name2, cert1);
// secureSocketManager = new SecureSocketManager(keyStore1, password);
}
#Before
public void init() throws IOException, GeneralSecurityException, InterruptedException, ExecutionException {
SSLServerSocket sslServerSocket = getSSLServerSocket();
SSLSocketFactory sslSocketFactory = getSSLSocketFactory();
ExecutorService pool = Executors.newFixedThreadPool(2);
Callable<SSLSocket> c1 = () -> {
return (SSLSocket) sslServerSocket.accept();
};
Callable<SSLSocket> c2 = () -> {
return (SSLSocket) sslSocketFactory.createSocket("localhost", 2048);
};
Future<SSLSocket> server = pool.submit(c1);
Thread.sleep(1000);
Future<SSLSocket> client = pool.submit(c2);
Thread.sleep(1000);
serverSocket = server.get();
clientSocket = client.get();
}
#After
public void tearDown(){
serverSocket = null;
clientSocket = null;
}
#org.junit.Test
public void endSession(){
Thread test = new Thread(new ReceiverClientThread(serverSocket));
test.start();
try (ObjectOutputStream output = new ObjectOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()))) {
System.out.println("here");
}catch (IOException e){
fail();
}
}
private SSLServerSocket getSSLServerSocket() throws GeneralSecurityException, IOException {
char[] entryPassword = "relaypass".toCharArray();
// COULD ADD PROVIDER IN THESE FOR CONSISTENCY
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX", "BCJSSE");
keyManagerFactory.init(keyStore1, entryPassword);
// specify TLS version e.g. TLSv1.3
SSLContext sslContext = SSLContext.getInstance(TLS_VERSION, "BCJSSE");
sslContext.init(keyManagerFactory.getKeyManagers(),null, null);
SSLServerSocketFactory fact = sslContext.getServerSocketFactory();
return (SSLServerSocket) fact.createServerSocket(2048 );
}
private SSLSocketFactory getSSLSocketFactory() throws GeneralSecurityException{
char[] entryPassword = "relaypass".toCharArray();
// COULD ADD PROVIDER IN THESE FOR CONSISTENCY
// KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER, "BCJSSE");
// keyManagerFactory.init(keyStore1, entryPassword);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX", "BCJSSE");
trustManagerFactory.init(trustStore2);
// specify TLS version e.g. TLSv1.3
SSLContext sslContext = SSLContext.getInstance(TLS_VERSION, "BCJSSE");
sslContext.init(null,trustManagerFactory.getTrustManagers(), null);
return sslContext.getSocketFactory();
}
This is the class which it is testing and the only relevant line, the one where the code hangs is commented as such:
public class ReceiverClientThread implements Runnable {
private final SSLSocket sslSocket;
public ReceiverClientThread(SSLSocket sslSocket) {
this.sslSocket = sslSocket;
}
public void run() {
try (ObjectInputStream input = new ObjectInputStream(new BufferedInputStream(sslSocket.getInputStream()))) {
System.out.println("here");
} catch (IOException e) {
}
}
}
Thanks
You could set a timeout on your sslSocket, so that if it hangs during stream read, it will only hang for a set period of time and then will throw an exception. This way the thread will not just hang indefinitely.
sslSocket.setSoTimeout(120000); // timeout of 2 min

Java SSLSocket with Socks5 Proxy

How can I use a SSLSocket with a socks5 proxy? I use a normal socket with proxy as underlying.
This code does not work:
public void debugIP(Proxy proxy) throws IOException, NoSuchAlgorithmException, KeyManagementException {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, null, null);
Socket underlying = new Socket(proxy);
InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address();
underlying.connect(new InetSocketAddress("checkip.amazonaws.com", 80));
SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket(
underlying,
proxyAddress.getHostName(),
proxyAddress.getPort(),
true);
printInputStream(socket.getInputStream());
}
private void printInputStream(InputStream inputStream) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
This code is throwing exceptions:
Exception in thread "main" javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
Without SSL the code works.
You are talking SSL to a plaintext port.
Just as the error message says.
Either fix the port or don't use SSL.

Smtp server issue starttls command to sslsocket but when startHandshake() read time out

public static Socket createSsl(Socket socket) throws IOException {
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) (factory.createSocket(socket, socket
.getInetAddress().getHostAddress(), socket.getPort(), true));
sslsocket.setUseClientMode(false);
sslsocket.startHandshake();
return sslsocket;
}
the sslsocket always read time out when sslsocket.startHandshake(), so what should I do to solve the problem?

Create app with SSLSocket Java

I want to create an app use SSLSocket: client send a String to server and server will uppercase that String and send back to client for display.
SSLServer
public class SSLServer {
public static void main(String args[]) throws Exception
{
try{
//Creaet a SSLServersocket
SSLServerSocketFactory factory=(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslserversocket=(SSLServerSocket) factory.createServerSocket(1234);
//Tạo 1 đối tượng Socket từ serversocket để lắng nghe và chấp nhận kết nối từ client
SSLSocket sslsocket=(SSLSocket) sslserversocket.accept();
//Tao cac luong de nhan va gui du lieu cua client
DataInputStream is=new DataInputStream(sslsocket.getInputStream());
PrintStream os=new PrintStream(sslsocket.getOutputStream());
while(true) //khi dang ket noi voi client
{
//Doc du lieu den
String input=is.readUTF();
String ketqua=input.toUpperCase();
//Du lieu tra ve
os.println(ketqua);
}
}
catch(IOException e)
{
System.out.print(e);
}
}
}
SSLClient
public class SSLClient {
public static void main(String args[])
{
try
{
//Mo 1 client socket den server voi so cong va dia chi xac dinh
SSLSocketFactory factory=(SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket=(SSLSocket) factory.createSocket("127.0.0.1",1234);
//Tao luong nhan va gui du lieu len server
DataOutputStream os=new DataOutputStream(sslsocket.getOutputStream());
DataInputStream is=new DataInputStream(sslsocket.getInputStream());
//Gui du lieu len server
String str="helloworld";
os.writeBytes(str);
//Nhan du lieu da qua xu li tu server ve
String responseStr;
if((responseStr=is.readUTF())!=null)
{
System.out.println(responseStr);
}
os.close();
is.close();
sslsocket.close();
}
catch(UnknownHostException e)
{
System.out.println(e.getMessage());
}
catch(IOException e)
{
System.out.println(e.getMessage());
}
}
}
When run SSLServer. It displays this error:
javax.net.ssl.SSLException: No available certificate or key corresponds
to the SSL cipher suites which are enabled
I have search and do some ways but.. Can you help me.
This will generate certificate:
keytool -genkey -keystore yourKEYSTORE -keyalg RSA
Enter yourPASSWORD and than start your server with ssl debug information(put yourKEYSTORE into directory with SSLServer.class):
java -Djavax.net.ssl.keyStore=yourKEYSTORE -Djavax.net.ssl.keyStorePassword=yourPASSWORD -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol -Djavax.net.debug=ssl SSLServer
Than start your client(put yourKEYSTORE into directory with SSLClient.class):
java -Djavax.net.ssl.trustStore=yourKEYSTORE -Djavax.net.ssl.trustStorePassword=yourPASSWORD SSLClient
#corVaroxid's answer is right. But if you want to set configurations programmatically to avoid global settings (like me), you can go like below (Kotlin):
val password = "yourPassword".toCharArray()
val keyStore = KeyStore.getInstance(File("yourKeystorePath.jks"), password)
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(keyStore)
val keyManagerFactory = KeyManagerFactory.getInstance("NewSunX509")
keyManagerFactory.init(keyStore, password)
val context = SSLContext.getInstance("TLS") //"SSL" "TLS"
context.init(keyManagerFactory.keyManagers, trustManagerFactory.trustManagers, null)
val factory = context.serverSocketFactory
(factory.createServerSocket(LISTENING_PORT) as SSLServerSocket).use { serverSocket ->
logger.trace("Listening on port: $LISTENING_PORT")
// ...
}
Or in Java:
final char[] password = "yourPassword".toCharArray();
final KeyStore keyStore = KeyStore.getInstance(new File("yourKeystorePath.jks"), password);
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("NewSunX509");
keyManagerFactory.init(keyStore, password);
final SSLContext context = SSLContext.getInstance("TLS");//"SSL" "TLS"
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
final SSLServerSocketFactory factory = context.getServerSocketFactory();
try (SSLServerSocket serverSocket = ((SSLServerSocket) factory.createServerSocket(LISTENING_PORT))) {
logger.trace("Listening on port: " + LISTENING_PORT);
// ...
}
Check the certificates that you have installed. Make sure they are supporting the cipher suites that you are negotiating.

Categories

Resources