getLocalCertificates() return 空
getLocalCertificates() return null
我正在尝试编写一个简单的 ssl 服务器套接字和客户端套接字程序。首先我得到一些真正的证书,然后我使用第一个代码为它生成密钥库。然后我编写了服务器和客户端代码,因此我的服务器使用该密钥库作为服务器证书,但在连接期间没有发送证书并且 session.getLocalCertificates() 仅 return null
我的密钥库生成代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.security.KeyStore;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
public class MainClass {
public static void main(String args[]) throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
List mylist = new ArrayList();
FileInputStream in = new FileInputStream("C:\Users\nima\Downloads\72315359_example.com.cert");
Certificate cr = cf.generateCertificate(in);
mylist.add(cr);
CertPath cp = cf.generateCertPath(mylist);
System.out.println(cp);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, null);
List cplist = cp.getCertificates();
Object[] o = cplist.toArray();
for (int i = 0; i < o.length; i++) {
X509Certificate c = (X509Certificate) o[i];
ks.setCertificateEntry("my" + i, c);
}
FileOutputStream output = new FileOutputStream("C:\Users\nima\Downloads\test.dat");
ks.store(output, "mypass".toCharArray());
output.close();
}
}
我的服务器代码:
import java.io.PrintStream;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
public class MainClass {
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.keyStore", "C:\Users\nima\Downloads\test.dat");
System.setProperty("javax.net.ssl.keyStorePassword", "mypass");
SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = ssf.createServerSocket(5432);
while (true) {
Socket s = ss.accept();
SSLSession session = ((SSLSocket) s).getSession();
Certificate[] cchain2 = session.getLocalCertificates();
for (int i = 0; i < cchain2.length; i++) {
System.out.println(((X509Certificate) cchain2[i]).getSubjectDN());
}
System.out.println("Peer host is " + session.getPeerHost());
System.out.println("Cipher is " + session.getCipherSuite());
System.out.println("Protocol is " + session.getProtocol());
System.out.println("ID is " + new BigInteger(session.getId()));
System.out.println("Session created in " + session.getCreationTime());
System.out.println("Session accessed in " + session.getLastAccessedTime());
PrintStream out = new PrintStream(s.getOutputStream());
out.println("Hi");
out.close();
s.close();
}
}
}
我的客户代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.Socket;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class MainClass {
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.trustStore", "C:\Users\nima\Downloads\test.dat");
SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
Socket s = ssf.createSocket("127.0.0.1", 5432);
SSLSession session = ((SSLSocket) s).getSession();
Certificate[] cchain = session.getPeerCertificates();
System.out.println("The Certificates used by peer");
for (int i = 0; i < cchain.length; i++) {
System.out.println(((X509Certificate) cchain[i]).getSubjectDN());
}
System.out.println("Peer host is " + session.getPeerHost());
System.out.println("Cipher is " + session.getCipherSuite());
System.out.println("Protocol is " + session.getProtocol());
System.out.println("ID is " + new BigInteger(session.getId()));
System.out.println("Session created in " + session.getCreationTime());
System.out.println("Session accessed in " + session.getLastAccessedTime());
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String x = in.readLine();
System.out.println(x);
in.close();
}
}
我的服务器代码来自 here 并且在服务器端和客户端我都从 getLocalCertificates 中得到空值。也有可能我所有的代码都是错误的。
(来自评论,略有扩展)
如果在握手完成之前调用SSLSocket.getSession()
,它会尝试这样做,但是如果握手失败getSession()
会吞下异常并且只是returns一个'nullSession' 对象,它没有真正的会话对象所具有的数据。 (1) 设置 sysprop javax.net.debug=ssl
(在启动时,通常在命令行上使用 -D
)并查看它记录的内容以查看您的握手有什么问题,或者 (2) 显式调用 ((SSLSocket)s).startHandshake()
(不管名称如何,它实际上运行握手完成,成功与否)并查看它抛出的内容。
特别是如果您使用由显示的第一个代码创建的密钥库文件,该文件仅包含证书 (trustedCertEntry) 而不是 privateKeyEntry(具有私钥和 certificate/chain),这是 SSL/TLS 服务器使用任何通用和默认启用的套件;此错误通常表现为与 'no cipher[suite] in common' 或 'no cipher[suite] overlap' 的握手失败,有点令人困惑。
第二部分(SSL/TLS 没有私钥的服务器不工作)已经被询问和回答了很多次,但我不记得有任何欺骗也包括 'getSession masks the error' 部分。
我正在尝试编写一个简单的 ssl 服务器套接字和客户端套接字程序。首先我得到一些真正的证书,然后我使用第一个代码为它生成密钥库。然后我编写了服务器和客户端代码,因此我的服务器使用该密钥库作为服务器证书,但在连接期间没有发送证书并且 session.getLocalCertificates() 仅 return null 我的密钥库生成代码:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.security.KeyStore;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
public class MainClass {
public static void main(String args[]) throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
List mylist = new ArrayList();
FileInputStream in = new FileInputStream("C:\Users\nima\Downloads\72315359_example.com.cert");
Certificate cr = cf.generateCertificate(in);
mylist.add(cr);
CertPath cp = cf.generateCertPath(mylist);
System.out.println(cp);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, null);
List cplist = cp.getCertificates();
Object[] o = cplist.toArray();
for (int i = 0; i < o.length; i++) {
X509Certificate c = (X509Certificate) o[i];
ks.setCertificateEntry("my" + i, c);
}
FileOutputStream output = new FileOutputStream("C:\Users\nima\Downloads\test.dat");
ks.store(output, "mypass".toCharArray());
output.close();
}
}
我的服务器代码:
import java.io.PrintStream;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
public class MainClass {
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.keyStore", "C:\Users\nima\Downloads\test.dat");
System.setProperty("javax.net.ssl.keyStorePassword", "mypass");
SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = ssf.createServerSocket(5432);
while (true) {
Socket s = ss.accept();
SSLSession session = ((SSLSocket) s).getSession();
Certificate[] cchain2 = session.getLocalCertificates();
for (int i = 0; i < cchain2.length; i++) {
System.out.println(((X509Certificate) cchain2[i]).getSubjectDN());
}
System.out.println("Peer host is " + session.getPeerHost());
System.out.println("Cipher is " + session.getCipherSuite());
System.out.println("Protocol is " + session.getProtocol());
System.out.println("ID is " + new BigInteger(session.getId()));
System.out.println("Session created in " + session.getCreationTime());
System.out.println("Session accessed in " + session.getLastAccessedTime());
PrintStream out = new PrintStream(s.getOutputStream());
out.println("Hi");
out.close();
s.close();
}
}
}
我的客户代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.Socket;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class MainClass {
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.trustStore", "C:\Users\nima\Downloads\test.dat");
SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
Socket s = ssf.createSocket("127.0.0.1", 5432);
SSLSession session = ((SSLSocket) s).getSession();
Certificate[] cchain = session.getPeerCertificates();
System.out.println("The Certificates used by peer");
for (int i = 0; i < cchain.length; i++) {
System.out.println(((X509Certificate) cchain[i]).getSubjectDN());
}
System.out.println("Peer host is " + session.getPeerHost());
System.out.println("Cipher is " + session.getCipherSuite());
System.out.println("Protocol is " + session.getProtocol());
System.out.println("ID is " + new BigInteger(session.getId()));
System.out.println("Session created in " + session.getCreationTime());
System.out.println("Session accessed in " + session.getLastAccessedTime());
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String x = in.readLine();
System.out.println(x);
in.close();
}
}
我的服务器代码来自 here 并且在服务器端和客户端我都从 getLocalCertificates 中得到空值。也有可能我所有的代码都是错误的。
(来自评论,略有扩展)
如果在握手完成之前调用SSLSocket.getSession()
,它会尝试这样做,但是如果握手失败getSession()
会吞下异常并且只是returns一个'nullSession' 对象,它没有真正的会话对象所具有的数据。 (1) 设置 sysprop javax.net.debug=ssl
(在启动时,通常在命令行上使用 -D
)并查看它记录的内容以查看您的握手有什么问题,或者 (2) 显式调用 ((SSLSocket)s).startHandshake()
(不管名称如何,它实际上运行握手完成,成功与否)并查看它抛出的内容。
特别是如果您使用由显示的第一个代码创建的密钥库文件,该文件仅包含证书 (trustedCertEntry) 而不是 privateKeyEntry(具有私钥和 certificate/chain),这是 SSL/TLS 服务器使用任何通用和默认启用的套件;此错误通常表现为与 'no cipher[suite] in common' 或 'no cipher[suite] overlap' 的握手失败,有点令人困惑。
第二部分(SSL/TLS 没有私钥的服务器不工作)已经被询问和回答了很多次,但我不记得有任何欺骗也包括 'getSession masks the error' 部分。