I am currently working on a university little project in which we should make an android application which can communicate with a java SSL Socket. I am kinda new on the SSL connections, I red about keystores and stuff but I didn't really get it.
This is the Android side:
SSLSocketFactory socketFactory;
SSLSocket socket;
socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
try {
socket = (SSLSocket) socketFactory.createSocket("192.168.1.131", 7070);
System.out.println("Connected!");
} catch (IOException e) {
e.printStackTrace();
}
This is the java server one:
SSLServerSocketFactory socketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket serverSocket = (SSLServerSocket) socketFactory.createServerSocket(7070);
serverSocket.setEnabledProtocols(new String[] {"TLSv1.3"});
while (true) {
// wait for client connection and check login information
try {
System.err.println("Waiting for connection...");
SSLSocket socket = (SSLSocket) serverSocket.accept();
System.out.println("Connessione Accettata");
// open BufferedReader for reading data from client
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// open PrintWriter for writing data to client
System.out.println(input);
//PrintWriter output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
//output.close();
input.close();
socket.close();
} // end try
// handle exception communicating with client
catch (IOException ioException) {
ioException.printStackTrace();
}
}
Obviously the sockets don't even connect each other, what should I implement to make it work?
Related
I need to develop a client-server desktop application with SSL sockets in Java. One of the requirements is to encrypt messages.
I'm trying out some internet example codes just to know how to make the encrypted connection. The examples seem to work fine, or at least they do not generate errors, however I have to verify from Wireshark that messages are actually encrypted, but in wireshark I only see TCP packets. I have the certificates and keystores correct, in my opinion.
JavaSSLServer.java
/**
#web http://java-buddy.blogspot.com/
*/
public class JavaSSLServer {
static final int port = 8000;
public static void main(String[] args) {
System.setProperty("javax.net.ssl.keyStore","/home/jose/serverKey.jks");
System.setProperty("javax.net.ssl.keyStorePassword","servpass");
SSLServerSocketFactory sslServerSocketFactory =
(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
try {
ServerSocket sslServerSocket =
sslServerSocketFactory.createServerSocket(port);
System.out.println("SSL ServerSocket started");
System.out.println(sslServerSocket.toString());
Socket socket = sslServerSocket.accept();
System.out.println("ServerSocket accepted");
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
try (BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
String line;
while((line = bufferedReader.readLine()) != null){
System.out.println(line);
out.println(line);
}
}
System.out.println("Closed");
} catch (IOException ex) {
Logger.getLogger(JavaSSLServer.class.getName())
.log(Level.SEVERE, null, ex);
}
}}
JavaSSLClient.java
/**
#web http://java-buddy.blogspot.com/
*/
public class JavaSSLClient {
static final int port = 8000;
public static void main(String[] args) {
System.setProperty("javax.net.ssl.trustStore", "/home/jose/clientTrustedCerts.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "clientpass");
SSLSocketFactory sslSocketFactory =
(SSLSocketFactory)SSLSocketFactory.getDefault();
try {
Socket socket = sslSocketFactory.createSocket("localhost", port);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
try (BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
Scanner scanner = new Scanner(System.in);
while(true){
System.out.println("Enter something:");
String inputLine = scanner.nextLine();
if(inputLine.equals("q")){
break;
}
out.println(inputLine);
System.out.println(bufferedReader.readLine());
}
}
} catch (IOException ex) {
Logger.getLogger(JavaSSLClient.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}
I added the System.setProperty (...
In Wireshark:
Other example:
https://github.com/chuidiang/chuidiang-ejemplos-google-code/commit/2843dafc0a942c2dd636f7e2e1f9be6fe0b9e9ec
The results in Wireshark were similar.
I want to establish a connection with SSL sockets that encrypts the messages between the client and server, and that can be verified from Wireshark (that is another requirement).
My questions are:
How do I verify that the message is actually encrypted using wireshark?
Should I see SSL / TLS packets instead of TCP to conclude that they are encrypted?
Can you tell me if some of the example code is wrong or incomplete?
Your client and server are codes are exchanging plain text messages, so if you don't see that plain text in the TCP packets then the messages are likely being encrypted (which they should be, given the code shown).
To verify, you can filter the Wireshark capture on the two IP/Port pairs of the connection, then decode that TCP stream as TLS, and see if that succeeds. If so, it will show the first few packets of the connection (after the TCP 3-way handshake) are an unencrypted TLS handshake (exchanging the certificates and negotiating the encryption values), and the subsequent packets are encrypted TLS packets.
Having an issue with my input/output streams. Connecting a client to a server via SSL, and trying to send a message from the client to server.
However, when I write to my outputstream, nothing is read on the other end.
note - I am running my buffer in a separate thread called sendReceive, so that it does not block the main application while waiting for input. I pass it an input of SSLSocket, and it then establishes the corresponding streams/buffers. I'm not sure if this is where the issue lies in itself.
Here's the relevant part of my server.
static void initializeCLAConnection(){
try {
SSLServerSocketFactory sslserversocketfactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslserversocket =
(SSLServerSocket) sslserversocketfactory.createServerSocket(3577);
SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();
System.out.println("Connection accepted from: "+sslserversocket.getInetAddress());
//initialize buffer thread
sendReceive CLABuf = new sendReceive(sslsocket);
System.out.println("CLABuf established.");
CLABuf.start();
When CLABuf.start() is called, it runs the following thread. Here, it never reaches the print statement "Receiving input", regardless of how many times I write to the stream.
public class sendReceive extends Thread{
InputStream inputstream;
InputStreamReader inputstreamreader;
BufferedReader bufferedreader;
OutputStream outputstream;
OutputStreamWriter outputstreamwriter;
BufferedWriter bufferedwriter;
public sendReceive(SSLSocket socket) throws IOException{
inputstream = socket.getInputStream();
inputstreamreader = new InputStreamReader(inputstream);
bufferedreader = new BufferedReader(inputstreamreader);
outputstream = socket.getOutputStream();
outputstreamwriter = new OutputStreamWriter(outputstream);
bufferedwriter = new BufferedWriter(outputstreamwriter);
System.out.println("CLA Buf established in new thread");
}
#Override
public void run() {
//listen to inputstream
String string=null;
while(this.isAlive()){
System.out.println("Buf running");
try {
while((string=this.bufferedreader.readLine())!=null){
System.out.println("Thread receiving input!");
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
and the relevant part of my client sending the msg.
public void initializeVoterToCLA(){
try {
/*
* socket for Voter -> CLA
*/
SSLSocketFactory sslsocketfactoryCLA = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocketCLA = (SSLSocket) sslsocketfactoryCLA.createSocket("localhost", 3577);
InputStream inputstreamVoter = sslsocketCLA.getInputStream();
InputStreamReader inputstreamreaderVoter = new InputStreamReader(inputstreamVoter);
BufferedReader bufferedreaderVoter = new BufferedReader(inputstreamreaderVoter);
OutputStream outputstreamCLA = sslsocketCLA.getOutputStream();
OutputStreamWriter outputstreamwriterCLA = new OutputStreamWriter(outputstreamCLA);
BufferedWriter bufferedwriterCLA = new BufferedWriter(outputstreamwriterCLA);
//send msg
bufferedwriterCLA.write("test msg");
You're reading lines but you're not writing lines. Add a line terminator.
Nothing to do with SSL.
NB Testing this.isAlive() is futile. If it was false, the code that tests it wouldn't be running. This outer loop is completely pointless. Once the inner loop exits, there is nothing more to read. Just remove the outer loop.
I have a SSLServerSocket in Java, when a client is connected, I create a thread for its communication:
System.setProperty("javax.net.ssl.keyStore", "keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
SSLServerSocket server = (SSLServerSocket)null;
if(ipSocket == null){
ipSocket = new HashMap<String,java.net.Socket>();
}
try {
SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
server = (SSLServerSocket) sslserversocketfactory.createServerSocket(4380);
log.info("Server started");
} catch(IOException e) {
e.printStackTrace();
}
while(true){
try {
SSLSocket client = (SSLSocket) server.accept();
log.info("new client");
} catch (Exception e){
e.printStackTrace();
}
}
The problem is when the code sometimes rejects connections. It happens when the code is running for a while, so I think the problem is the clients lost the connection and reconect, but the previous thread is still alive, and there is a maximun SSLServerSockets.
Could this happen? What number is the maximum?
How can I kill the threads when a disconnection happens?
Based on your code and my understanding of networking (both from the lower level and from the API level) you may be incorrectly using the API.
At a high level, you want to do this a little differently
public static void main(String[] args) {
System.setProperty("javax.net.ssl.keyStore", "keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
SSLServerSocket server = (SSLServerSocket)null;
if(ipSocket == null){
ipSocket = new HashMap<String,java.net.Socket>();
}
try {
SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
// Creates a socket with a default backlog of 50 - meaning
// There will be a maximum of 50 client connection attempts on this
// socket after-which connections will be refused. If the server is
// overwhelmed by more than that number of requests before they can be
// accepted, they will be refused
// The API allows for you to speccify a backlog.
server = (SSLServerSocket) sslserversocketfactory.createServerSocket(4380);
log.info("Server started");
} catch(IOException e) {
e.printStackTrace();
}
while(true){
try {
// This will take one of the waiting connections
SSLSocket client = (SSLSocket) server.accept();
log.info("new client");
// HERE is where you should create a thread to execute the
// conversation with the client.
} catch (Exception e){
e.printStackTrace();
}
}
}
I hope that more correctly answers your question.
In regards to the comment by EJP - I have updated my explanation and cited the documentation located here:
The maximum queue length for incoming connection indications (a request to connect) is set to the backlog parameter. If a connection indication arrives when the queue is full, the connection is refused.
I'm currently working on a tiny individual project for this semester with Android. What I'm going to do is making lots of connections to my https server with my Android phone so the server goes down. I know absolutely nothing about programming because I'm studying networking not computer language. But I somehow collected from here and there piece by piece and made a code like below. I think it's using a socket connection.
import java.net.*;
import java.io.*;
import java.security.*;
import javax.net.ssl.*;
public class HTTPSClient {
public static void main(String[] args) {
System.out.println("Usage: java HTTPSClient host");
int port = 443; // default https port
String host = "192.168.0.8";
TrustManager[] trustAll = new javax.net.ssl.TrustManager[]{
new javax.net.ssl.X509TrustManager(){
public java.security.cert.X509Certificate[] getAcceptedIssuers(){
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs,String authType){}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs,String authType){}
}
};
try {
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAll, new java.security.SecureRandom());
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
SSLSocketFactory factory = (SSLSocketFactory) sc.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
Writer out = new OutputStreamWriter(socket.getOutputStream());
out.write("GET / HTTP/1.0\\r\\n");
out.write("\\r\\n");
out.flush();
// read response
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
int c;
while ((c = in.read()) != -1) {
System.out.write(c);
}
// out.close();
// in.close();
// socket.close();
} catch (Exception e) {
System.err.println(e);
}
}
}
I enabled https on my macbook and I can see the port 443 listening. When I execute the code above I can see one established connection through 'netstat -an | grep 443' until I stop it. My question is this: if I want to make multiple connection with this code, what should I add on? Is it possible with this code? My idea is that if I can see heaps of established connections to 443 port on my macbook, I will not be able to connect https:://localhost with a browser because the machine is down. I don't know if it's correct but I hope. Because the semester is almost over and I anyway have to make something to report.
I'm not sure if that code will be the same when I make the code for Android phone but I just want to see something happening first. I'm really desperate, please help me. Thank you very much.
From what I can understand, you are trying to have multiple clients(phones) connect to your server.
Your server looks solid. You should be able to modify it to handle multiple clients easily.
Generally you need a handler of some sort to process incoming client connections. You will need a loop to wait for new connections, and then a thread to handle each connection independently. Each instance of a socket can only handle one connection. A socket factory allows you to bind more than once instance of a socket to the server. I have two classes to handle multiple connections. My first class is the server itself and the second is a a thread to handle each client.
If you are not familiar with threading, you should check into it.
This is the server class:
public class ServerThread extends Thread
{
private Vector<ClientHandlerThread> connectedClients = new Vector<ClientHandlerThread>(20, 5);
public void run()
{
SSLServerSocket sslDataTraffic = null;
SSLServerSocket sslFileTraffic = null;
SSLServerSocketFactory sslFac = null;
try
{
System.out.print("Validating SSL certificate... ");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(certificateDir), password);
System.out.println("DONE.");
System.out.print("Creating trust engine........ ");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
System.out.println("DONE.");
System.out.print("Creating key engine.......... ");
KeyManagerFactory kmf = KeyManagerFactory.getInstance((KeyManagerFactory.getDefaultAlgorithm()));
kmf.init(keyStore, password);
System.out.println("DONE.");
System.out.print("Creating SSL context......... ");
System.setProperty("https.protocols", "SSL");
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
sslFac = ctx.getServerSocketFactory();
System.out.println("DONE.");
}
catch (Exception e) {}
try
{
System.out.print("Creating data socket......... ");
sslDataTraffic = (SSLServerSocket) sslFac.createServerSocket(dataPort);
System.out.println("DONE. Est. on:" + dataPort);
}
catch (IOException e)
{
System.out.println("FAILED.");
System.out.println(e.toString() + " ::: " + e.getCause());
System.exit(-1);
}
try
{
System.out.print("Creating file socket......... ");
sslFileTraffic = (SSLServerSocket) sslFac.createServerSocket(filePort);
System.out.println("DONE. Est. on:" + filePort);
}
catch (IOException e)
{
System.out.println("FAILED.");
System.out.println(e.toString() + " ::: " + e.getCause());
System.exit(-1);
}
while (running)
{
SSLSocket sslDataTrafficSocketInstance = (SSLSocket) sslDataTraffic.accept();
SSLSocket sslFileTrafficSocketInstance = (SSLSocket) sslFileTraffic.accept();
ClientHandlerThread c = new ClientHandlerThread(sslDataTrafficSocketInstance, sslFileTrafficSocketInstance);
c.start();
connectedClients.add(c);
}
}
Notice the while loop at the end of the class. It will wait until a client connects (which invokes the accept() method). An independent thread is created to handle that client (phone).
The client thread is as follows:
public class ClientHandlerThread extends Thread
{
private boolean running = true;
private SSLSocket dataSocket;
private SSLSocket fileSocket;
private PrintWriter writer;
private BufferedReader reader;
private InputStream inputStream;
private OutputStream outputStream;
public ClientHandlerThread(
SSLSocket dataSocket,
SSLSocket fileSocket)
{
this.dataSocket = dataSocket;
this.fileSocket = fileSocket;
try
{
this.reader = new BufferedReader(new InputStreamReader(this.dataSocket.getInputStream()));
this.writer = new PrintWriter(this.dataSocket.getOutputStream());
this.inputStream = fileSocket.getInputStream();
this.outputStream = fileSocket.getOutputStream();
}
catch (IOException e)
{
e.printStackTrace();
}
this.ip = this.dataSocket.getInetAddress().getHostAddress();
}
public void run()
{
try
{
writer.println("SERVER_HANDSHAKE_INIT");
writer.flush();
String fromClient;
while (running && (fromClient = reader.readLine()) != null)
{
if (fromClient.equals("CLIENT_HANDSHAKE_INIT"))
System.out.println("Client Connected: " + getIP());
}
}
catch (IOException e)
{
e.getCause();
}
}
public String getIP()
{
return ip;
}
public boolean isRunning()
{
return running;
}
public void setRunning(boolean running)
{
this.running = running;
}
}
You now have the ability to iterate through each client thread held within the Vector containing all clients. This will allow you to handle multiple clients and interact with each of them independently. This includes reading input/output streams.
These classes are stripped down versions of the ones I use for a simple remote management system I developed over the summer. You should be able to modify them as necessary to meet your needs. You could add a parameter to the client thread constructor to keep track of naming for example.
I hope this explained how to handle multiple incoming connections to a server.
Feel free to DM or email me for additional info.
Cheers
You could change your code to open connections in a loop:
int numConnections = 100;
for (int i=0; i<numConnections; i++) {
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
Writer out = new OutputStreamWriter(socket.getOutputStream());
out.write("GET / HTTP/1.0\\r\\n");
out.write("\\r\\n");
out.flush();
// read response
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
int c;
while ((c = in.read()) != -1) {
System.out.write(c);
}
// out.close();
// in.close();
// socket.close();
}
I highly suggest retaining the socket objects in an array or collection variable and closing the I/O streams and socket when you are done, but this will also be done when main() exits - just know this is generally bad practice in programming if you were to want to reuse this code in a situation where the whole program didn't exit after the block of code that opens connection(s).
I am using TCP/IP sockets to create a client and server applicaton. Originally I was using regular sockets but now I have decided to use SSL for my connection. I have created a keystore and have tried running my application but it has yet to be successful.
Here is my code for the server
public class ArFileServer {
public static void main(String[] args)
{
boolean listening = true;
ServerSocketFactory serversocketfactory;
ServerSocket serverSocket;
try
{
//serverSocket = new ServerSocket(4445);
serversocketfactory = SSLServerSocketFactory.getDefault();
serverSocket = serversocketfactory.createServerSocket(4445);
String keystore = System.getProperty("javax.net.ssl.trustStore");
System.out.println(keystore);
// infinite loop to continually listen for connection requests made by clients
while (listening)
{
new ClientConnection(serverSocket.accept()).start();
if (serverSocket != null)
{
System.out.println("Connection to client established");
}
}
serverSocket.close();
}
catch (IOException e)
{
System.out.println("Error could not create socket connection to port, check that port is not busy");
}
}
}
and here is the client code:
public class ClientSocket
{
SocketFactory socketfactory = null;
Socket clientSocket = null;
PrintWriter out = null;
BufferedReader in = null;
// establish a connection to All Care's server application through socket 4444 (adjust localhost to reflect the IP address that the server
// is being run from)
public ClientSocket()
{
try
{
//clientSocket = new Socket("localhost", 4445);
//SocketFactory socketfactory = SSLSocketFactory.getDefault();
clientSocket = socketfactory.createSocket("192.168.1.8", 4445);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String truststore = System.getProperty("javax.net.ssl.trustStore");
System.out.println(truststore);
}
catch (IOException e)
{
System.out.println("Could not connect to All Care Server Application : " + e.getMessage());
}
}
}
I am also using these runtime arguments:
-Djavax.net.ssl.keyStore=C:\Users\Chris\Documents\NetBeansProjects\ArFile\keystore.jks -Djavax.net.ssl.keyStorePassword=password
When I try to print out the truststore it always returns null, what am I doing wrong?
When I try to print out the truststore it always returns null
Because you never set it. All you are doing is printing out the value of a system property. If you didn't set it, it is null.
what am I doing wrong?
Nothing yet, except printing out meaningless information. But much of your code doesn't make sense:
if (serverSocket != null)
{
System.out.println("Connection to client established");
}
serverSocket being non-null (a) is inevitable at this point, and (b) doesn't have anything do with the client socket being established, which is inevitable at this point.
catch (IOException e)
{
System.out.println("Error could not create socket connection to port, check that port is not busy");
}
An IOException at this point could mean many things, but the one thing it doesn't mean is 'cannot create socket connection to port'. It is the client that does the connecting: the server accepts connections. When you catch an exception, always print its message, don't just make up your own.
You need to define both trustStore and keyStore in runtime arguments:
-Djavax.net.ssl.keyStore=xxx.ks
-Djavax.net.ssl.keyStorePassword=yyy
-Djavax.net.ssl.trustStore=xxx.ks
-Djavax.net.ssl.trustStorePassword=yyy
Both can be same file.
trustStore contains public keys of others.
keyStore contains own keys and certificates.