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
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.
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
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.
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?
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.