Java TLS Practice

Introduction

記錄 Java 使用 SSL 的方法 (不要求 client auth)

Reference

Prepare jks files

  1. Install openssl in Ubuntu
    sudo apt-get install openssl
  2. Execute following commands one by one
    openssl req -x509 -newkey rsa:1024 -keyout private/cakey.pem -out private/cacert.pem -days 3650
    openssl x509 -in private/cacert.pem -addtrust clientAuth -setalias "Isaac Test Class 1 CA" -out public/catrust.pem
    keytool -importcert -trustcacerts -noprompt -file private/cacert.pem -alias ca -keystore public/catrust.jks -storepass 123456
    keytool -genkeypair -keyalg RSA -keysize 1024 -validity 730 -keystore public/server.jks
    keytool -certreq -file server-req.pem -keystore public/server.jks
    openssl x509 -req -in server-req.pem -out public/server-cert.pem -CA private/cacert.pem -CAkey private/cakey.pem -extensions v3_usr -days 730 -CAserial private/cacert.srl -CAcreateserial
    cat private/cacert.pem >> public/server-cert.pem
    keytool -importcert -v -file public/server-cert.pem -keystore public/server.jks
    rm server-req.pem
  3. There are public/server.jks and public/catrust.jks

Run server code

public class ServerDontNeedClientAuth {

    private static String SERVER_KEY_STORE = Paths.get("src/main/resources/certs/server.jks").toAbsolutePath().toString();
    private static String SERVER_KEY_STORE_PASSWORD = "123456";

    public static void main(String[] params) throws Exception {
//        System.setProperty("javax.net.debug", "ssl,handshake");
        System.setProperty("javax.net.ssl.trustStore", SERVER_KEY_STORE);
        SSLContext context = SSLContext.getInstance("TLS");
        KeyStore ks = KeyStore.getInstance("jceks");
        ks.load(new FileInputStream(SERVER_KEY_STORE), null);
        KeyManagerFactory kf = KeyManagerFactory.getInstance("SunX509");
        kf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray());
        context.init(kf.getKeyManagers(), null, null);

        ServerSocketFactory factory = context.getServerSocketFactory();
        ServerSocket serverSocket = factory.createServerSocket(8443);
        SSLServerSocket sslServerSocket =  (SSLServerSocket) serverSocket;
        sslServerSocket.setNeedClientAuth(false);
        while(true){
            try{
                System.out.println("listen port 8443..");
                Socket socket = sslServerSocket.accept();
                System.out.println("accept:" + socket);
                InputStream is = socket.getInputStream();
                BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
                String readLine = buffer.readLine();
                System.out.println("server receive:" + readLine);
                socket.getOutputStream().write("1234567890".getBytes());
                socket.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

}

Run client code

public class ClientWithoutAuth {

    private static String CLIENT_KEY_STORE = Paths.get("src/main/resources/certs/catrust.jks").toAbsolutePath().toString();

    public static void main(String[] params) throws Exception {
        System.setProperty("javax.net.ssl.trustStore", CLIENT_KEY_STORE);
        SocketFactory sf = SSLSocketFactory.getDefault();
        Socket s = sf.createSocket("localhost", 8443);
        PrintWriter writer = new PrintWriter(s.getOutputStream());
        BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
        writer.println("hello\n");
        writer.flush();
        System.out.println("client receive:" + reader.readLine());
        s.close();
    }

}

Server output

listen port 8443..
accept:340f438e[SSL_NULL_WITH_NULL_NULL: Socket[addr=/127.0.0.1,port=50429,localport=8443]]
server receive:hello
listen port 8443..

Client output

1234567890

別名演算法 Alias Method

 題目 每個伺服器支援不同的 TPM (transaction per minute) 當 request 來的時候, 系統需要馬上根據 TPM 的能力隨機找到一個適合的 server. 雖然稱為 "隨機", 但還是需要有 TPM 作為權重. 解法 別名演算法...