Keytool 创建受信任的自签名证书
我正在尝试使用 (java) keytool 创建自签名证书,但是当我尝试使用它时,出现以下异常(有关整个异常,请参见底部)。
...<5 more exceptions above this>
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:304)
at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:107)
at sun.security.validator.Validator.validate(Validator.java:203)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
... 22 more
我知道我可以用以下代码绕过这个:
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
但我对这个解决方案不感兴趣,因为我认为它会造成安全漏洞。 (如果我错了,请纠正我)。
有人能指出我正确的方向吗?我现在正在本地进行测试,因此更改内容非常容易。我可以访问服务器代码、客户端代码和 .keystore 文件。
更新
我试图对客户端和服务器使用一个 .keystore 文件,但为了简化我的问题,我创建了 server.keystore (见下文)和 client.truststore (见下文)。我有理由相信这些证书是正确的,但如果有人可以验证我将不胜感激。
server.keystore
hostname[username:/this/is/a/path][711]% keytool -list -keystore server.keystore -v
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: hostname
Creation date: Feb 4, 2010
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Issuer: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Serial number: 4b6b0ea7
Valid from: Thu Feb 04 13:15:03 EST 2010 until: Wed May 05 14:15:03 EDT 2010
Certificate fingerprints:
MD5: 81:C0:3F:EC:AD:5B:7B:C4:DA:08:CC:D7:11:1F:1D:38
SHA1: F1:78:AD:C8:D0:3A:4C:0C:9A:4F:89:C0:2A:2F:E2:E6:D5:13:96:40
Signature algorithm name: SHA1withDSA
Version: 3
*******************************************
*******************************************
client.truststore
hostname[username:/this/is/a/path][713]% keytool -list -keystore client.truststore -v
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: mykey
Creation date: Feb 4, 2010
Entry type: trustedCertEntry
Owner: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Issuer: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Serial number: 4b6b0ea7
Valid from: Thu Feb 04 13:15:03 EST 2010 until: Wed May 05 14:15:03 EDT 2010
Certificate fingerprints:
MD5: 81:C0:3F:EC:AD:5B:7B:C4:DA:08:CC:D7:11:1F:1D:38
SHA1: F1:78:AD:C8:D0:3A:4C:0C:9A:4F:89:C0:2A:2F:E2:E6:D5:13:96:40
Signature algorithm name: SHA1withDSA
Version: 3
*******************************************
*******************************************
更新
我认为包含整个异常可能会很有用:
javax.xml.soap.SOAPException: java.io.IOException: Could not transmit message
at org.jboss.ws.core.soap.SOAPConnectionImpl.callInternal(SOAPConnectionImpl.java:115)
at org.jboss.ws.core.soap.SOAPConnectionImpl.call(SOAPConnectionImpl.java:66)
at com.alcatel.tpapps.common.utils.SOAPClient.execute(SOAPClient.java:193)
at com.alcatel.tpapps.common.utils.SOAPClient.main(SOAPClient.java:280)
Caused by: java.io.IOException: Could not transmit message
at org.jboss.ws.core.client.RemotingConnectionImpl.invoke(RemotingConnectionImpl.java:192)
at org.jboss.ws.core.client.SOAPRemotingConnection.invoke(SOAPRemotingConnection.java:77)
at org.jboss.ws.core.soap.SOAPConnectionImpl.callInternal(SOAPConnectionImpl.java:106)
... 3 more
Caused by: org.jboss.remoting.CannotConnectException: Can not connect http client invoker. sun.security.validator.ValidatorException: No trusted certificate found.
at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:368)
at org.jboss.remoting.transport.http.HTTPClientInvoker.transport(HTTPClientInvoker.java:148)
at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:141)
at org.jboss.remoting.Client.invoke(Client.java:1858)
at org.jboss.remoting.Client.invoke(Client.java:718)
at org.jboss.ws.core.client.RemotingConnectionImpl.invoke(RemotingConnectionImpl.java:171)
... 5 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1584)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:877)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1116)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1100)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:857)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:288)
... 10 more
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:304)
at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:107)
at sun.security.validator.Validator.validate(Validator.java:203)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
... 22 more
I am trying to use the (java) keytool to create a self signed certificate but when I attempt to use it I get the following exception (see bottom for entire exception).
...<5 more exceptions above this>
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:304)
at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:107)
at sun.security.validator.Validator.validate(Validator.java:203)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
... 22 more
I know that I can by-pass this with this code:
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
But I am not interested in this solutions because I think that it creates a security hole. (please correct me if I am wrong).
Can anyone point me in the right direction? I am testing locally at the moment right now so it is pretty easy to change things. I have access to the server code, client code and to the .keystore file.
Update
I was attempting to use one .keystore file for both the client and server but in hopes of simplifying my issues I have created server.keystore (see below) and client.truststore (see below). I am reasonably confident that the certicates are correct but if someone could verify I would be grateful.
server.keystore
hostname[username:/this/is/a/path][711]% keytool -list -keystore server.keystore -v
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: hostname
Creation date: Feb 4, 2010
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Issuer: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Serial number: 4b6b0ea7
Valid from: Thu Feb 04 13:15:03 EST 2010 until: Wed May 05 14:15:03 EDT 2010
Certificate fingerprints:
MD5: 81:C0:3F:EC:AD:5B:7B:C4:DA:08:CC:D7:11:1F:1D:38
SHA1: F1:78:AD:C8:D0:3A:4C:0C:9A:4F:89:C0:2A:2F:E2:E6:D5:13:96:40
Signature algorithm name: SHA1withDSA
Version: 3
*******************************************
*******************************************
client.truststore
hostname[username:/this/is/a/path][713]% keytool -list -keystore client.truststore -v
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: mykey
Creation date: Feb 4, 2010
Entry type: trustedCertEntry
Owner: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Issuer: CN=hostname, OU=hostname, O=hostname, L=hostname, ST=hostname, C=hostname
Serial number: 4b6b0ea7
Valid from: Thu Feb 04 13:15:03 EST 2010 until: Wed May 05 14:15:03 EDT 2010
Certificate fingerprints:
MD5: 81:C0:3F:EC:AD:5B:7B:C4:DA:08:CC:D7:11:1F:1D:38
SHA1: F1:78:AD:C8:D0:3A:4C:0C:9A:4F:89:C0:2A:2F:E2:E6:D5:13:96:40
Signature algorithm name: SHA1withDSA
Version: 3
*******************************************
*******************************************
Update
I thought it could be useful to include the entire exception:
javax.xml.soap.SOAPException: java.io.IOException: Could not transmit message
at org.jboss.ws.core.soap.SOAPConnectionImpl.callInternal(SOAPConnectionImpl.java:115)
at org.jboss.ws.core.soap.SOAPConnectionImpl.call(SOAPConnectionImpl.java:66)
at com.alcatel.tpapps.common.utils.SOAPClient.execute(SOAPClient.java:193)
at com.alcatel.tpapps.common.utils.SOAPClient.main(SOAPClient.java:280)
Caused by: java.io.IOException: Could not transmit message
at org.jboss.ws.core.client.RemotingConnectionImpl.invoke(RemotingConnectionImpl.java:192)
at org.jboss.ws.core.client.SOAPRemotingConnection.invoke(SOAPRemotingConnection.java:77)
at org.jboss.ws.core.soap.SOAPConnectionImpl.callInternal(SOAPConnectionImpl.java:106)
... 3 more
Caused by: org.jboss.remoting.CannotConnectException: Can not connect http client invoker. sun.security.validator.ValidatorException: No trusted certificate found.
at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:368)
at org.jboss.remoting.transport.http.HTTPClientInvoker.transport(HTTPClientInvoker.java:148)
at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:141)
at org.jboss.remoting.Client.invoke(Client.java:1858)
at org.jboss.remoting.Client.invoke(Client.java:718)
at org.jboss.ws.core.client.RemotingConnectionImpl.invoke(RemotingConnectionImpl.java:171)
... 5 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1584)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:877)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1089)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1116)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1100)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:857)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:288)
... 10 more
Caused by: sun.security.validator.ValidatorException: No trusted certificate found
at sun.security.validator.SimpleValidator.buildTrustedChain(SimpleValidator.java:304)
at sun.security.validator.SimpleValidator.engineValidate(SimpleValidator.java:107)
at sun.security.validator.Validator.validate(Validator.java:203)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
... 22 more
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要在服务器和客户端之间“建立信任”(我假设您只需要进行服务器端身份验证)。这是因为您使用自签名证书。
这涉及将服务器的证书导入客户端信任存储:
在服务器端:
将 .cert 文件复制到客户端,然后:
You would need to "establish trust" between your server and client (I'm assuming you only need to do server-side authentication). This is because you use self-signed certs.
That involves importing your server's cert into the client trust store:
On the server side:
Copy the .cert file over to the client side and then:
您无法在客户端和服务器之间共享密钥库,因为密钥库包含私钥。进行身份验证时,客户端会跳过带有私钥的证书。如上所述,您需要在客户端部署信任库。
密钥库中的证书的行为方式不同,具体取决于您生成或导入它们的方式。
导入的证书的条目类型(在使用
-list -v
详细列出整个密钥库时看到)是“trustedCertEntry”。生成的证书的条目类型是“PrivateKeyEntry”。导出证书时,您仅导出其公钥以及对其颁发者的可选引用。似乎您需要将密钥库中的自签名证书导出为信任库中的受信任证书(名称在这里有意义)。
我不会这样做,因为 SSL/TLS 实现可能不支持它。从现实世界的角度来看,这就像在一些不起眼的 Web 服务器上部署来自 Verisign 的最终秘密私钥来签署临时页面,而该私钥的唯一目的是保留在保险箱中并签署其他证书。 SSL/TLS 实现者可能不会用这样的用例污染他们的代码,无论如何,“KeyUsage”证书扩展可能会将证书的使用限制为签名,从而防止加密。
这就是为什么我建议为您的测试重建证书链。
keytool 文档包含有关创建链(
-gencert
命令)的有趣部分,但它是一个非常骨架的示例,未涵盖密钥库-信任库关系。我对其进行了增强以模拟第三方证书颁发机构。临时存储
ir-keystore.jks
代表证书颁发机构。我给它提供了ca2 -> 的证书链ca1-> ca
,其中ca
被视为根证书。该链与每个非根证书(即ca1
和ca2
)一起出现,将其颁发者引用为Certificate[2]
。请注意,每个证书都是“PrivateKeyEntry”。然后,我按顺序向
my-keystore.jks
提供这些证书:ca
、ca1
、ca2
。我使用 -trustcacerts 选项导入 ca,这意味着它成为根证书。在 my-keystore.jks 中,每个导入的证书现在都是“trustedCertEntry”,这意味着只有公钥。发行关系仅出现在“发行者”字段中,但没关系,因为信任关系在导入时最重要。此时,
my-keystore.jks
模拟包含一些受信任证书的环境,例如新的 JRE。 ir-keystore.jks 模拟这些证书的所有者,他们有权签署证书请求。我也是:我在
my-keystore.jks
中创建一个自签名证书e1
,并由ca2
对其进行签名(通过their-keystore.jks)并将签名结果导入回
my-keystore.jks
。e1
仍然是一个“PrivateKeyEntry”(因为它的私钥保留在my-keystore.jks
中),但现在我已经构建了以下链:e1 -> ; ca2-> ca1
。看来ca1 -> ca
是隐式的,ca
是一个证书颁发机构。为了构建信任库,我只需导入证书
ca
、ca1
和ca2
,就像我为my-keystore.jks.请注意,我不导入
e1
,因为我希望 SSL/TLS 客户端根据ca2
对其进行验证。我认为这非常接近现实世界中的运作方式。这里的好处是您可以完全控制证书,并且不依赖于 JRE 的 cacerts。
这是将我所说的付诸实践的代码。只要禁用证书吊销列表(该主题留到另一天),似乎就可以与 Jetty(客户端和服务器)一起使用。
You can't share the keystore between client and server, because the keystore contains the private key. When authenticating, the client skips the certificates with private keys. As said above you need to deploy a truststore on client side.
The certificates in a keystore don't behave the same way, depending on how you generated or imported them.
An imported certificate's entry type (seen when verbosely listing the whole keystore with
-list -v
) is "trustedCertEntry". A generated certificate's entry type is "PrivateKeyEntry". When you export a certificate, you only export its public key, and an optional reference to its issuer.Seems like you need to export the self-signed certificate in your keystore as a trusted certificate in your truststore (names make sense here).
I wouldn't do that, because SSL/TLS implementations probably don't support it. From a real world perspective it's like deploying the ultimately secret private key from Verisign on some obscure Web server to sign casual pages, while the only purpose of this private key is to remain in a safe and sign other certificates. SSL/TLS implementors probably won't pollute their code with such a use case, and anyways, the "KeyUsage" certificate extension may restrict a certificate usage to signing, preventing encipherment.
That's why I suggest to rebuild a chain of certificates for your test.
The keytool documentation contains an interesting part about creating a chain (
-gencert
command) but it's a very skeletal example which doesn't cover the keystore-truststore relationship. I've enhanced it to simulate a third-party certification authority.A temporary store
their-keystore.jks
represents a certificate-emitting authority. I feed it with a certificate chain ofca2 -> ca1 -> ca
withca
being considered as a root certificate. The chain appears with each non-root certificate (namelyca1
andca2
) referencing their issuer asCertificate[2]
. Please note that every certificate is "PrivateKeyEntry".Then I feed the
my-keystore.jks
with those certificates in order:ca
,ca1
,ca2
. I importca
with the-trustcacerts
option which means it becomes a root certificate. Inmy-keystore.jks
each imported certificate now is "trustedCertEntry" which means there is only the public key. The issuing relationship only appears in the "Issuer" field but it's OK because the trust relationship mattered most at the time of the import.At this point
my-keystore.jks
simulates an environment containing some trusted certificates, like a fresh JRE. Thetheir-keystore.jks
simulates the owners of those certificates, who have the power to sign certificate requests.So do I : I create a self-signed certificate
e1
inmy-keystore.jks
, get it signed byca2
(throughtheir-keystore.jks
) and import the signed result back intomy-keystore.jks
.e1
is still a "PrivateKeyEntry" (because its private key remains inmy-keystore.jks
) but now I've built the following chain :e1 -> ca2 -> ca1
. It seems thatca1 -> ca
is implicit withca
being a certification authority.To build the truststore I just import certificates
ca
,ca1
andca2
the same way I did formy-keystore.jks
. Please note I don't importe1
, as I expect the SSL/TLS client to validate it againstca2
.I think this gets rather close of how things work in real world. What's nice here is you have full control on the certificates, and no dependency on JRE's cacerts.
Here is the code putting what I say in practice. Seems to work with Jetty (client and server) as long as you disable certificate revocation list (a topic left for another day).
你不应该那样做。密钥库是严格私有的。如果您将其泄露给任何人,您的安全就会受到致命的损害。仅仅为了让它工作而做这种事情是没有意义的,因为它没有工作 - 这只是一个安全漏洞。您必须正确执行:从服务器的密钥库导出到客户端的信任库,并从客户端的密钥库(如果有)导出到服务器的密钥库。
You mustn't do that. A keystore is strictly private. If you leak it to anybody you have fatally compromised security. There is no point in doing this kind of thing just to get it working, because it isn't working - it is just a security breach. You have to do it right: export from the server's keystore into the client's truststore, and from the client's keystore if any to the server's keystore.
我不明白。您是否将服务器密钥存储与客户端一起使用?您的用例到底是什么?您是否正在尝试设置相互身份验证?
如果是,那么您就走错路了。您将需要一个客户端密钥存储(用于客户端的自签名证书和私钥)和一个客户端信任存储(用于服务器的“独立”自签名证书,即没有其私钥)。两者都不同于服务器密钥存储。
I don't get it. Are you using the server key store with the client? What is your use case exactly? Are you trying to setup mutual authentication?
If yes, you're on the wrong path here. You'll need a client key store (for the client's self-signed certificate and private key) and a client trust store (for the server's "stand-alone" self-signed certificate i.e. without its private key). Both are different from the server key store.