如何在春季启动时使用不受密码保护(.p12)的SSL证书

时间:2019-10-11 16:40:24

标签: java spring spring-boot ssl

我有一个.pem证书,必须在我的spring boot应用程序中使用。 现在,由于Java无法理解.pem格式,因此我将其转换为.p12格式。

因为我们已经有了一个.pem证书,该证书不受任何密码保护,所以我也尝试避免使用.p12密码。

我创建了两个.p12文件,其中一个使用以下命令使用密码:

openssl x509 -signkey sslcert.key  -in sslcert.csr   -req -days 365
-out sslcert.pem

另外一个没有密码,请使用以下命令:

openssl pkcs12  -inkey sslcert.key  -in sslcert.pem  -export -passout
pass: -nokeys -out sslcert.p12

我可以在Spring Boot应用程序中使用以下属性,使用带有密码的密码成功获得结果:

server.port=8443  
server.ssl.enabled=true 
server.ssl.key-store-type=PKCS12 
server.ssl.key-store=keys/sslcert.p12 
server.ssl.key-store-password=password

但是,当我尝试使用不带密码的密码(这是我的偏爱)时,我会遇到sslhandshake异常。

而且,我无法弄清楚如何将此信息传递给ssl不受密码保护的spring boot。

到目前为止,我尝试了许多组合,例如不传递密码属性或将其保留为空,但在所有情况下均失败。

server.port=8443 
server.ssl.enabled=true
server.ssl.key-store-type=PKCS12
server.ssl.key-store=keys/sslcert.p12

我正在获得例外:

javax.net.ssl.SSLHandshakeException: no cipher suites in common
    at sun.security.ssl.Handshaker.checkThrown(Unknown Source)
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
    at sun.security.ssl.SSLEngineImpl.writeAppRecord(Unknown Source)
    at sun.security.ssl.SSLEngineImpl.wrap(Unknown Source)
    at javax.net.ssl.SSLEngine.wrap(Unknown Source)
    at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.flush(SslConnection.java:864)
    at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:515)
    at org.eclipse.jetty.server.HttpConnection.fillRequestBuffer(HttpConnection.java:331)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:243)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:411)
    at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:305)
    at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:159)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.lang.Thread.run(Unknown Source)

那么,任何人都可以对在春季启动时如何使用不受密码保护的.p12证书有所了解。

所有google文章似乎都在说明预期的密码。所以在Java中这是强制性的吗?

3 个答案:

答案 0 :(得分:3)

因此,经过所有研究,似乎Java密钥存储区需要密码。 因此,我不得不忽略没有密码的.p12。 然后使用pem证书,使用密码将其转换为.p12。 而且我是从Spring代码中执行此操作的,在该代码中,我将随机密码传递给Shell脚本,该脚本使用该密码从.pem生成.p12。

然后我将相同的密码从代码传递给ssl属性。

一个缺点是,每次重新启动应用程序时,我都必须从.pem重新生成.p12,但这是防止静态密码的方法。

答案 1 :(得分:0)

无法设置密码

答案 2 :(得分:0)

通过使用WebServerFactoryCustomizer和BouncyCastle JCE提供程序的自定义实现,我能够使用不带密码的PKCS12密钥库来为Spring Boot应用程序提供SSL。

首先,我使用BouncyCastle提供程序(org.bouncycastle:bcprov-jdk15on)将无密码的PKCS12(以我的情况为例,从Azure密钥保管库检索)加载到密钥库中:

    ByteArrayInputStream keyStoreStream = new ByteArrayInputStream(pfxBytes);

    logger.info("Loading server cert keystore from Vault retrieved cert");
    KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
    keyStore.load(keyStoreStream, "".toCharArray());

然后我将keyStore放入org.springframework.boot.web.server.SslStoreProvider的实现中:

public class CustomSslStoreProvider implements SslStoreProvider {

    private KeyStore keyStore;
    private KeyStore trustStore;

    public CustomSslStoreProvider(KeyStore keyStore, KeyStore trustStore){
        this.keyStore = keyStore;
        this.trustStore = trustStore;
    }

然后我将CustomSslStoreProvider注册为Bean,以便可以将其注入到我的WebServerFactoryCustomizer的实现中,以便嵌入式服务器可以使用它:

@Component
public class CustomSSLServletContainer implements
        WebServerFactoryCustomizer<TomcatServletWebServerFactory> {


    @Autowired(required = false)
    private CustomSslStoreProvider sslStoreProvider;


    public void customize(TomcatServletWebServerFactory factory) {
        if(sslStoreProvider != null) {
            factory.setSslStoreProvider(sslStoreProvider);
        }

通过此实现,我仍然在application.properties中配置了密钥别名(不相关,我碰巧需要ssl客户端身份验证)。但是,您不需要提供任何server.ssl.key-store属性:

server.ssl.key-alias=panda-asfafa=asfaf
server.ssl.client-auth=need