SSLSocket 创建的 Java 异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22423063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Exception on SSLSocket creation
提问by naxo
In the code:
在代码中:
System.setProperty("javax.net.ssl.trustStore", cacerts);
System.setProperty("javax.net.ssl.trustStorePassword", pwdCacerts);
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", port);
I obtain a Java Exception:
我得到一个 Java 异常:
java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
at javax.net.ssl.DefaultSSLSocketFactory.throwException(Unknown Source)
at javax.net.ssl.DefaultSSLSocketFactory.createSocket(Unknown Source)
at PracticaRO.Cliente.main(Cliente.java:24)
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
at java.security.Provider$Service.newInstance(Unknown Source)
at sun.security.jca.GetInstance.getInstance(Unknown Source)
at sun.security.jca.GetInstance.getInstance(Unknown Source)
at javax.net.ssl.SSLContext.getInstance(Unknown Source)
at javax.net.ssl.SSLContext.getDefault(Unknown Source)
at javax.net.ssl.SSLSocketFactory.getDefault(Unknown Source)
at PracticaRO.Cliente.main(Cliente.java:23)
Caused by: java.io.IOException: Invalid keystore format
at sun.security.provider.JavaKeyStore.engineLoad(Unknown Source)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(Unknown Source)
at java.security.KeyStore.load(Unknown Source)
at sun.security.ssl.TrustManagerFactoryImpl.getCacertsKeyStore(Unknown Source)
at sun.security.ssl.SSLContextImpl$DefaultSSLContext.getDefaultTrustManager(Unknown Source)
at sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
... 7 more
It worked fine until I imported a new public key into cacerts with -keytool -import -keystore cacerts -alias kpServer type JCEKS -file Server.cer
what caused the exception above.
它工作正常,直到我将一个新的公钥导入 cacerts 并-keytool -import -keystore cacerts -alias kpServer type JCEKS -file Server.cer
导致上述异常。
Thanks in advance for any help.
在此先感谢您的帮助。
回答by Ted Bigham
The file you imported (Server.cer) is not in the format java is expecting. You told keytool the format was JCEKS. I believe that means it's a full keystore, which is not likely for a file named Server.cer.
您导入的文件 (Server.cer) 不是 java 期望的格式。你告诉 keytool 格式是 JCEKS。我相信这意味着它是一个完整的密钥库,对于名为 Server.cer 的文件来说不太可能。
You may have wanted to use -type PKCS12 instead.
您可能想改用 -type PKCS12。
回答by naxo
I got the solution from another way, I share it for someone who comes here with the same problem:
我从另一种方式得到了解决方案,我将它分享给遇到同样问题的人:
I need add this code
我需要添加此代码
System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
because by default it expects a JKS type.
因为默认情况下它需要 JKS 类型。
回答by Jinshad PT Koottil
Thanks for your Answer... Solved my problem by putting this code :
感谢您的回答...通过放置此代码解决了我的问题:
System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
Code as follows :
代码如下:
System.setProperty("javax.net.ssl.keyStore", CommonUtils.getKeystorePath());
System.setProperty("javax.net.ssl.keyStorePassword",
CommonUtils.getKeystorePassword());
System.setProperty("javax.net.ssl.trustStore",
CommonUtils.getTruststorePath());
System.setProperty("javax.net.ssl.trustStorePassword",
CommonUtils.getTruststorePassword());
System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
回答by Jo?o Rodrigues
I'm going to walk you through setup process. I suggest you use one password for everything just for you not to get confuse with it at first.
我将引导您完成设置过程。我建议您对所有内容都使用一个密码,以免一开始就混淆。
Follow this steps:
1.On Command Line:
请按照以下步骤操作:
1.在命令行上:
To create a Public/Private Key Pair using RSA, 2048 bits, entity name is "secureEntity", stored in file "server.keyStore".
1.1keytool -genkeypair -alias secureEntity -keyalg RSA -keysize 2048 - keystone server.keyStore
要使用 RSA 创建公钥/私钥对,2048 位,实体名称为“secureEntity”,存储在文件“server.keyStore”中。
1.1keytool -genkeypair -alias secureEntity -keyalg RSA -keysize 2048 - keystone server.keyStore
That command stored a Private Key and a Public Key for "secureEntity".
The Private Key, only you should have access to it (by knowing file password).
The Public Key is stored as a Certificate, so it follows X509 Certificate protocol fields. That way we can assume it contains a public key, and this public key is associated to "secureEntity".
And this is what we need to know for us to validate the certificate sent by server to client.
SSL first step validation is made by client, so the client validates the server in first place.
So now that we have generated a certificate and it is stored in server.keyStore we can export it in order to be able to import it into one or more trustStore.
The way we do it:
1.2keytool -exportcert -alias secureEntity -file exported.cer -keystore server.keystore
该命令为“secureEntity”存储了一个私钥和一个公钥。
私钥,只有您应该可以访问它(通过知道文件密码)。
公钥存储为证书,因此它遵循 X509 证书协议字段。这样我们就可以假设它包含一个公钥,并且这个公钥与“secureEntity”相关联。
这是我们需要知道的,以便我们验证服务器发送给客户端的证书。
SSL 第一步验证由客户端进行,因此客户端首先验证服务器。
因此,现在我们已经生成了一个证书并将其存储在 server.keyStore 中,我们可以将其导出,以便能够将其导入一个或多个 trustStore。
我们这样做的方式:
1.2keytool -exportcert -alias secureEntity -file exports.cer -keystore server.keystore
So now we can add to our really trustStore file, and it will ask us to confirm that we really trust that entity right after the import. If the file doesn't exists it well be automatically created.
1.3keytool -importcert -alias secureEntity -keystore trustedEntities.trustStore -file exported.cer
所以现在我们可以添加到我们真正的 trustStore 文件中,它会要求我们在导入后立即确认我们真的信任该实体。如果文件不存在,它会自动创建。
1.3keytool -importcert -alias secureEntity -keystoretrustedEntities.trustStore -fileexported.cer
Now for convenience lets import it to a file that only contains server certificate:
1.4keytool -importcert -alias secureEntity -keystore serverKeys.keyStore -file exported.cer
现在为方便起见,让我们将其导入仅包含服务器证书的文件:
1.4keytool -importcert -alias secureEntity -keystore serverKeys.keyStore -file exports.cer
So now your server should have a private and public key (certificate).
所以现在你的服务器应该有一个私钥和公钥(证书)。
In JAVA:
在 Java 中:
Client Side:
System.setProperty("javax.net.ssl.trustStore","trustedEntities.trustStore")
and Create sslsocket here
客户端:
System.setProperty("javax.net.ssl.trustStore","trustedEntities.trustStore")
并在此处创建 sslsocket
Server Side:
System.setProperty("javax.net.ssl.keyStore", "serverKeys.keyStore")
System.setProperty("javax.net.ssl.keyStorePassword", "serverKeys.keyStore FILE PASSWORD THAT YOU DEFINED BEFORE")
服务器端:
System.setProperty("javax.net.ssl.keyStore", "serverKeys.keyStore")
System.setProperty("javax.net.ssl.keyStorePassword", "serverKeys.keyStore 文件密码,您之前定义的")
Create a server ssl and thats it. Hope this helps. Cheers!
创建一个服务器 ssl,就是这样。希望这可以帮助。干杯!