如何在 Java Sun HttpsServer 中使用 LetsEncrypt 证书?
How do I use LetsEncrypt certificates in Java Sun HttpsServer?
使用大量谷歌搜索的各种结果,我设法制作了一个 Java class 来处理从 LetsEncrypt 下载证书,非常简洁。 (如果有人感兴趣,可用here)
有了这个,我在一个文件夹中得到了这个内容作为输出:
chain.crt
domain.crt
domain.csr
domain.key
user.key
我一直在使用带有自签名证书的 com.sun.net.httpserver.HttpsServer,我按照一些指南生成了它,它给了我一个 .jks 文件,到目前为止,它在使用测试客户端时运行良好。但是现在我需要浏览器接受证书而不给出验证错误,所以我想在此 HttpsServer 中使用从 LetsEncrypt 下载的证书,但我不知道如何去做。我在谷歌上搜索了一下,但我没有找到任何对我有用的东西,尽管我不得不承认我并不真正理解我在这里做的大部分事情,我什至不知道哪一个我应该尝试使用上面的 5 个文件。
我当前的代码使用现有生成的 .jks 文件设置我的 HttpsServer:(也可用 here)
public void initHttpsServer(int port, String certificateFilePath, String sslPassword)
{
try
{
this.server = HttpsServer.create(new InetSocketAddress(port), 0);
SSLContext sslContext = SSLContext.getInstance("TLS");
char[] password = sslPassword.toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream(certificateFilePath);
ks.load(fis, password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
this.server.setHttpsConfigurator(new HttpsConfigurator(sslContext)
{
@Override
public void configure(HttpsParameters params)
{
try
{
SSLContext c = SSLContext.getDefault();
SSLEngine engine = c.createSSLEngine();
params.setNeedClientAuth(false);
params.setCipherSuites(engine.getEnabledCipherSuites());
params.setProtocols(engine.getEnabledProtocols());
SSLParameters defaultSSLParameters = c.getDefaultSSLParameters();
params.setSSLParameters(defaultSSLParameters);
}
在寻找解决方案时,我遇到了一些答案,其中包括来自 cmd 的 运行 命令以生成不同类型的文件。我需要所有这些在运行时工作,因此首选以编程方式进行的方式。
我还有一个相关的问题,当旧的 LetsEncrypt 证书过期并且我已经下载了新的证书时,我可以更新 HttpsServer 的 运行 实例以使用新下载的证书,还是我必须重新启动服务器?
非常感谢任何帮助弄清楚如何完成这项工作的人。
旁白:调用此 JKS 文件 'certificateFile' 具有误导性; JKS(或其他密钥库,如 PKCS12)通常包含多个证书,但通常还包括私钥,而且关键是私钥。
通常较难的部分是读取密钥文件,因为您使用的是 acme4j,它会为您处理。由于缺乏基础设施而未进行测试,但可以执行以下操作:
KeyPair kp = KeyPairUtils.readKeyPair (new FileReader ("domain.key"));
// add error handling and close much like your getOrCreateKeyPair
CertificateFactory cf = CertificateFactory.getInstance ("X.509");
Certificate cert0 = cf.generateCertificate (new FileInputStream ("domain.crt"));
Certificate cert1 = cf.generateCertificate (new FileInputStream ("chain.crt"));
// add similar error handling and close
KeyStore ks = KeyStore.getInstance ("jks"); // type doesn't really matter since it's in memory only
ks.load (null);
ks.setKeyEntry ("anyalias", kp.getPrivate(), password, new Certificate[]{cert0,cert1});
// now create a KMF and KeyManager from this KeyStore,
// optionally a TMF and TrustManager, then SSLContext etc as in your existing code
不知道Sun HttpsServer是否可以在运行时更改KeyManager数据;如果我以后有时间,我会试着看看。但显然你需要在改变它之前开始它是一个问题:-)
使用大量谷歌搜索的各种结果,我设法制作了一个 Java class 来处理从 LetsEncrypt 下载证书,非常简洁。 (如果有人感兴趣,可用here)
有了这个,我在一个文件夹中得到了这个内容作为输出:
chain.crt
domain.crt
domain.csr
domain.key
user.key
我一直在使用带有自签名证书的 com.sun.net.httpserver.HttpsServer,我按照一些指南生成了它,它给了我一个 .jks 文件,到目前为止,它在使用测试客户端时运行良好。但是现在我需要浏览器接受证书而不给出验证错误,所以我想在此 HttpsServer 中使用从 LetsEncrypt 下载的证书,但我不知道如何去做。我在谷歌上搜索了一下,但我没有找到任何对我有用的东西,尽管我不得不承认我并不真正理解我在这里做的大部分事情,我什至不知道哪一个我应该尝试使用上面的 5 个文件。
我当前的代码使用现有生成的 .jks 文件设置我的 HttpsServer:(也可用 here)
public void initHttpsServer(int port, String certificateFilePath, String sslPassword)
{
try
{
this.server = HttpsServer.create(new InetSocketAddress(port), 0);
SSLContext sslContext = SSLContext.getInstance("TLS");
char[] password = sslPassword.toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream(certificateFilePath);
ks.load(fis, password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
this.server.setHttpsConfigurator(new HttpsConfigurator(sslContext)
{
@Override
public void configure(HttpsParameters params)
{
try
{
SSLContext c = SSLContext.getDefault();
SSLEngine engine = c.createSSLEngine();
params.setNeedClientAuth(false);
params.setCipherSuites(engine.getEnabledCipherSuites());
params.setProtocols(engine.getEnabledProtocols());
SSLParameters defaultSSLParameters = c.getDefaultSSLParameters();
params.setSSLParameters(defaultSSLParameters);
}
在寻找解决方案时,我遇到了一些答案,其中包括来自 cmd 的 运行 命令以生成不同类型的文件。我需要所有这些在运行时工作,因此首选以编程方式进行的方式。
我还有一个相关的问题,当旧的 LetsEncrypt 证书过期并且我已经下载了新的证书时,我可以更新 HttpsServer 的 运行 实例以使用新下载的证书,还是我必须重新启动服务器?
非常感谢任何帮助弄清楚如何完成这项工作的人。
旁白:调用此 JKS 文件 'certificateFile' 具有误导性; JKS(或其他密钥库,如 PKCS12)通常包含多个证书,但通常还包括私钥,而且关键是私钥。
通常较难的部分是读取密钥文件,因为您使用的是 acme4j,它会为您处理。由于缺乏基础设施而未进行测试,但可以执行以下操作:
KeyPair kp = KeyPairUtils.readKeyPair (new FileReader ("domain.key"));
// add error handling and close much like your getOrCreateKeyPair
CertificateFactory cf = CertificateFactory.getInstance ("X.509");
Certificate cert0 = cf.generateCertificate (new FileInputStream ("domain.crt"));
Certificate cert1 = cf.generateCertificate (new FileInputStream ("chain.crt"));
// add similar error handling and close
KeyStore ks = KeyStore.getInstance ("jks"); // type doesn't really matter since it's in memory only
ks.load (null);
ks.setKeyEntry ("anyalias", kp.getPrivate(), password, new Certificate[]{cert0,cert1});
// now create a KMF and KeyManager from this KeyStore,
// optionally a TMF and TrustManager, then SSLContext etc as in your existing code
不知道Sun HttpsServer是否可以在运行时更改KeyManager数据;如果我以后有时间,我会试着看看。但显然你需要在改变它之前开始它是一个问题:-)