Java – javax.net.ssl.SSLPeerUnverifiedException:peer未经过身份验证

我正在尝试使用自己的SSL客户端连接到我自己的SSL服务器,但是我收到以下错误:

javax.net.ssl.SSLPeerUnverifiedException:peer未经过身份验证
    at sun.security.ssl.SSLSessionImpl.getPeerCertificateChain(SSLSessionImpl.java:420)
    在server.run(Server.java:70)
    在server.main(Server.java:22)

我在*上搜索了同样的问题,但我只能找到在Apache或其他HTTPS“系统”中使用它的人.

这是我的服务器代码:

    /* Server SSL */


import javax.net.ssl.*;
import java.io.*;
import java.net.InetAddress;
import java.security.KeyStore;
//import java.security.cert.X509Certificate;
import java.util.Date;
import javax.security.cert.X509Certificate;

class server {

    ObjectOutputStream out;
    ObjectInputStream in;

    public static void main(String[] args) {    
        new server().run();
    }

    void run() {

    Date date = new Date();


        try {

            // Security test (to avoid starting from the command line)c

            char[] passphrase = "password".toCharArray();

           KeyStore keystore = KeyStore.getInstance("JKS");


           keystore.load(new FileInputStream("/home/ME/CERT/keystore"), passphrase);


           KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
           kmf.init(keystore, passphrase);


           SSLContext context = SSLContext.getInstance("TLS");
           KeyManager[] keyManagers = kmf.getKeyManagers();

           context.init(keyManagers, null, null);


            // -- End of security test

        // 1. Create a server Socket
            SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
            SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(9999);

         // TBH im not sure what the following code does, but I need it?

                    String[] enabledCipherSuites = { "SSL_DH_anon_WITH_RC4_128_MD5" };
                    sslserversocket.setEnabledCipherSuites(enabledCipherSuites);



        // 2. Wait for connection.
        System.out.println("Waiting for connection. ");
            SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();

           SSLSession session = sslsocket.getSession();
           X509Certificate cert = (X509Certificate)session.getPeerCertificateChain()[0];
           String subject = cert.getSubjectDN().getName();
           System.out.println(subject);


        // 2.1 Prints information about client, this could be (very) valuable to save in a file.
        System.out.println("Connection received: ");
        System.out.println("   Hostname: " + sslsocket.getInetAddress().getHostName());
        sslsocket.getInetAddress();
        System.out.println("         IP: " + InetAddress.getLocalHost().getHostAddress());
        System.out.println("          @  " + date.toString());
        System.out.println();

        // 3. Create input and output streams.



        // for some reason i cant make the out/in-variable without using it as global?

        out = new ObjectOutputStream(sslsocket.getOutputStream());
        out.flush();
        in = new ObjectInputStream(sslsocket.getInputStream());

        sendMessage("Connection successful");

        // 4. Client and server talks via the input and output streams

        String message;

        do {
        message = (String)in.readObject();
        System.out.println(" Client says:  " + message);
        if (message.equals("bye")) {
            sendMessage("bye");
        }

        }while(!message.equals("bye"));

        // 5. Closing connection

        in.close();
        out.close();
        sslsocket.close();
System.out.println("Server terminated. ");

        } catch (Exception exception) {
            exception.printStackTrace();

        }
    }
    void sendMessage(String msg) throws Exception
    {
    out.writeObject(msg);
    out.flush();
    System.out.println("  You(server) says: " + msg);
    }


}

这是我的客户代码:

/* Java SSL Client */

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

class client {

String message;
ObjectOutputStream out;
ObjectInputStream in;


public static void main(String[] args) {
    new client().run();
}

void run() {

System.out.println();

int port = 9999;

String host = "127.0.0.1";

try {

    // Security test (to avoid starting with the command line)
    char[] passphrase = "trustword".toCharArray();

    KeyStore keystore = KeyStore.getInstance("JKS");
    keystore.load(new FileInputStream("/home/ME/CERT/truststore"), passphrase);

   TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
   tmf.init(keystore);


   SSLContext context = SSLContext.getInstance("TLS");
   TrustManager[] trustManagers = tmf.getTrustManagers();

   context.init(null, trustManagers, null);



    // --- End of security test



    System.out.println("Connecting to " + host + " on port " + port);

    // 1. Create a client socket. 
    SSLSocketFactory sslFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
    SSLSocket sslSocket = (SSLSocket)sslFactory.createSocket(host, port);

    // TBH im not sure what the following code does, but I need it?
    String[] enabledCipherSuites = { "SSL_DH_anon_WITH_RC4_128_MD5" };
    sslSocket.setEnabledCipherSuites(enabledCipherSuites);


    System.out.println("Connected.");

    // 2. Create input and output streams
    out = new ObjectOutputStream(sslSocket.getOutputStream());
    out.flush();
    in = new ObjectInputStream(sslSocket.getInputStream());

    // 3. Client and server talks via the input and output streams

    Scanner input = new Scanner(System.in);

    message = (String)in.readObject();
    System.out.println(" Server says: " + message);

    sendMessage("Hello Server! ");

    do {
    // Sends input text
    System.out.print("Enter text to send: ");
    message = input.nextLine();
    sendMessage(message);

    if (message.equals("bye")) {
        message = (String)in.readObject();
        System.out.println(" Server says: " + message);
    }

    } while(!message.equals("bye"));

    // 4. Closing connection

    in.close();
    out.close();
    sslSocket.close();
    System.out.println("Client terminated. ");
}

catch (Exception exception) {
    exception.printStackTrace();

}

}

void sendMessage(String msg) throws Exception
{
out.writeObject(msg);
out.flush();
System.out.println("  You(client) says: " + msg);
}

}

我非常感谢答案,或者朝着正确的方向努力!

解决方法:

这里有两个问题.

>您正在将密码套件限制为SSL_DH_anon_WITH_RC4_128_MD5,这是一个匿名密码套件,因此没有身份验证.只需删除它,你不需要它.
>您没有在服务器上调用setWantClientAuth(true)或setNeedClientAuth(true),因此永远不会要求客户端发送其证书,因此它不会发送证书.因此让服务器请求对等证书是没有意义的.让客户要求它.

此时,您需要确定是否确实需要客户端身份验证.如果这样做,则必须调用上述方法之一,并且还需要在密钥库中为客户端提供私钥和签名证书,并通过导出/导入或安排服务器的信任库信任此密钥库.通过CA签署客户端证书.目前还不清楚你是否需要这些.

上一篇:Java – KeyStore没有在Android中使用BouncyCastle为PKCS12文件应用/强制执行私钥密码


下一篇:Android:将密钥库作为资产打开以生成SSLSocketFactory