使用 SSLSockets 的正确方法是什么?为什么会收到这些错误?
我正在尝试保护旨在通过多台计算机连接的应用程序系统。当我开始从普通套接字切换到 SSLSockets 时,我开始收到两个错误:
客户端:
“javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX 路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException: 无法找到有效的认证 请求目标的路径”
服务器端:
“javax.net.ssl.SSLHandshakeException: 收到致命警报: 证书_未知”
我将代码剥离为仅套接字并将它们放入一个程序中:
package sslTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class TestMain {
public class TestModuleReceive {
int port = 4445;
SSLServerSocket ss;
SSLSocket socket;
TestModuleReceive() {
initServerSocket();
receiveConnection();
}
private void initServerSocket() {
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("/home/uName/.keystore"), ("password").toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ("password").toCharArray());
SSLContext sslcontext = SSLContext.getInstance("SSLv3");
sslcontext.init(kmf.getKeyManagers(), null, null);
ServerSocketFactory ssf =
sslcontext.getServerSocketFactory();
ss = (SSLServerSocket)
ssf.createServerSocket();
ss.setReceiveBufferSize(8200);
ss.bind(new InetSocketAddress(port));
}
catch (KeyStoreException e) { e.printStackTrace(); }
catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
catch (CertificateException e) { e.printStackTrace(); }
catch (FileNotFoundException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
catch (UnrecoverableKeyException e) { e.printStackTrace(); }
catch (KeyManagementException e) { e.printStackTrace(); }
}
public void receiveConnection() {
new Thread() { public void run() {
try {
socket = (SSLSocket) ss.accept();
receiveData();
}
catch (IOException e) { e.printStackTrace(); }
}}.start();
}
public void receiveData() {
try {
System.out.println(socket.getInputStream().read());
}
catch (IOException e) { e.printStackTrace(); }
}
}
public class TestModuleSend {
int port = 4445;
String address = "localhost";
SSLSocketFactory factory;
SSLSocket socket;
TestModuleSend() {
initFactory();
addConnection();
sendData();
}
private void initFactory() {
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("/home/uName/.keystore"), ("password").toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ("password").toCharArray());
SSLContext sslcontext = SSLContext.getInstance("SSLv3");
sslcontext.init(kmf.getKeyManagers(), null, null);
factory = sslcontext.getSocketFactory();
}
catch (KeyStoreException e) { e.printStackTrace(); }
catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
catch (CertificateException e) { e.printStackTrace(); }
catch (FileNotFoundException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
catch (UnrecoverableKeyException e) { e.printStackTrace(); }
catch (KeyManagementException e) { e.printStackTrace(); }
}
public void addConnection() {
// Initialize socket
try {
socket = (SSLSocket) factory.createSocket(InetAddress.getByName(address), port);
}
catch (UnknownHostException e1) { e1.printStackTrace(); }
catch (IOException e1) { e1.printStackTrace(); }
}
public void sendData() {
// Send single byte
try {
socket.getOutputStream().write((byte)0x00);
}
catch (IOException e) { e.printStackTrace(); }
}
}
TestMain() {
TestModuleReceive receive = new TestModuleReceive();
TestModuleSend send = new TestModuleSend();
}
public static void main(String[] args) {
TestMain testMain = new TestMain();
}
}
当我运行此代码时,我得到以下堆栈跟踪:
javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1731)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:974)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1158)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:773)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:94)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:69)
at sslTest.TestMain$TestModuleReceive.receiveData(TestMain.java:71)
at sslTest.TestMain$TestModuleReceive$1.run(TestMain.java:63)
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1665)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:258)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:252)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1165)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:154)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:610)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:546)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:913)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1158)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:652)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:78)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:92)
at sslTest.TestMain$TestModuleSend.sendData(TestMain.java:121)
at sslTest.TestMain$TestModuleSend.<init>(TestMain.java:87)
at sslTest.TestMain.<init>(TestMain.java:129)
at sslTest.TestMain.main(TestMain.java:133)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:324)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:224)
at sun.security.validator.Validator.validate(Validator.java:235)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:147)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:230)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1144)
... 12 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:197)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:255)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:319)
... 18 more
有人能告诉我我做错了什么吗?
。
I am trying to secure a system of applications which are meant to be connected over multiple machines. When I started making the switch from plain Sockets to SSLSockets, I started getting two errors:
Client-side:
"javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification
path to requested target"
Server-side:
"javax.net.ssl.SSLHandshakeException:
Received fatal alert:
certificate_unknown"
I stripped down the code to just the sockets and put them into one program:
package sslTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class TestMain {
public class TestModuleReceive {
int port = 4445;
SSLServerSocket ss;
SSLSocket socket;
TestModuleReceive() {
initServerSocket();
receiveConnection();
}
private void initServerSocket() {
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("/home/uName/.keystore"), ("password").toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ("password").toCharArray());
SSLContext sslcontext = SSLContext.getInstance("SSLv3");
sslcontext.init(kmf.getKeyManagers(), null, null);
ServerSocketFactory ssf =
sslcontext.getServerSocketFactory();
ss = (SSLServerSocket)
ssf.createServerSocket();
ss.setReceiveBufferSize(8200);
ss.bind(new InetSocketAddress(port));
}
catch (KeyStoreException e) { e.printStackTrace(); }
catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
catch (CertificateException e) { e.printStackTrace(); }
catch (FileNotFoundException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
catch (UnrecoverableKeyException e) { e.printStackTrace(); }
catch (KeyManagementException e) { e.printStackTrace(); }
}
public void receiveConnection() {
new Thread() { public void run() {
try {
socket = (SSLSocket) ss.accept();
receiveData();
}
catch (IOException e) { e.printStackTrace(); }
}}.start();
}
public void receiveData() {
try {
System.out.println(socket.getInputStream().read());
}
catch (IOException e) { e.printStackTrace(); }
}
}
public class TestModuleSend {
int port = 4445;
String address = "localhost";
SSLSocketFactory factory;
SSLSocket socket;
TestModuleSend() {
initFactory();
addConnection();
sendData();
}
private void initFactory() {
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("/home/uName/.keystore"), ("password").toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ("password").toCharArray());
SSLContext sslcontext = SSLContext.getInstance("SSLv3");
sslcontext.init(kmf.getKeyManagers(), null, null);
factory = sslcontext.getSocketFactory();
}
catch (KeyStoreException e) { e.printStackTrace(); }
catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
catch (CertificateException e) { e.printStackTrace(); }
catch (FileNotFoundException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
catch (UnrecoverableKeyException e) { e.printStackTrace(); }
catch (KeyManagementException e) { e.printStackTrace(); }
}
public void addConnection() {
// Initialize socket
try {
socket = (SSLSocket) factory.createSocket(InetAddress.getByName(address), port);
}
catch (UnknownHostException e1) { e1.printStackTrace(); }
catch (IOException e1) { e1.printStackTrace(); }
}
public void sendData() {
// Send single byte
try {
socket.getOutputStream().write((byte)0x00);
}
catch (IOException e) { e.printStackTrace(); }
}
}
TestMain() {
TestModuleReceive receive = new TestModuleReceive();
TestModuleSend send = new TestModuleSend();
}
public static void main(String[] args) {
TestMain testMain = new TestMain();
}
}
When I run this code, I get the following stack trace:
javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1731)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:974)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1158)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:773)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:94)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:69)
at sslTest.TestMain$TestModuleReceive.receiveData(TestMain.java:71)
at sslTest.TestMain$TestModuleReceive$1.run(TestMain.java:63)
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1665)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:258)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:252)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1165)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:154)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:610)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:546)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:913)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1158)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:652)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:78)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:92)
at sslTest.TestMain$TestModuleSend.sendData(TestMain.java:121)
at sslTest.TestMain$TestModuleSend.<init>(TestMain.java:87)
at sslTest.TestMain.<init>(TestMain.java:129)
at sslTest.TestMain.main(TestMain.java:133)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:324)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:224)
at sun.security.validator.Validator.validate(Validator.java:235)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:147)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:230)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1144)
... 12 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:197)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:255)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:319)
... 18 more
Could anyone tell me what I am doing wrong?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在客户端,您不应该使用 KeyManager,而应该使用 TrustManager,因为您的客户端必须决定信任谁。
更改
为
当然,在实际应用程序中,客户端的密钥库应仅包含带有公钥的证书,而不包含服务器的私钥。
On the client side you should not use KeyManager, but TrustManager, since your client has to decide whom to trust.
Change
to
Of course, in a real application the client's keystore should only contain the certificates with the public keys, not the private keys of the server.