benedekh / WeLoveClouds

Repository for submissions on the CloudDB course.
0 stars 1 forks source link

Secure Socket hints #203

Closed benedekh closed 7 years ago

benedekh commented 7 years ago

I did some experiments for pure SSLSocket and SSLServerSocket classes. Here is a working demo. Just simply copy-paste the code into a class, and run that class with JUnit (as a unit test).

 @Test
    public void test() throws Exception {
        // path & password for the keystore
        String path = "E://keystore.jks";
        char[] passphrase = "fsesdfsdf".toCharArray();

        // load keystore
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream(path), passphrase);

        // initialize key manager
        KeyManagerFactory kmf =
                KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, passphrase);

        // we sign the key ourselves
        TrustManagerFactory tmf =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);

        // create the socket factories
        SSLContext ctx = SSLContext.getInstance("SSL");
        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        final SSLSocketFactory sslFactory = ctx.getSocketFactory();
        final SSLServerSocketFactory sslServerFactory = ctx.getServerSocketFactory();

        new Thread() {
            public void run() {
                try {
                    ServerSocket serverSocket = sslServerFactory.createServerSocket(8080);
                    Socket socket = serverSocket.accept();
                    byte[] response = new byte[256];
                    socket.getInputStream().read(response);
                    System.out.println(response[0]);
                    socket.close();
                    serverSocket.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }.start();

        new Thread() {
            public void run() {
                try {
                    Socket socket = sslFactory.createSocket("localhost", 8080);
                    socket.getOutputStream().write(new byte[] {42});
                    socket.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }.start();

        synchronized (this) {
            this.wait();
        }
    }

Don't forget to replace E://keystore.jks with a valid path to your keystore. In order to create a keystore, download Putty which contains keytool.

In command-line run keytool -genkey -keystore keystore.jks -keyalg RSA. When it asks for the keystore's password type fsesdfsdf. When it asks for 'demographical details', just leave the field empty (press return). When it asks to confirm the details type yes. Finally just press return because we would like to use the same password for <mykey> as we did for the keystore. The keystore.jks file is created in the folder the keytool ran.

ghost commented 7 years ago

Got any tips for extending builder pattern classes, specifically with regards to extending the inner static builder class? I've implemented a solution using something called "Curiously recurring generics pattern", I want to know if you think there's a better way.

benedekh commented 7 years ago

That's the only way I know so far.

2016-12-29 21:49 GMT+01:00 RMIT-s3529366-Hunton-Bowland:

Got any tips for extending builder pattern classes, specifically with regards to extending the inner static builder class? I've implemented a solution using something called "Curiously recurring generics pattern", I want to know if you think there's a better way.

ghost commented 7 years ago

How and where would you recommend

I've was trying to work out a good solution for this yesterday and couldn't come up with anything. I don't think it should go in SocketFactory.java but I need the SSLSocketFactory in there. Perhaps just make everything key/certificate related happen weloveclouds.client.core.Client.java? Furthermore; are the client and server going to share the same key/certificate or should I make separate ones? Thanks for answering all of my questions!

benedekh commented 7 years ago

It is up to you, the less duplicate is, better the solution is. Note that the client and server are going to share the same key/certificate, otherwise they would not understand each other.

2016-12-30 7:56 GMT+01:00 RMIT-s3529366-Hunton-Bowland:

How and where would you recommend

  • loading the keystore
  • Initializing the key manager
  • Signing the key
  • Creating and initializing the ssl context. I've was trying to work out a good solution for this yesterday and couldn't come up with anything. I don't think it should go in SocketFactory.java but I need the SSLSocketFactory in there. Perhaps just make everything key/certificate related happen weloveclouds.client.core. Client.java? Furthermore; are the client and server going to share the same key/certificate or should I make separate ones? Thanks for answering all of my questions!
ghost commented 7 years ago

screenshot from 2017-01-06 17-35-53 Hey Guys, I've run into this problem with dependency injection, to the best of my knowledge I haven't changed anything that would affect the serializer, de-serializer or anything in the ECS. (The exception being parts of the communication package). Any tips on how to fix this?

Also; I've been looking into implementing SSL sockets on the server, ecs and loadbalancer. I'll definitely need some help with this part as I'm not quite sure where I should be making changes, I was under the impression that I'd only have to modify the concurrent communication service but it appears that the run methods on a number of services deal with sockets. Should I perhaps be editing the Abstract classes in the commons networking packages?

benedekh commented 7 years ago

ServerSockets are always in the weloveclouds.commons.networking.AbstractServer class. You shall replace the ServerSocket field there.

As I know, the ConcurrentCommunicationService does not create any connections, it just reuses them. So don't change that class, because it doesn't need to know if a Connection is a secure/raw one. Instead, try to find those places in the code, where the ConnectionFactory.createConnectionFrom() method is called, or the Connection.Builder.build() method is called. The former one is a potentional place which have to be replaced according to the next paragraph; the latter one is just a possible place for a not-so-secure connection. Former ones have to be replaced, latter ones need to be listed at least to know where to scrutine.

Regarding the CommunicationService, the only row you have to change is this: connectionToEndpoint = connectionFactory.createConnectionFrom(remoteServer); where instead of this, you have to create a secure connection: connectionToEndpoint = connectionFactory.createSecureConnectionFrom(remoteServer); (if that method is the one which puts a SSLSocket instead of a normal Socket into the connection).

ghost commented 7 years ago

I've made those changes. My problem now is the screen shot further up the thread. I don't know how to fix that or what to search for, as the problem seems specific to our case.

benedekh commented 7 years ago

Don't know either. Maybe @banctilrobitaille can help. But if you're ready, then I'll do some tests to see if we use secure sockets everywhere. (Please have a look at 2nd paragraph in the previous comment that I had just changed.)

ghost commented 7 years ago

No problem, feel free to write the tests.

banctilrobitaille commented 7 years ago

Hello folks, this guice issue is fixed in the latest PR merging my branch with the ms5 intitial commit. This is due to the fact that no serializer is binded for the ECSNotiricationMessage. You can take a look at this file : weloveclouds/commons/serialization/configuration/modules/SerializationModule.java in the PR #220