import java.io.*; import java.net.*; import com.sun.net.ssl.KeyManagerFactory; import com.sun.net.ssl.KeyManager; import com.sun.net.ssl.TrustManagerFactory; import com.sun.net.ssl.TrustManager; import com.sun.net.ssl.SSLContext; import javax.net.ServerSocketFactory; import java.security.KeyStore; public class svr implements Runnable{ public staticfinalint PORT =5555; public staticfinal String HOST =" localhost" ; public staticfinal String QUESTION ="Knock, knock."; public staticfinal String ANSWER =" Who's there?" ; // The new constants that are used during setup. publicstaticfinal String KEYSTORE_FILE = "mycerts";// "server_keystore"; publicstaticfinal String ALGORITHM = "sunx509"; public staticfinal String PASSWORD ="churchillobjects"; public staticvoid main(String[] args){ new Thread(new svr()).start(); } public void run(){ ServerSocket ss = null; try{ // Local references used for clarity. Their presence // here is part of the reason we need to import // so many classes. KeyManagerFactory kmf; KeyManager[] km; KeyStore ks; TrustManagerFactory tmf; TrustManager[] tm; SSLContext sslc; // Create a keystore that will read the JKS (Java KeyStore) // file format which was created by the keytool utility. ks = KeyStore.getInstance( "JKS"); // Load the keystore object with the binary keystore file and // a byte array representing its password. ks.load( new FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray()); // Gives us a factory for key managers that will let // us handle the asymetric keys we created earlier. kmf = KeyManagerFactory.getInstance(ALGORITHM); // Initialize the key manager factory with the keystore object, // again using the same password for security since it is going to // access the private key. kmf.init(ks, PASSWORD.toCharArray()); // Now we can get the key managers from the factory, since it knows // what type we are using now. km = kmf.getKeyManagers(); // Next, create a trust manager factory using the same algorithm. // This is to avoid using the certificates in cacerts that // represent an authentication security risk. tmf = TrustManagerFactory.getInstance(ALGORITHM); //then initialize it with the keystore object. This time we don't // need the keystore password. This is because trusted certificates // are not a sensitive element in the keystore, unlike the // private keys. tmf.init(ks); // Once that's initialized, get the trust managers from the factory. tm = tmf.getTrustManagers(); // Almost done, we need a context object that will get our // server socket factory. We specify TLS to indicate that we will // need a server socket factory that supports SSL. sslc = SSLContext.getInstance( "TLS"); // Initialize the context object with the key managers and trust // managers we got earlier. The third parameter is an optional // SecureRandom object. By passing in null, we are letting the // context object create its own. sslc.init(km, tm, null); // Finally, we get the ordinary-looking server socket factory // from the context object. ServerSocketFactory ssf = sslc.getServerSocketFactory(); // From the factory, we simply ask for an ordinary-looking // server socket on the port we wish. ss = ssf.createServerSocket(PORT); listen(ss); } catch(Exception e){ e.printStackTrace(); } finally{ if(ss !=null){ try{ ss.close(); } catch(IOException e){ // oh, well } } System.exit(0); } } static void listen(ServerSocket ss) throws Exception{ System.out.println("Ready for connections."); while( true){ Socket s = ss.accept(); BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(s.getOutputStream())); BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream())); String q = br.readLine(); if( !QUESTION.equals(q)){ throw new RuntimeException( "Wrong question: / "" + q + "/""); } System.out.println("Question: /"" + q + "/""); bw.write(ANSWER+" /n"); bw.flush(); s.close(); } } }
CLI端程序:
import java.io.*; import java.net.*; import com.sun.net.ssl.KeyManagerFactory; import com.sun.net.ssl.TrustManagerFactory; import com.sun.net.ssl.SSLContext; import java.security.KeyStore; import javax.net.SocketFactory; public class cli implements Runnable{ public staticfinalint PORT =5555; public staticfinal String HOST =" localhost" ; public staticfinal String KEYSTORE_FILE ="clikeystore";// "client_keystore"; publicstaticfinal String ALGORITHM = "sunx509"; public staticfinal String PASSWORD ="churchillobjects"; public staticfinal String QUESTION ="Knock, knock."; public staticfinal String ANSWER =" Who's there?" ; public staticvoid main(String[] args){ new Thread(new cli()).start(); } public void run(){ Socket socket = null; try{ KeyManagerFactory kmf; KeyStore ks; TrustManagerFactory tmf; SSLContext sslc; kmf = KeyManagerFactory.getInstance(ALGORITHM); ks = KeyStore.getInstance( "JKS " ); ks.load(new FileInputStream(KEYSTORE_FILE), PASSWORD.toCharArray()); kmf.init(ks, PASSWORD.toCharArray()); tmf = TrustManagerFactory.getInstance(ALGORITHM); tmf.init(ks); sslc = SSLContext.getInstance("TLS "); sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); // The process is different from here on the client. Instead of // getting a ServerSocketFactory, we ask for a SocketFactory from // the SSL context. SocketFactory sf = sslc.getSocketFactory(); // Then we get the socket from the factory and treat it // as if it were a standard (plain) socket. socket = sf.createSocket(HOST, PORT); doQuery(socket); } catch(Exception e){ e.printStackTrace(); } finally{ if(socket !=null){ try{ socket.close(); } catch(IOException e){ // oh, well } } System.exit(0); } } private void doQuery(Socket s) throws Exception{ BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(s.getOutputStream())); BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream())); bw.write(QUESTION+" /n"); bw.flush(); String response = br.readLine(); if( !ANSWER.equals(response)){ throw new RuntimeException( "Wrong answer: / "" + response + "/""); } System.out.println("Got the right answer: /"" + response + "/ ""); } }