2012-02-27 2 views
3

Je suis en train de se connecter à mon propre serveur SSL avec mon client SSL, mais je reçois l'erreur suivante:Java - javax.net.ssl.SSLPeerUnverifiedException: peer non authentifié

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at sun.security.ssl.SSLSessionImpl.getPeerCertificateChain(SSLSessionImpl.java:420) at server.run(Server.java:70) at server.main(Server.java:22)

I J'ai cherché le même problème ici sur stackoverflow mais je ne peux trouver que des gens qui l'utilisent dans Apache ou d'autres "systèmes" HTTPS.

Voici mon code serveur:

/* 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); 
    } 


} 

Et voici mon code client:

/* 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); 
} 

}

Je suis profondément reconnaissant une réponse, ou un coup de pouce dans la bonne direction!

Répondre

6

Il y a deux problèmes ici.

  1. Vous restreignez les suites de chiffrement à SSL_DH_anon_WITH_RC4_128_MD5, qui est une suite de chiffrement anonyme, donc il n'y a pas d'authentification. Retirez-le, vous n'en avez pas besoin.

  2. Vous n'appelez pas setWantClientAuth(true) ou setNeedClientAuth(true) sur le serveur, de sorte que le client n'est jamais invité à envoyer son certificat, il n'en envoie donc pas. Donc, avoir le serveur demande le certificat d'homologue est inutile. Demandez au client de le demander.

À ce stade, vous devez décider si vous avez vraiment besoin de l'authentification du client ou non. Si vous le faites, vous devez appeler l'une des méthodes ci-dessus et fournir au client une clé privée et un certificat signé dans un magasin de clés, et faire en sorte que le fichier de clés certifiées du serveur approuve ce fichier de clés par exportation/importation ou en faisant signer le certificat client par une autorité de certification. Il n'est pas immédiatement clair que vous en avez besoin.

+0

1. Je soupçonnais faufilant que cette DeffieHelman Anon pourrait avoir quelque chose à voir avec ça, mais si je retire ces lignes, je reçois l'erreur suivante: Aucun certificat disponible ou clé correspond à la SSL suites de chiffrement qui sont activées. \t à sun.security.ssl.SSLServerSocketImpl.checkEnabledSuites (SSLServerSocketImpl.java:327) \t à sun.security.ssl.SSLServerSocketImpl.accept (SSLServerSocketImpl.java:272) 2. Donc, il n'y a pas une façon de faire cela sans avoir le client pour s'authentifier? Je sais que je veux l'authentification du serveur mais je ne suis pas sûr du client si ... – phiip

+0

@phiip 1. si vous voulez le certificat de pair, le pair doit l'envoyer, et si le pair est le client que vous voulez ou besoin d'une authentification client pour que cela se produise. 2. L'exception liée à la suite de chiffrement signifie qu'il y a quelque chose de très étrange dans votre certificat de serveur. Générez une nouvelle clé privée à l'aide de RSA et recommencez tout le processus de signature. – EJP

+0

@phiip Bien sûr, vous devez supprimer ce paramètre de suite de chiffrement aux deux extrémités, à la fois le serveur et le client. – EJP

1

Le certificat expiré était la cause de notre "javax.net.ssl.SSLPeerUnverifiedException: pair non authentifié".

keytool -list -v -keystore filetruststore.ts

Enter keystore password: 
    Keystore type: JKS 
    Keystore provider: SUN 
    Your keystore contains 1 entry 
    Alias name: somealias 
    Creation date: Jul 26, 2012 
    Entry type: PrivateKeyEntry 
    Certificate chain length: 1 
    Certificate[1]: 
    Owner: CN=Unknown, OU=SomeOU, O="Some Company, Inc.", L=SomeCity, ST=GA, C=US 
    Issuer: CN=Unknown, OU=SomeOU, O=Some Company, Inc.", L=SomeCity, ST=GA, C=US 
    Serial number: 5011a47b 
    Valid from: Thu Jul 26 16:11:39 EDT 2012 until: Wed Oct 24 16:11:39 EDT 2012 
Questions connexes