جافا - javax.net.ssl.SSLPeerUnverifiedException:النظير غير مصادق عليه
-
13-11-2019 - |
سؤال
أحاول الاتصال بخادم SSL الخاص بي باستخدام عميل SSL الخاص بي، ولكنني أتلقى الخطأ التالي:
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)
لقد بحثت عن نفس المشكلة هنا في stackoverflow ولكن لا يمكنني العثور إلا على الأشخاص الذين يستخدمون هذا في 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.ليس من الواضح على الفور أنك بحاجة إلى أي من هذا.
نصائح أخرى
كانت الشهادة منتهية الصلاحية هي سبب "javax.net.ssl.SSLPeerUnverifiedException:النظير غير مصادق عليه".
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