Spring Boot 2.7.18启用SSL后Windows无法识别PEM文件报错
问题描述
将spring-boot-starter-parent升级至2.7.18版本并启用SSL后,在Windows服务器部署时出现两类错误:
The PKCS#8 encryption algorithm with DER encoded OID of [2a864886f70d010503] was not recognised- 嵌套错误:
java.security.KeyStoreException: Cannot store non-PrivateKeys
但在Ubuntu 23.04机器上部署时应用可正常初始化。
证书生成步骤
通过以下OpenSSL命令生成PEM相关文件:
openssl req -x509 -newkey rsa:4096 -keyout <key_name>.pem -out <cert_name>.pemopenssl pkcs12 -export -out keyStore.p12 -inkey <key_name>.pem -in <cert_name>.pemopenssl pkcs12 -in keyStore.p12 -clcerts -nokeys -out <cert_name>.crtopenssl pkcs12 -in keyStore.p12 -clcerts -out <key_name>.key
完整报错栈
org.apache.catalina.LifecycleException: Protocol handler start failed at org.apache.catalina.connector.Connector.startInternal(Connector.java:1042) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) at org.apache.catalina.core.StandardService.addConnector(StandardService.java:232) at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:282) at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:213) at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:43) at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:179) at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:357) at java.base/java.lang.Iterable.forEach(Iterable.java:75) at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:156) at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:124) at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:946) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:594) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:164) at com.Main.main(Main.java:50) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) Caused by: java.lang.IllegalArgumentException: Cannot store non-PrivateKeys at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:107) at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:71) at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:236) at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1332) at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1418) at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:665) at org.apache.catalina.connector.Connector.startInternal(Connector.java:1039) ... 27 common frames omitted Caused by: java.security.KeyStoreException: Cannot store non-PrivateKeys at java.base/sun.security.provider.JavaKeyStore.engineSetKeyEntry(JavaKeyStore.java:282) at java.base/sun.security.util.KeyStoreDelegator.engineSetKeyEntry(KeyStoreDelegator.java:112) at java.base/java.security.KeyStore.setKeyEntry(KeyStore.java:1167) at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:372) at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:268) at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:105) ... 33 common frames omitted
解决方案
原因分析
- 密钥提取错误:原第4步命令使用
-clcerts参数,会只提取证书而非私钥,导致输出的.key文件实际是证书,触发Cannot store non-PrivateKeys错误; - JDK加密算法兼容性:Windows环境下的JDK对PKCS#8密钥的加密算法支持更严格,OID
2a864886f70d010503对应PBKDF2WithHmacSHA1,部分Windows JDK版本无法正确识别。
修复步骤
1. 重新生成正确的私钥文件
替换原第4步命令,去掉-clcerts参数,正确提取私钥:
openssl pkcs12 -in keyStore.p12 -nocerts -out <key_name>.key
执行时需输入p12文件密码,私钥加密密码可直接回车跳过。
2. 转换私钥为兼容Windows的PKCS#8格式
若仍出现PKCS#8算法识别错误,将私钥转为无加密的PKCS#8格式:
openssl pkcs8 -topk8 -inform PEM -in <key_name>.key -out <key_name>-pkcs8.key -nocrypt
之后在Spring Boot配置中使用转换后的<key_name>-pkcs8.key。
3. 简化配置(推荐)
直接使用生成的keyStore.p12作为密钥库,无需拆分crt和key,配置示例:
server.ssl.key-store=classpath:keyStore.p12 server.ssl.key-store-password=你的p12密码 server.ssl.key-store-type=PKCS12 server.ssl.key-alias=1 # 生成p12时未指定alias则默认是1
4. 对齐JDK版本
确保Windows服务器的JDK版本与Ubuntu一致(Spring Boot 2.7.x推荐使用OpenJDK 11/17),避免因加密算法支持差异导致问题。
内容的提问来源于stack exchange,提问作者liorko
相关产品推荐
相关产品推荐

