【问题标题】:keytool said "keystore password was incorrect"keytool 说“密钥库密码不正确”
【发布时间】:2022-02-21 23:41:13
【问题描述】:

我使用这些命令来生成自签名证书:

gmssl ecparam -genkey -name sm2p256v1 -out ca.key
gmssl req -new -key ca.key -out ca.csr
gmssl x509 -req -days 3650 -sm3 -signkey ca.key -in ca.csr -out ca.crt

gmssl ecparam -genkey -name sm2p256v1 -out server.key
gmssl req -new -key server.key -out server.csr
gmssl x509 -req -days 3650 -sm3 -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt

gmssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -name serverkey

每当它说需要输入密码时,我都会输入 123456。 但是当我尝试将服务器证书和密钥导入 jks 文件时,它不起作用,我也尝试将一些密码替换为“changeit”,但 keytool 显示相同的错误:

keytool -importkeystore -deststorepass 123456 -destkeypass 123456 \
-destkeystore server.jks -srckeystore server.p12 -srcstoretype PKCS12 \
-srcstorepass 123456 -alias serverkey

keytool error: java.io.IOException: keystore password was incorrect

一些补充细节:

回复@dave_thompson_085 的回答:

非常感谢您回答我的问题。

实际上,我想使用 GMSSL 构建一个 netty https 服务器,但我对此并不熟悉,也没有找到有关如何使用 netty 构建 gmssl 服务器的教程,所以我想先构建一个普通的 SSL 服务器而不是将其修改为 GMSSL。我发现构建 SSL 服务器的教程使用 jks 文件,所以我尝试将 SM2 密钥和证书放入其中以将其修改为 GMSSL。

我还找到了直接使用证书和密钥文件的其他方式,例如通过这些代码构建 SSLContext:

File certChainFile = new File("server.crt");  
File keyFile = new File("server.key");  
File rootFile = new File("ca.crt");  
SslContext sslCtx = SslContextBuilder.forServer(certChainFile, keyFile)  
.trustManager(rootFile).protocols("GMSSLv.1.0")  
// will it recognize these string "GMSSLv.1.0"? I'dont konw, I just try.
.clientAuth(ClientAuth.NONE).build();

但是当我尝试运行时它会抛出错误:

java.lang.IllegalArgumentException: File does not contain valid certificates

我在google上搜索这些错误,有人说我需要使用pkcs8证书,所以我试试这个命令:

gmssl pkcs8 -topk8 -inform PEM -outform PEM -in server.p12 -out server.p8 -nocrypt

它也不起作用:

unable to load key  
4577107392:error:25066067:DSO support routines:dlfcn_load:could not load the shared library:crypto/dso/dso_dlfcn.c:113:filename(libproviders.dylib): dlopen(libproviders.dylib, 2): image not found  
4577107392:error:25070067:DSO support routines:DSO_load:could not load the shared library:crypto/dso/dso_lib.c:161:  
4577107392:error:0E07506E:configuration file routines:module_load_dso:error loading dso:crypto/conf/conf_mod.c:220:module=providers, path=providers  
4577107392:error:0E076071:configuration file routines:module_run:unknown module name:crypto/conf/conf_mod.c:162:module=providers  
4577107392:error:0906D06C:PEM routines:PEM_read_bio:no start line:crypto/pem/pem_lib.c:695:

其实我很迷茫,不知道怎么用netty搭建gmssl服务器。

netty 支持 gmssl 和 SM2 SM3 SM4 算法吗?我看到它似乎支持这个问题(https://github.com/netty/netty/issues/11406),但它看到拉取请求并不意味着加密算法。

我应该如何构建 GMSSL 服务器?我应该使用特殊版本的 JCE、Netty 还是 JDK?还是我需要自己暗示协议?

【问题讨论】:

  • 您修改后的问题非常不同,我无法真正回答;你想让我删除我现在不适用的答案以避免让其他人失望吗?正如我所说,Bouncy 支持中文 primitives,但它和标准 Java 都不支持明显修改的 protocol。 Netty 确实支持 tomcat-native 的变体(即不是 Java),它与 OpenSSL 接口,github.com/guanzhi/GmSSL 说它与 OpenSSL 兼容,所以这可能有效,但我对它们的了解不够多,无法回答。或者,GmSSL 表示它支持 apache,您可以将其用作代理。

标签: java ssl netty keytool


【解决方案1】:

Meta:这不是编程,它充其量是开发的边界;它可能更适合 security.SX 或超级用户。但由于似乎没有人投票结束,至少现在还没有……

问题在于“标准”Java 不支持 SM2, 或者更准确地说,Oracle 或 OpenJDK Java 中的标准提供者 不支持。如果您运行 keytool 命令并添加了 -v 以获取完整的堆栈跟踪,您可以看到 PKCS12KeyStore.engineLoad 实际上得到了 Unknown named curve 的异常,但将其包装为 password was incorrect,我称之为混乱和糟糕的 UI部分。

BouncyCastle(在相当新的版本中)可以,但我只能通过以下相当笨拙的方式让 keytool 来处理这样的密钥:

  1. 指定-J-cp -J/path/to/bcprov-jdk15on-$ver.jar

  2. 修改 JRE/conf/security/java.security 文件以将 org.bouncycastle.jce.provider.BouncyCastleProvider 的条目添加到提供程序列表中 -- 或者因为我不想修改我的 JRE,所以修改 copy 和使用-J-Djava.security.properties=$filename 指向它

  3. 指定-srcprovidername BC-destprovidername BC

此外,这不会将结果放入 JKS 文件中,因为 Bouncy 提供程序不支持 JKS。你为什么要JKS呢?仍受支持的所有 Java 版本都可以读取 PKCS12——但仅在使用 Bouncy 提供程序时才适用于 SM2,因此您需要在您的应用程序和/或它们的 JVM 中使用它。而且,一旦您读入密钥,无论如何您都需要 Bouncy 提供程序来对密钥执行任何操作——也许还有证书,我不确定何时解析它。

【讨论】:

  • 非常感谢您回答我的问题。我的评论太长了,所以我已经编辑了要回复的问题,我不确定你是否会收到通知,所以我发送了这条评论。