SSLPeerUnverifiedException:在本地主机上的 netbeans 8.2 中,对等端未使用自签名证书进行身份验证

SSLPeerUnverifiedException: peer not authenticated with self signed certificates in netbeans 8.2 on localhost

我已经用谷歌搜索这个错误几个小时了,到目前为止没有任何效果而且我不知道为什么......我这样生成我的证书:

客户:

keytool -genkey -alias babicaprivate -keystore babica.private -storetype JKS -keyalg rsa -dname "CN=Babica" -storepass babicapwd -keypass babicapwd -validity 365 keytool -export -alias babicaprivate -keystore babica.private -file temp.key -storepass babicapwd keytool -import -noprompt -alias babicapublic -keystore client.public -file temp.key -storepass public del temp.key

服务器:

keytool -genkey -alias serverprivate -keystore server.private -storetype JKS -keyalg rsa -dname "CN=localhost" -storepass serverpwd -keypass serverpwd -validity 365 keytool -export -alias serverprivate -keystore server.private -file temp.key -storepass serverpwd keytool -import -noprompt -alias serverpublic -keystore server.public -file temp.key -storepass public del temp.key

这给了我 public 以及服务器和客户端的私有证书

然后我启动服务器和客户端,当我尝试登录服务器并尝试使用

从服务器上的客户端读取 "Common name"

Socket newClientSocket = ss.accept(); ((SSLSocket)newClientSocket).startHandshake(); String username = ((SSLSocket) newClientSocket).getSession().getPeerPrincipal().getName();

是用户名获取给我错误,我不知道为什么。我制作证书的方式有问题吗?

这是我的服务器的完整代码:

import java.io.*;
import java.net.*;
import java.util.*;
import javax.net.ssl.*;
import java.security.*;

public class ChatServer {

protected List<Socket> clients = new ArrayList<Socket>(); // list of clients

private String[][] portUserPair = new String[10][2];
int i = 0;

private String passphrase = "serverpwd";
private int port = 1234;

public static void main(String[] args) throws Exception {
    new ChatServer();
}

public ChatServer() throws Exception {

    KeyStore clientKeyStore = KeyStore.getInstance("JKS");
    clientKeyStore.load(new FileInputStream("client.public"), "public".toCharArray());

    KeyStore serverKeyStore = KeyStore.getInstance("JKS");
    serverKeyStore.load(new FileInputStream("server.private"), passphrase.toCharArray());

    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
    tmf.init(clientKeyStore);
    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    kmf.init(serverKeyStore, passphrase.toCharArray());
    SSLContext sslContext = SSLContext.getInstance("TLS");
    SSLContext.setDefault(sslContext);
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), (new SecureRandom()));

    SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
    SSLServerSocket ss = (SSLServerSocket) factory.createServerSocket(port);
    ss.setNeedClientAuth(false);
    ss.setEnabledCipherSuites(new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});


    // start listening for new connections
    System.out.println("[system] listening ...");
    try {
        while (true) {
            Socket newClientSocket = ss.accept(); // wait for a new client connection
            ((SSLSocket)newClientSocket).startHandshake();
            String username = ((SSLSocket) newClientSocket).getSession().getPeerPrincipal().getName();
            System.out.println("Established SSL connection with: " + username);
            synchronized(this) {
                portUserPair[i][0] = Integer.toString(newClientSocket.getPort());
                clients.add(newClientSocket); // add client to the list of clients
            }
            ChatServerConnector conn = new ChatServerConnector(this, newClientSocket); // create a new thread for communication with the new client
            conn.start(); // run the new thread
        }
    } catch (Exception e) {
        System.err.println("[error] Accept failed.");
        e.printStackTrace(System.err);
        System.exit(1);
    }

    // close socket
    System.out.println("[system] closing server socket ...");
    try {
        ss.close();
    } catch (IOException e) {
        e.printStackTrace(System.err);
        System.exit(1);
    }
}

// send a message to all clients connected to the server
public void sendToAllClients(String message) throws Exception {
    Iterator<Socket> i = clients.iterator();
    while (i.hasNext()) { // iterate through the client list
        Socket socket = (Socket) i.next(); // get the socket for communicating with this client
        try {
            DataOutputStream out = new DataOutputStream(socket.getOutputStream()); // create output stream for sending messages to the client
            out.writeUTF(message); // send message to the client
        } catch (Exception e) {
            System.err.println("[system] could not send message to a client");
            e.printStackTrace(System.err);
        }
    }
}

public void sendToAClient(String message, String userInfo) throws Exception {
    Socket userSocket = null;
    String userPort = "";
    Iterator<Socket> i = clients.iterator();
    for (int k = 0; k < portUserPair.length; k++) {
        if(portUserPair[k][1].equals(userInfo)) {
            userPort = portUserPair[k][0];
            break;
        }
    }

    System.out.println(userPort);

    while (i.hasNext()) { // iterate through the client list
        Socket socket = (Socket) i.next(); // get the socket for communicating with this client
        if(Integer.toString(socket.getPort()).equals(userPort)) {
            userSocket = socket;
            break;
        }
    }

    message = message.substring(userInfo.length()+2);

    try {
        DataOutputStream out = new DataOutputStream(userSocket.getOutputStream()); // create output stream for sending messages to the client
        out.writeUTF(message); // send message to the client
    } catch (Exception e) {
        System.err.println("[system] could not send message to the client");
        e.printStackTrace(System.err);
    }
}

public void removeClient(Socket socket) {
    synchronized(this) {
        clients.remove(socket);
    }
}

public void saveUserInfo(String userInfo) {
    portUserPair[i][1] = userInfo;
    System.out.println(portUserPair[i][0] + " : " + portUserPair[i][1]);
    i++;
}
}

