设置 Java SSL ServerSocket 使用的证书
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12370351/
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
Setting the certificate used by a Java SSL ServerSocket
提问by Philipp
I want to open a secure listening socket in a Java server application. I know that the recommended way to do that is to just do this:
我想在 Java 服务器应用程序中打开一个安全的侦听套接字。我知道推荐的方法就是这样做:
SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = ssf.createServerSocket(443);
But this requires to pass the certificate of the server to the JVM when launching java. Because this would make some things in deployment more complicated for me, I would prefer to load the certificate at runtime.
但这需要在启动java时将服务器的证书传递给JVM。因为这会使部署中的某些事情对我来说更加复杂,所以我更愿意在运行时加载证书。
So I have a key file and a password and I want a server socket. How do I get there? Well, I read the documentation and the only way I could find is this:
所以我有一个密钥文件和一个密码,我想要一个服务器套接字。我如何到达那里?好吧,我阅读了文档,我能找到的唯一方法是:
// these are my parameters for SSL encryption
char[] keyPassword = "P@ssw0rd!".toCharArray();
FileInputStream keyFile = new FileInputStream("ssl.key");
// init keystore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyFile, keyPassword);
// init KeyManagerFactory
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyPassword);
// init KeyManager
KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
// init the SSL context
SSLContext sslContext = SSLContext.getDefault();
sslContext.init(keyManagers, null, new SecureRandom());
// get the socket factory
SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory();
// and finally, get the socket
ServerSocket serverSocket = socketFactory.createServerSocket(443);
And that doesn't even have any error handling. Is it really that complicated? Isn't there an easier way to do it?
这甚至没有任何错误处理。真的有那么复杂吗?没有更简单的方法吗?
采纳答案by user207421
But this requires to pass the certificate of the server to the JVM when launching java.
但这需要在启动java时将服务器的证书传递给JVM。
No it doesn't. Just set these system properties before you create the SSLServerSocket:
不,它没有。只需在创建之前设置这些系统属性SSLServerSocket:
javax.net.ssl.keyStore ssl.key
javax.net.ssl.keyStorePassword P@ssw0rd!
You can do that with System.setProperties()
oron the command line.
您可以使用System.setProperties()
或在命令行上执行此操作。
回答by David Grant
If you look at the code, you can see why it's necessarily complicated. This code decouples the implementation of the SSL protocol from:
如果您查看代码,就会明白为什么它一定很复杂。此代码将 SSL 协议的实现从以下方面解耦:
- the source of your key material (
KeyStore
) - certificate algorithm choice and key management (
KeyManager
) - management of peer trust rules (
TrustManager
) - not used here - secure random algorithm (
SecureRandom
) - NIO or socket implementation (
SSLServerSocketFactory
) - could useSSLEngine
for NIO
- 密钥材料的来源 (
KeyStore
) - 证书算法选择和密钥管理 (
KeyManager
) - 对等信任规则的管理 (
TrustManager
) - 此处未使用 - 安全随机算法 (
SecureRandom
) - NIO 或套接字实现 (
SSLServerSocketFactory
) - 可SSLEngine
用于 NIO
Consider what your own implementation would look like if you were trying to reach the same goals!
考虑一下,如果您试图达到相同的目标,您自己的实现会是什么样子!
回答by Ali Bagheri
Use this.
用这个。
public class KeyMaster
{
public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
try
{
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustKey);
SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
context.init(null, tmf.getTrustManagers(), null);
return context.getSocketFactory();
}
catch(Exception e)
{
Assistance.log("Err: getSSLSocketFactory(), ");
}
return null;
}
public static SSLServerSocketFactory getSSLServerSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
try
{
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustKey);
SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
context.init(null, tmf.getTrustManagers(), null);
return context.getServerSocketFactory();
}
catch(Exception e)
{
Assistance.log("Err: getSSLSocketFactory(), ");
}
return null;
}
public static SSLServerSocket getSSLServerSocket(SSLServerSocketFactory socketFactory, int port)
{
try
{
return (SSLServerSocket) socketFactory.createServerSocket(port);
}
catch(Exception e)
{Assistance.log("Err: getSSLSocket(), ");}
return null;
}
public static KeyStore getFromPath(String path, String algorithm, String filePassword)//PKSC12
{
try
{
File f = new File(path);
if(!f.exists())
throw new RuntimeException("Err: File not found.");
FileInputStream keyFile = new FileInputStream(f);
KeyStore keystore = KeyStore.getInstance(algorithm);
keystore.load(keyFile, filePassword.toCharArray());
keyFile.close();
return keystore;
}
catch(Exception e)
{
Assistance.log("Err: getFromPath(), " + e.toString());
}
return null;
}
and in main.
并在主要。
KeyStore key = KeyMaster.getFromPath(".\cssl.pfx", "PKCS12", "123");
SSLServerSocketFactory fac = KeyMaster.getSSLServerSocketFactory(key, "TLS");
listener = KeyMaster.getSSLServerSocket(fac, 49015);