TLS客户端服务器通信

时间:2014-11-15 21:28:10

标签: java multithreading security sockets ssl

我想构建TLS多线程客户端/服务器聊天应用程序,我能够使用ServerSocket构建简单的客户端服务器,但我在使用TLS时遇到问题:

  1. 首先,没有TLS客户端/服务器的分步指南
  2. 沟通我能找到的只有几个问题答案 stack-overflow我尝试使用那些但失败了SSL Socket connection
  3. 我得到的错误来自服务器端:

      

    收听[SSL:ServerSocket [addr = 0.0.0.0 / 0.0.0.0,localport = 786]]   来自21a947fe的连接[SSL_NULL_WITH_NULL_NULL:   插座[ADDR = / 127.0.0.1,端口= 39264,将localPort = 786]]   javax.net.ssl.SSLHandshakeException:没有共同的密码套件   sun.security.ssl.Alerts.getSSLException(Alerts.java:192)at   sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1917)at at   sun.security.ssl.Handshaker.fatalSE(Handshaker.java:301)at   sun.security.ssl.Handshaker.fatalSE(Handshaker.java:291)at   sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:1007)     在   sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:724)     在   sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:213)     在sun.security.ssl.Handshaker.processLoop(Handshaker.java:925)at at   sun.security.ssl.Handshaker.process_record(Handshaker.java:860)at   sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1043)at at   sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)     在   sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:909)

    在客户端:

      

    javax.net.ssl.SSLHandshakeException:收到致命警报:   handshake_failure

    这是我的服务器代码:

    public class Server {
    
    // The ServerSocket we'll use for accepting new connections 
    private SSLServerSocket server;
    private final SSLContext sc;
    private final Hashtable outputStreams;
    
    // Constructor and while-accept loop all in one. 
    public Server(int port) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
        this.outputStreams = new Hashtable();
        KeyStore ks = initKeyStore(KEYSTORE, "JKS", KEYSTORE_PASSWORD);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
    
        kmf.init(ks, KEYSTORE_PASSWORD.toCharArray());
    
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
        tmf.init(ks);
    
        this.sc = SSLContext.getInstance("TLS");
        TrustManager[] trustManagers = tmf.getTrustManagers();
        this.sc.init(kmf.getKeyManagers(), trustManagers, null);
        // All we have to do is listen 
        listen(port);
    }
    private static final String KEYSTORE = "serverkeystore";
    private static final String KEYSTORE_PASSWORD = "blackzero@server";
    
    private static KeyStore initKeyStore(String keyStore, String keyStoreType, String keyPass) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        KeyStore ks = null;
        try {
    
            ks = KeyStore.getInstance(keyStoreType);
            //ks.load(new FileInputStream(keyStore), keyPass.toCharArray());
            ks.load(null, keyPass.toCharArray());
        } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) {
            Logger.getLogger(CNS.class.getName()).
                    log(Level.SEVERE, null, e);
            //X509Certificate certificate = generateX509Certificate("CNS"); 
            ks = KeyStore.getInstance(keyStoreType);
            ks.load(null, keyPass.toCharArray());
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(2048);
            KeyPair kp = kpg.genKeyPair();
            Key publicKey = kp.getPublic();
            Key privateKey = kp.getPrivate();
            Certificate[] certChain = new Certificate[1];  
            certChain[0] = certificate;
            ks.setKeyEntry("key1", privateKey, KEYSTORE_PASSWORD.toCharArray(), certChain);
            try (FileOutputStream writeStream = new FileOutputStream(keyStore)) {
                ks.store(writeStream, keyPass.toCharArray());
            }
        }
        return ks;
    }
    
    private static X509Certificate generateX509Certificate(String certificateName) throws CertificateException, FileNotFoundException, IOException {
        InputStream inStream = null;
        X509Certificate cert = null;
        try {
            inStream = new FileInputStream(certificateName);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            cert = (X509Certificate) cf.generateCertificate(inStream);
        } finally {
            if (inStream != null) {
                inStream.close();
            }
        }
        return cert;
    }
    
    private void listen(int port) throws IOException {
        // Create the ServerSocket 
        SSLServerSocketFactory ssf = sc.getServerSocketFactory();
        server = (SSLServerSocket) ssf.createServerSocket(port);
    
        //server = new ServerSocket(port);
        // Tell the world we're ready to go 
        System.out.println("Listening on " + server);
        // Keep accepting connections forever 
        while (true) {
            // Grab the next incoming connection 
            SSLSocket s = (SSLSocket) server.accept();
            //Socket s = server.accept();
            // Tell the world we've got it 
            System.out.println("Connection from " + s);
            // Create a DataOutputStream for writing data to the 
            // other side 
            DataOutputStream dout = new DataOutputStream(s.getOutputStream());
            // Save this stream so we don't need to make it again 
            outputStreams.put(s, dout);
            // Create a new thread for this connection, and then forget // about it 
            new ServerThread(this, s);
        }
    }
    
    // Get an enumeration of all the OutputStreams, one for each client 
    // connected to us 
    Enumeration getOutputStreams() {
        return outputStreams.elements();
    }
    
    // Send a message to all clients (utility routine) 
    void sendToAll(String message) {
        // We synchronize on this because another thread might be 
        // calling removeConnection() and this would screw us up 
        // as we tried to walk through the list 
        synchronized (outputStreams) {
            // For each client ... 
            for (Enumeration e = getOutputStreams(); e.hasMoreElements();) {
                // ... get the output stream ... 
                DataOutputStream dout = (DataOutputStream) e.nextElement();
                // ... and send the message 
                try {
                    dout.writeUTF(message);
                } catch (IOException ie) {
                    System.out.println(ie);
                }
            }
        }
    }
    
    // Remove a socket, and it's corresponding output stream, from our 
    // list. This is usually called by a connection thread that has 
    // discovered that the connectin to the client is dead. 
    void removeConnection(Socket s) {
        // Synchronize so we don't mess up sendToAll() while it walks 
        // down the list of all output streamsa 
        synchronized (outputStreams) {
            // Tell the world 
            System.out.println("Removing connection to " + s);
            // Remove it from our hashtable/list 
            outputStreams.remove(s);
            // Make sure it's closed 
            try {
                s.close();
            } catch (IOException ie) {
                System.out.println("Error closing " + s);
                ie.printStackTrace();
            }
        }
    }}
    

    客户代码:

    public class Client implements Runnable {
    
    private SSLSocket socket;
    // The streams we communicate to the server; these come 
    // from the socket private 
    DataOutputStream dout;
    private DataInputStream din;
    
    // Constructor 
    public Client(String host, int port) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException, java.security.cert.CertificateException {
        // Connect to the server 
        try {
            // Initiate the connection 
            KeyStore ks = initKeyStore(KEYSTORE, "JKS", KEYSTORE_PASSWORD);
    
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, KEYSTORE_PASSWORD.toCharArray());
    
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
            tmf.init(ks);
    
            SSLContext sc = SSLContext.getInstance("TLS");
            TrustManager[] trustManagers = tmf.getTrustManagers();
            sc.init(kmf.getKeyManagers(), trustManagers, null);
    
            SSLSocketFactory ssf = sc.getSocketFactory();
            socket = (SSLSocket) ssf.createSocket(host, port);
            socket.startHandshake();
            //socket = new Socket(host, port);
            // We got a connection! Tell the world 
            System.out.println("connected to " + socket);
            // Let's grab the streams and create DataInput/Output streams 
            // from them 
            din = new DataInputStream(socket.getInputStream());
            dout = new DataOutputStream(socket.getOutputStream());
            // Start a background thread for receiving messages 
            new Thread(this).start();
        } catch (IOException ie) {
            System.out.println(ie);
        }
    }
    
    private static final String KEYSTORE = "clientkey.store";
    private static final String KEYSTORE_PASSWORD = "blackzero@client";
    
    private static KeyStore initKeyStore(String keyStore, String keyStoreType, String keyPass) throws KeyStoreException, IOException, NoSuchAlgorithmException, java.security.cert.CertificateException {
        KeyStore ks = null;
        try {
            ks = KeyStore.getInstance(keyStoreType);
            ks.load(null, keyPass.toCharArray());
        } catch (KeyStoreException | IOException | NoSuchAlgorithmException | java.security.cert.CertificateException e) {
            Logger.getLogger(Client.class.getName()).
                    log(Level.SEVERE, null, e);
            ks.load(null, keyPass.toCharArray());
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(2048);
            KeyPair kp = kpg.genKeyPair();
            Key publicKey = kp.getPublic();
            Key privateKey = kp.getPrivate();
            ks.setKeyEntry("keyForSeckeyDecrypt", privateKey, null, null);
            ks.setKeyEntry("keyForDigitalSignature", publicKey, null, null);
            try (FileOutputStream writeStream = new FileOutputStream(keyStore)) {
                ks.store(writeStream, keyPass.toCharArray());
            }
        }
        return ks;
    }
    
    // Gets called when the user types something 
    private void processMessage(String message) {
        try {
            // Send it to the server 
            dout.writeUTF(message);
            // Clear out text input field 
            //tf.setText("");
        } catch (IOException ie) {
            System.out.println(ie);
        }
    }
    
    // Variables declaration - do not modify                     
    // End of variables declaration                   
    @Override
    public void run() {
        try {
            // Receive messages one-by-one, forever 
            while (true) {
                // Get the next message 
                String message = din.readUTF();
                // Print it to our text window 
                //ta.append(message + "\n");
            }
        } catch (IOException ie) {
            System.out.println(ie);
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // Get the port # from the command line 
        int port = 786;
        try {
            Client c1 = new Client("localhost", port);
            c1.processMessage("Hi c1 is here");
        } catch (KeyStoreException 
                | NoSuchAlgorithmException 
                | CertificateException 
                | UnrecoverableKeyException 
                | KeyManagementException 
                | java.security.cert.CertificateException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }}
    

    如果你能指出我正确的方向,我将不胜感激。

    谢谢, Attiqe

0 个答案:

没有答案