class ChatServerConnector extends Thread {
private ChatServer server;
private Socket socket;

public ChatServerConnector(ChatServer server, Socket socket) {
    this.server = server;
    this.socket = socket;
}

public void run() {
    System.out.println("[system] connected with " + this.socket.getInetAddress().getHostName() + ":" + this.socket.getPort());

    DataInputStream in;
    try {
        in = new DataInputStream(this.socket.getInputStream()); // create input stream for listening for incoming messages
    } catch (IOException e) {
        System.err.println("[system] could not open input stream!");
        e.printStackTrace(System.err);
        this.server.removeClient(socket);
        return;
    }

    while (true) { // infinite loop in which this thread waits for incoming messages and processes them
        String msg_received;
        try {
            msg_received = in.readUTF(); // read the message from the client
        } catch (Exception e) {
            System.err.println("[system] there was a problem while reading message client on port " + this.socket.getPort());
            e.printStackTrace(System.err);
            this.server.removeClient(this.socket);
            return;
        }

        if (msg_received.length() == 0) // invalid message
            continue;

        String[] msg = msg_received.split(" ");
        System.out.println(msg_received);

        if (msg[1].equals("system")) {
//            try {
//                server.saveUserInfo(((SSLSocket) socket).getSession().getPeerPrincipal().getName());
//            } catch (SSLPeerUnverifiedException ex) {
//                Logger.getLogger(ChatServerConnector.class.getName()).log(Level.SEVERE, null, ex);
//            }
            continue;
        }

        System.out.println(msg_received); // print the incoming message in the console

        String msg_send = msg_received.toUpperCase();

        if (msg[3].charAt(0) == '/') {
            String[] privateMsg = msg[3].split(" ");
            try {
                this.server.sendToAClient(msg_send, privateMsg[0].replace("/", "")); // send message to the client
            } catch (Exception e) {
                System.err.println("[system] there was a problem while sending the message to the client");
                e.printStackTrace(System.err);
                continue;
            }
            continue;
        }

        try {
            this.server.sendToAllClients(msg_send); // send message to all clients
        } catch (Exception e) {
            System.err.println("[system] there was a problem while sending the message to all clients");
            e.printStackTrace(System.err);
            continue;
        }
    }
}
}

这是我的朋友:

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import javax.net.ssl.*;
import java.security.*;

public class ChatClient extends Thread {

    private String userInfo = "";

    private String passphrase = "pwd";
    private int port = 1234;

    public static void main(String[] args) throws Exception {
        new ChatClient();
    }

    public ChatClient() throws Exception {

        KeyStore serverKeyStore = KeyStore.getInstance("JKS");
        serverKeyStore.load(new FileInputStream("server.public"), "public".toCharArray());

        KeyStore clientKeyStore = KeyStore.getInstance("JKS");
        Scanner s = new Scanner(System.in);
        String username = s.nextLine();
        clientKeyStore.load(new FileInputStream(username + ".private"), (username + passphrase).toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(serverKeyStore);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(clientKeyStore, (username + passphrase).toCharArray());
        SSLContext sslContext = SSLContext.getInstance("TLS");
        SSLContext.setDefault(sslContext);
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

        SSLSocketFactory sf = sslContext.getSocketFactory();
        SSLSocket socket = (SSLSocket) sf.createSocket("localhost", port);
        socket.setEnabledCipherSuites(new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});
        socket.startHandshake();

        DataInputStream in = null;
        DataOutputStream out = null;

        // connect to the chat server
        try {
            System.out.println("[system] connecting to chat server ...");
            System.out.println("[system] you are signed in as: " + username);

            in = new DataInputStream(socket.getInputStream()); // create input stream for listening for incoming messages
            out = new DataOutputStream(socket.getOutputStream()); // create output stream for sending messages

            this.sendMessage(username, out, "system");

            System.out.println("[system] connected");
            System.out.println("[system] to send a private message type \"/<NameOfUser>\" and then type the message");

            ChatClientMessageReceiver message_receiver = new ChatClientMessageReceiver(in); // create a separate thread for listening to messages from the chat server
            message_receiver.start(); // run the new thread
        } catch (Exception e) {
            e.printStackTrace(System.err);
            System.exit(1);
        }

        // read from STDIN and send messages to the chat server
        BufferedReader std_in = new BufferedReader(new InputStreamReader(System.in));
        String userInput;
        while ((userInput = std_in.readLine()) != null) { // read a line from the console
            this.sendMessage(userInput, out, userInfo); // send the message to the chat server
        }

        // cleanup
        out.close();
        in.close();
        std_in.close();
        socket.close();
    }

    private void sendMessage(String message, DataOutputStream out, String userInfo) {
        message = "[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + userInfo + " : " + message;
        try {
            out.writeUTF(message); // send the message to the chat server
            out.flush(); // ensure the message has been sent
        } catch (IOException e) {
            System.err.println("[system] could not send message");
            e.printStackTrace(System.err);
        }
    }
}

// wait for messages from the chat server and print the out
class ChatClientMessageReceiver extends Thread {
    private DataInputStream in;

    public ChatClientMessageReceiver(DataInputStream in) {
        this.in = in;
    }

    public void run() {
        try {
            String message;
            while ((message = this.in.readUTF()) != null) { // read new message
                System.out.println(message); // print the message to the console
            }
        } catch (Exception e) {
            System.err.println("[system] could not read message");
            e.printStackTrace(System.err);
        }
    }
}

整个事情应该是一个 "chat",它使用 SSL 来加密消息并且应该从证书中获取用户名...所以除了 "getting the usename out of the certificate's 'Common name' field"

救命啊,我快疯了! :'(

ss.setNeedClientAuth(false);

问题就在这里。您从未要求提供客户端证书,因此从未发送过。将其更改为 true.