Java 在Jetty中设置运行时的ssl密钥库
是否可以在运行时更改密钥库?目前,我正在先设置SSL,然后再设置服务器。start()Java 在Jetty中设置运行时的ssl密钥库,java,ssl,certificate,jetty,ssl-certificate,Java,Ssl,Certificate,Jetty,Ssl Certificate,是否可以在运行时更改密钥库?目前,我正在先设置SSL,然后再设置服务器。start() 我想做的是在运行时创建一个证书并使用它。基本上,我正在创建一个类似Fiddler的工具,它可以动态创建证书。我不是java安全包方面的专家,但据我所知,没有直接的方法从公共API创建密钥对 但是,如果您允许您的代码从sun的受限软件包进行导入,我是有可能的,例如: import sun.security.x509.*; 下面是您要查找的代码的概要: PrivateKey privkey = pair.get
我想做的是在运行时创建一个证书并使用它。基本上,我正在创建一个类似Fiddler的工具,它可以动态创建证书。我不是java安全包方面的专家,但据我所知,没有直接的方法从公共API创建密钥对 但是,如果您允许您的代码从sun的受限软件包进行导入,我是有可能的,例如:
import sun.security.x509.*;
下面是您要查找的代码的概要:
PrivateKey privkey = pair.getPrivate();
X509CertInfo info = new X509CertInfo();
Date from = new Date();
//Validity for next one year
Date to = new Date(from.getTime() + (365) * 86400000l);
CertificateValidity interval = new CertificateValidity(from, to);
BigInteger sn = new BigInteger(64, new SecureRandom());
X500Name owner = new X500Name(dn);
info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
// Sign the cert
X509CertImpl cert = new X509CertImpl(info);
cert.sign(privkey, algorithm);
//cert object is ready to use
希望这有助于创建您自己的
密钥库实现
您可以创建一个覆盖密钥库的类,并将其作为Jetty的信任库。然后,您可以自由返回所需的任何证书
可能您必须使用第三方库动态创建证书,因为Java无法创建证书(使用官方API)。您可以使用BouncyCastle进行此操作。这里似乎有两个问题:在上动态生成证书(“我想做的是在运行时创建一个证书并使用它”),以及在不重新启动的情况下进行设置(“是否可以在运行时更改密钥库?”)
- 要动态生成证书,可以使用
- 首先,生成一个自签名CA(使用CA基本约束集),例如(有关详细信息,请查看
-ext
选项)。这将是您的定制CA
- 从该密钥库导出证书(仅CA证书,而不是其私钥),并将其导入到要使用的客户端
- 在应用程序中,使用该私钥与
X509V3CertificateGenerator
进行签名,并确保使用的颁发者DN与上面生成的CA证书的主题DN匹配
- 然后,您需要使用与您的客户机要联系的主机名相匹配的主题DN(或主题替代名称)配置生成的证书。如果您打算作为某种透明代理自动执行此操作,那么这可能是一个棘手的问题。(据我所知,当前版本的Java无法读取来自SNI扩展的名称,至少不能提前读取或不进行更多手动处理。)
更简单的方法当然是将此主机名作为工具中的可配置选项
- 要在不重新启动服务器的情况下进行设置,您可以实现自己的
X509KeyManager
,它保留在您正在使用的SSLContext
中,但保留一个引用和自定义访问器,以便稍后重新配置证书。它当然不一定是“干净”的东西,我也没有试过,但原则上它应该是有效的。(您当然应该确保正确处理并发方面。)
这可能使您不必关闭侦听套接字,重新配置SSLContext
并重新启动套接字。考虑到您可能需要与应用程序进行交互(以重新配置主机名),这可能有些过分
在Jetty邮件列表中发布此问题后,我得到的答复是,这不太可行自Jetty 9.4.0以来,此问题已得到修复,请参阅。现在,您可以覆盖密钥/信任库等,并调用SslContextFactory.reload
但是请注意,TLS会话恢复有一个警告:。根据评论,这不应该是普通浏览器的问题,但谁知道IE、移动、非浏览器客户端等呢。为什么?谁会相信它?你想清楚了吗?当然有办法创建密钥对。看-1…我如何告诉Jetty在运行时使用特定的密钥库/密钥?@gauravphoenix您不必更改密钥库。只需更改密钥库即可。Jetty会在每次需要密钥时询问您的密钥库,然后您可以自由返回任何您想要的密钥。Jetty不是这样工作的-一旦加载密钥库,Jetty就不会重新加载对其所做的更改
PrivateKey privkey = pair.getPrivate();
X509CertInfo info = new X509CertInfo();
Date from = new Date();
//Validity for next one year
Date to = new Date(from.getTime() + (365) * 86400000l);
CertificateValidity interval = new CertificateValidity(from, to);
BigInteger sn = new BigInteger(64, new SecureRandom());
X500Name owner = new X500Name(dn);
info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));
// Sign the cert
X509CertImpl cert = new X509CertImpl(info);
cert.sign(privkey, algorithm);
//cert object is ready to use