PlainServer.java that doesn’t verify client

Posted on December 27, 2019. Filed under: CCNA |


In previous example, we have a client and server pair that do mutual certification. I saw some comments and questions in stack overflow about this setup. In many situations, server don’t care about the client side is legitimate or not, server can skip verifying the client’s public key.

  • step 1. Create self-signed server and client certificates with keytool.
  • step 2. create server java code.
  • step 3. create client java code.
SSLDemo #mkdir ssldemo
SSLDemo #cd ssldemo/
SSLDemo #echo "Generate the Client and Server Keystores" > /dev/null
SSLDemo #keytool -genkeypair -alias plainserverkeys -keyalg RSA -dname "CN=Plain Server,OU=kl2217,O=kl2217org,L=Boston,ST=MA,C=US" -keypass password -keystore plainserver.jks -storepass password
SSLDemo #keytool -genkeypair -alias plainclientkeys -keyalg RSA -dname "CN=Plain Client,OU=kl2217,O=kl2217org,L=Boston,ST=MA,C=US" -keypass password -keystore plainclient.jks -storepass password
SSLDemo #echo "Export the server public certificate and create a seperate keystore">/dev/null
SSLDemo #keytool -exportcert -alias plainserverkeys -file serverpub.cer -keystore plainserver.jks -storepass password
Certificate stored in file
SSLDemo #keytool -importcert -keystore serverpub.jks -alias serverpub -file serverpub.cer -storepass password
Owner: CN=Plain Server, OU=kl2217, O=kl2217org, L=Boston, ST=MA, C=US
Issuer: CN=Plain Server, OU=kl2217, O=kl2217org, L=Boston, ST=MA, C=US
Serial number: 23430928
Valid from: Fri Dec 27 11:48:10 EST 2019 until: Thu Mar 26 12:48:10 EDT 2020
Certificate fingerprints:
	 MD5:  41:CB:3E:75:BC:74:45:3F:09:E2:43:82:99:DD:60:62
	 SHA1: DF:96:E4:A2:CF:70:17:AE:85:71:E3:94:F7:4E:95:00:4A:B1:C4:E1
	 SHA256: A7:4E:45:65:C5:6F:8E:38:91:F5:04:39:0F:F8:6A:98:CA:E4:F9:19:1E:66:F9:FB:B5:DD:52:90:9A:12:C4:97
	 Signature algorithm name: SHA256withRSA
	 Version: 3

Extensions: 

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 2E 36 E1 D0 AF CF 28 4D   41 1D DC 64 27 8A 44 98  .6....(MA..d'.D.
0010: F6 61 35 CB                                        .a5.
]
]

Trust this certificate? [no]:  yes
Certificate was added to keystore
SSLDemo #ls
plainclient.jks	plainserver.jks	serverpub.cer	serverpub.jks
SSLDemo #vi PlainServer.java
SSLDemo #vi PlainClient.java
SSLDemo #cat PlainClient.java
import java.io.*;
import java.security.*;
import javax.net.ssl.*;

public class PlainClient {
    public static void main(String[] args) {
        SSLSocket socket = null;
        BufferedReader in = null;
        try {
            // load client private key
            KeyStore clientKeys = KeyStore.getInstance("JKS");
            clientKeys.load(new FileInputStream("plainclient.jks"),
                    "password".toCharArray());   //a jks containing any valid private key will work
            KeyManagerFactory clientKeyManager = KeyManagerFactory
                    .getInstance("SunX509");
            clientKeyManager.init(clientKeys, "password".toCharArray());
            // load server public key
            KeyStore serverPub = KeyStore.getInstance("JKS");
            serverPub.load(new FileInputStream("serverpub.jks"),
                    "password".toCharArray());
            TrustManagerFactory trustManager = TrustManagerFactory
                    .getInstance("SunX509");
            trustManager.init(serverPub);
            // use keys to create SSLSoket
            SSLContext ssl = SSLContext.getInstance("TLS");
            ssl.init(clientKeyManager.getKeyManagers(),
                    trustManager.getTrustManagers(),
                    SecureRandom.getInstance("SHA1PRNG"));
            socket = (SSLSocket) ssl.getSocketFactory().createSocket(
                    "localhost", 8889);
            socket.startHandshake();
            // receive data
            in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            String data;
            while ((data = in.readLine()) != null) {
                System.out.println(data);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null)
                    in.close();
                if (socket != null)
                    socket.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
SSLDemo #
SSLDemo #cat PlainServer.java
import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.*;

public class PlainServer {
    public static void main(String[] args) {
        SSLServerSocket serverSock = null;
        SSLSocket socket = null;
        PrintWriter out = null;
        try {
            // load server private key
            KeyStore serverKeys = KeyStore.getInstance("JKS");
            serverKeys.load(new FileInputStream(
                    "plainserver.jks"), "password"
                    .toCharArray());
            KeyManagerFactory serverKeyManager = KeyManagerFactory
                    .getInstance("SunX509");
            // System.out.println(KeyManagerFactory.getDefaultAlgorithm());
            // System.out.println(serverKeyManager.getProvider());
            serverKeyManager.init(serverKeys, "password".toCharArray());
            // load client public key is not needed

            TrustManager[] trustManagers = new X509TrustManager[] { new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain,
                        String authType) throws CertificateException {
                }

                public void checkServerTrusted(X509Certificate[] chain,
                        String authType) throws CertificateException {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            } };

            // use keys to create SSLSoket
            SSLContext ssl = SSLContext.getInstance("TLS");

            ssl.init(serverKeyManager.getKeyManagers(), trustManagers,
                    SecureRandom.getInstance("SHA1PRNG"));
            serverSock = (SSLServerSocket) ssl.getServerSocketFactory()
                    .createServerSocket(8889);
            serverSock.setNeedClientAuth(true);
            socket = (SSLSocket) serverSock.accept();
            // send data
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                    socket.getOutputStream())));
            out.println("data from PlainServer");
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("exit");
            if (out != null)
                out.close();
            try {
                if (serverSock != null)
                    serverSock.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
SSLDemo #
SSLDemo #
SSLDemo #javac PlainServer.java PlainClient.java
SSLDemo #java PlainServer &
[1] 4227
SSLDemo #java PlainClient
exit
data from PlainServer
[1]+  Done                    java PlainServer
SSLDemo #

Make a Comment

Leave a comment

One Response to “PlainServer.java that doesn’t verify client”

RSS Feed for IT Security Comments RSS Feed

in case bad serverpub.jks is supplied by PlainClient.java, the exception will be:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:957)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:892)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
at misc.PlainClient.main(PlainClient.java:33)
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:384)
at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:133)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)
… 8 more


Where's The Comment Form?

Liked it here?
Why not try sites on the blogroll...