我正在尝试使用自己的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);
}
}
我非常感谢答案,或者朝着正确的方向努力!
答案 0 :(得分:6)
这里有两个问题。
您正在将密码套件限制为SSL_DH_anon_WITH_RC4_128_MD5,这是一个匿名密码套件,因此没有身份验证。只需删除它,您就不需要它。
您没有在服务器上调用setWantClientAuth(true)
或setNeedClientAuth(true)
,因此永远不会要求客户端发送证书,因此不会发送证书。因此让服务器请求对等证书是没有意义的。让客户要求它。
此时您需要确定是否确实需要客户端身份验证。如果这样做,则必须调用上述方法之一,并且还需要在密钥库中为客户端提供私钥和签名证书,并通过导出/导入或安排服务器的信任库信任此密钥库。通过CA签署客户端证书。目前还不清楚你是否需要这些。
答案 1 :(得分:1)
过期的证书是我们“javax.net.ssl.SSLPeerUnverifiedException:peer not authenticated”的原因。
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