Keytool导入密钥库失败:IOException-密钥库密码错误排查求助
我有一个Spring Boot应用,通过Dockerfile执行entrypoint.sh中的keytool -importkeystore...命令导入p12密钥库,实现证书配置参数化,无需将证书打包进应用镜像。
环境配置详情
Dockerfile
FROM openjdk:8-jdk-alpine as builder WORKDIR application ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} application.jar RUN java -Djarmode=layertools -jar application.jar extract FROM openjdk:8-jdk-alpine WORKDIR application COPY --from=builder application/dependencies/ ./ COPY --from=builder application/spring-boot-loader/ ./ COPY --from=builder application/snapshot-dependencies/ ./ COPY --from=builder application/application/ ./ COPY entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/entrypoint.sh # Install CURL RUN apk --no-cache add curl ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
entrypoint.sh启动脚本
#!/bin/sh #echo "executing keytool import store" echo "statement is ${STATEMENT}" keytool ${STATEMENT} echo "Executing springboot load for app" #Execute using linux 'exec' Java launcher exec java org.springframework.boot.loader.JarLauncher "$@"
.env配置文件
通过docker-compose引用自定义.env文件,其中STATEMENT变量对应的keytool命令:
-v -importkeystore -srckeystore /etc/certs/ssl/appc.com.p12 -srcstorepass Appcpassword1234 -destkeystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -srcstoretype pkcs12 -deststoretype JKS -deststorepass changeit
Spring Boot SSL属性配置:
SERVER_SSL_KEYALIAS=appc-alias SERVER_SSL_KEYSTORE=file:/etc/certs/ssl/appc.com.p12 #试过多种格式,比如去掉"file:"前缀 SERVER_SSL_KEYPASSWORD=Appcpassword1234 SERVER_SSL_KEYSTORE_PASSWORD=Appcpassword1234
相关信息:
- p12密钥库文件:appc.com.p12
- 密钥库密码:Appcpassword1234
问题现象
应用在Windows的Docker Desktop中运行正常,但在CentOS的Docker Engine中启动时,抛出以下错误栈:
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed at org.apache.catalina.connector.Connector.startInternal(Connector.java:1058) ~[tomcat-embed-core-9.0.35.jar:9.0.35] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.35.jar:9.0.35] at org.apache.catalina.core.StandardService.addConnector(StandardService.java:227) ~[tomcat-embed-core-9.0.35.jar:9.0.35] ... 26 common frames omitted Caused by: java.lang.IllegalArgumentException: keystore password was incorrect at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:99) ~[tomcat-embed-core-9.0.35.jar:9.0.35] at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:71) ~[tomcat-embed-core-9.0.35.jar:9.0.35] at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:216) ~[tomcat-embed-core-9.0.35.jar:9.0.35] at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1141) ~[tomcat-embed-core-9.0.35.jar:9.0.35] at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.35.jar:9.0.35] at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:592) ~[tomcat-embed-core-9.0.35.jar:9.0.35] at org.apache.catalina.connector.Connector.startInternal(Connector.java:1055) ~[tomcat-embed-core-9.0.35.jar:9.0.35] ... 28 common frames omitted Caused by: java.io.IOException: keystore password was incorrect at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2059) ~[na:1.8.0_212] at java.security.KeyStore.load(KeyStore.java:1445) ~[na:1.8.0_212]
已尝试的无效方案
- 重新生成包含复杂字母数字/特殊字符的P12证书(确认密码长度大于11位)
- 调整keytool命令参数,添加
-keypass、-storepass:
其中-v -importkeystore -srckeystore /etc/certs/ssl/appc.com.p12 -srcstorepass Appcpassword1234 -keypass Appcpassword1234 -destkeystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -srcstoretype PKCS12 -storepass changeit -J-showversion-J-showversion输出的版本信息:openjdk version "1.8.0_212" OpenJDK Runtime Environment (IcedTea 3.12.0) (Alpine 8.212.04-r0) OpenJDK 64-Bit Server VM (build 25.212-b04, mixed mode) - 尝试添加
-deststoretype=PKCS12参数时,出现错误:keytool error: java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big. java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big. at sun.security.util.DerInputStream.getLength(DerInputStream.java:599) at sun.security.util.DerValue.init(DerValue.java:391) at sun.security.util.DerValue.<init>(DerValue.java:332) - 使用OpenSSL重新生成P12证书,问题依旧
- 未尝试Oracle JDK 8,优先选择开源OpenJDK解决方案
额外提示
keytool给出的警告(经搜索为非错误提示):
Warning: The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -destkeystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -deststoretype pkcs12".
排查方向与解决建议
检查证书文件挂载权限:CentOS上Docker挂载的证书文件可能存在权限问题,容器内的openjdk用户无法读取
/etc/certs/ssl/appc.com.p12。可在entrypoint.sh中添加权限检查命令:ls -l /etc/certs/ssl/appc.com.p12 cat /etc/certs/ssl/appc.com.p12 | head -20 # 确认文件内容正常如果权限不足,在docker-compose中添加
chmod命令,或者调整挂载目录的权限。密码转义问题:如果密码包含特殊字符,在.env文件中可能存在转义问题。可尝试将密码用单引号包裹,或者在entrypoint.sh中直接输出
${SERVER_SSL_KEYSTORE_PASSWORD}确认是否正确传递。更换OpenJDK镜像版本:虽然输出的OpenJDK版本相同,但Windows和CentOS的Docker镜像可能存在细微差异。可尝试使用
openjdk:8u382-jdk-alpine替代openjdk:8-jdk-alpine,避免老旧版本的bug。直接测试证书有效性:在CentOS的容器内手动执行命令读取证书,验证密码是否正确:
keytool -list -keystore /etc/certs/ssl/appc.com.p12 -storepass Appcpassword1234 -storetype PKCS12如果这个命令失败,说明证书文件或密码确实有问题;如果成功,说明Spring Boot的配置存在问题。
调整Spring Boot SSL配置:尝试去掉
file:前缀,直接使用路径/etc/certs/ssl/appc.com.p12,同时确认SERVER_SSL_KEYALIAS是否正确(可用keytool -list命令查看证书的别名)。
内容的提问来源于stack exchange,提问作者static-man

