【问题标题】:What do I do when keytool.exe can't establish a certificate chain from my certs?当 keytool.exe 无法从我的证书建立证书链时,我该怎么办?
【发布时间】:2023-07-19 18:23:01
【问题描述】:

我正在使用有效的 Microsoft Active Directory 证书服务 (MS ADCS) PKI 的环境中工作。在那个环境中,我正在部署 this Java app,它使用 java 密钥库来管理其 https 服务器的密钥和证书。 de facto 管理工具似乎是keytool.exekeytool 的文档可以在 here 找到。

生成密钥对、创建证书请求和导入证书的一般推荐方法如下所示:

  1. 生成密钥对 keytool -genkey -keyalg RSA -keysize 2048 -alias securekey -keystore keystore

  2. 生成证书请求 keytool -certreq -alias securekey -keystore keystore -file NewCertRequest.csr

  3. 导入根证书 keytool -importcert -alias root -keystore keystore -file rootcert.csr

  4. 导入中间证书 keytool -importcert -alias intermediateX -keystore keystore -file intcert.csr 按顺序对每个中间证书重复此操作

  5. 导入新签署的证书 keytool -importcert -alias securekey -keystore keystore -file NewlySignedCert.csr

keytool和建立证书链

第 3 步建立trust anchorkeytool '打印' 证书供您审核,并要求您回答“是”以明确信任该证书。

第 4 步导入信任链中从根链接到新签名证书的中间证书。当您导入每个连续的从属中间证书时,keytool 会自动信任它们(或者至少应该信任它们)。 keytool 表明它具有到信任锚的完整证书路径(即步骤 3 中的根证书)的方式是微妙且薄弱的:

如果没有找到证书并且没有指定-noprompt选项,则打印出链中最后一个证书的信息,并提示用户进行验证。

对此的不成文推论如下:“如果 keytool 可以验证到信任锚的完整证书路径,它将打印出任何证书。”

您可以通过分别使用步骤 3 和 4 的 GeoTrust Global CAGoogle Internet Authority G2 证书来确认这一点。 (当您转到 https://www.google.com 时,在绿色锁后面找到这些证书。)keytool 将打印出根 GeoTrust Global CA 并要求您明确信任它。信任 GeoTrust Global CA 后,keytool 将导入 Google Internet Authority G2 而不打印任何证书,从而表明 keytool 信任 Google Internet Authority G2

keytool 无法链接我的 Microsoft ADCS 证书

当我尝试使用我的 MS ADCS 证书(a la 上面描述的 google 链)构建信任链时,keytool 无法建立信任链。我不确定确切的区别是什么,但是当keytool 在步骤 4 中打印出证书表明它没有建立到步骤 3 中已经受信任的根证书的信任链时,失败就出卖了.

怎么办?

鉴于keytool 似乎无法链接 MS ADCS 证书,对于我们环境中使用 java 密钥库管理密钥和证书的应用程序,我应该怎么做?

【问题讨论】:

  • 您是否考虑过使用其他证书类型? tomcat 应用程序可以接受其他密钥库类型,而不仅仅是JKSPKCS12 可能更适合您的需求(只需使用您可能已经拥有的 .pfx 文件)。如果您确实使用 tomcat,只需在 server.xml 文件中定义 KeystoreType
  • 这是一个有趣的建议。我不记得我走了多远。我将检查应用程序是否可以指定 KeystoreType。有问题的应用程序是APC 关闭网络服务器的专有应用程序。

标签: java active-directory certificate keytool


【解决方案1】:

使用 KeyStore 资源管理器

经过多次反复试验,我放弃了 keytool 链接 MS ADCS 证书。最终对我有用的方法是使用Keystore Explorer 摄取链接在一起的所有证书的“捆绑包”。

准备证书“捆绑”

keytool 的其他用户建议通过创建 base64 编码的 X.509 证书的串联来导入证书链。我怀疑这种文件格式有一个正确的官方名称,但我不确定它是什么。本质上,您最终会得到一个如下所示的文本文件:

-----BEGIN CERTIFICATE-----
MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
...
5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
...
yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx
-----END CERTIFICATE-----
...

文件中最底部的证书是根证书,上面是链中的第一个从属证书,它是第二个,一直到您正在使用的设备的新签名证书位于顶部。

所有这一切都可以通过使用 Windows 的内置加密外壳扩展导出证书来准备,以导出 base64 编码的 X.509 证书和记事本以连接它们。

尝试使用 keytool 导入包失败

我尝试像这样使用keytool 导入包:

keytool -importcert -alias securekey -keystore keystore -file bundle.cer

根据文档keytool 应该对此感到满意,但我收到此错误:

keytool error: java.lang.Exception: Incomplete certificate chain in reply

这并不奇怪。毕竟,这些证书是相同的证书,keytool 在单独导入证书时无法建立信任链。

使用“KeyStore Explorer”将 CA 回复导入密钥库

使用 KeyStore Explorer 打开密钥库(即问题和本答案中名为 keystore 的文件)。右键单击密钥对并选择 Import CA Reply 并将其指向您之前准备的 base64 编码 X.509 证书包。

至少在我的情况下,KeyStore Explorer 成功导入了 keytool 失败的 MS ADCS 证书包。导入包后,我可以继续使用 keytool 管理密钥库,最终依赖于其 https 服务器的密钥库的应用程序成功使用我们的 MS ADCS 证书。

【讨论】:

    【解决方案2】:

    我遇到了类似的问题(虽然我使用的是 VMware Linux 版本)并且能够使用以下类似的方法来解决问题: 要求(提供)的信息: - Putty 用于与 PCNS 服务器的 SSH 连接 - 用于来回传输文件的 FTP 客户端 - 内部 Microsoft ADCS - 最后我使用的是 APC PCNS 3.1 VMware

    有用的网址:http://www2.schneider-electric.com/resources/sites/SCHNEIDER_ELECTRIC/content/live/FAQS/176000/FA176886/en_US/Replacing%20the%20SelfSigned%20Cert%20on%20PowerChute_Linux.pdf

    • 修改文件“/opt/APC/PowerChute/group1/pcnsconfig.ini” o 在 [NetworkManagementCard] 部分添加行 KeystorePassword = your_password

    • 命令:service PowerChute stop

    • 命令:opt/APC/PowerChute/jre1.7.0_45/bin/keytool -genkey -alias securekey -keyalg RSA -keystore /opt/APC/PowerChute/group1/keystore -keysize 2048

    • 命令:opt/APC/PowerChute/jre1.7.0_45/bin/keytool -certreq -alias securekey -keystore /opt/APC/PowerChute/group1/keystore -file /opt/APC/PowerChute/group1/newpowerchute。企业社会责任

    • 将证书链 (*.cer) 组合成 1 个捆绑文件 (bundle.cer):Web 服务器(顶部)、中间(中间)、根(底部)

    • 命令:opt/APC/PowerChute/jre1.7.0_45/bin/keytool -import -trustcacerts -alias securekey -file /opt/APC/PowerChute/group1/bundle.cer -keystore /opt/APC/PowerChute/ group1/密钥库

    • 命令:服务 PowerChute 启动

    问候,

    杰米

    【讨论】:

    • 我认为您省略了签署 newpowerchute.csr 的步骤。您是如何做到这一点的?
    • 我还想知道您是如何确认您的最终 keytool -import 命令成功的。 Keytool -import 喜欢默默地失败。
    • 创建“newpowerchute.csr”文件并将其通过 FTP 传输到我的 Windows 计算机后,我使用默认 Web 服务器将文件内容复制并粘贴到我的内部 Microsoft AD CA 网页中模板。 CA 自动接受了请求,我下载了 Base 64 编码证书。
    • 至于最后使用keytool导入。当命令运行时,它有详细的输出,我看到链中的所有证书都在那里。您还可以使用 keytool 运行“列表”开关,查看密钥库中有哪些证书。
    • 有趣的是,keytool 成功导入了在我的案例中失败的捆绑证书。感谢您提供详细信息。
    【解决方案3】:

    PCNS Windows 用户注意事项:

    要求:将有效的第三方证书安装到 PCNS 网络服务器 (TCP:6547)

    PKI 方案:根 CA -> 颁发 CA -> Web 服务器

    PCNS Security Handbook.pdf 中的“附录:替换默认 PowerChute SSL 证书”一章表明我们需要遵循以下步骤:

    1. 为 Java 密钥库文件“C:\Program Files\APC\PowerChute\group1\keystore”配置密码[GOOD]
    2. 删除现有的密钥库文件“C:\Program Files\APC\PowerChute\group1\keystore”[STANGE/GOOD]
    3. 为密钥库文件“C:\Program Files\APC\PowerChute\group1\keystore”生成新的 RSA 密钥[GOOD]
    4. 为密钥库文件“C:\Program Files\APC\PowerChute\group1\keystore”生成新的 CSR [不完美/好]
    5. 使用 openssl 使用自签名 CA 签署 CSR [不完美]
    6. 将根 CA 导入密钥库文件“C:\Program Files\APC\PowerChute\group1\PowerShute-keystore”[奇怪/导致错误]
    7. 将根 CA 签名的证书导入密钥库文件“C:\Program Files\APC\PowerChute\group1\PowerShute-keystore”[奇怪/导致错误]

    按照官方定义的程序后,我未能将企业 CA 签名证书安装到 PCNS Web 服务器。如果我们在“keystore”文件中生成 RSA 密钥,我什至无法理解为什么我们需要使用“PowerChute-keystore”文件进行证书导入过程

    我创建了以下适用于我的环境的程序。所有命令都是在具有提升权限的 PowerShell 中执行的,因为 keytool.exe 需要管理员权限才能从密钥库文件中删除条目。我使用了 Microsoft 的外部 OpenJDK,它安装了 JAVA_HOME 环境变量。示例密钥库密码设置为 changeme123,但最好使用另一个密码。企业 CA 配置了自动批准有效证书请求。使用 GPO 将企业 CA 和根 CA 证书添加到所有域客户端上的信任存储中

    # Java keystore password
    $jksPwd = 'changeme123'
    
    # Current host DNS name (hostname)
    $hostNameShort = $env:COMPUTERNAME.ToLower()
    
    # Current host DNS name (FQDN)
    $hostNameLong = $env:COMPUTERNAME.ToLower() + '.' + $env:USERDNSDOMAIN.ToLower()
    
    # Current host IP address
    $hostIp = (Get-NetIPAddress -AddressFamily IPV4 -InterfaceAlias 'Ethernet0').IPAddress
    
    # Enterprise PKI template name (web server)
    $pkiTpl = 'WebServer'
    
    # Enterprise PKI server FQDN
    $pkiHost = 'entpki.example.com'
    
    # Enterprise PKI server subject
    $pkiSubj = 'Example Issuing CA'
    
    # Get to the PCNS group1 folder
    Set-Location -Path 'C:\Program Files\APC\PowerChute\group1\'
    
    # Migrate keystore from JKS to PKCS12 format (there was a warning to use newer format for keystore file which I choose to follow up)
    & "${env:JAVA_HOME}bin\keytool.exe" -importkeystore -srckeystore keystore -destkeystore keystore -deststoretype pkcs12 -srcstorepass $jksPwd
    
    # Delete current certificate with key (requires Admin privileges)
    & "${env:JAVA_HOME}bin\keytool.exe" -delete -alias securekey -keystore keystore -storepass $jksPwd
    
    # Generate new keys and CSR
    & "${env:JAVA_HOME}bin\keytool.exe" -genkeypair -alias securekey -keyalg RSA -keysize 2048 -dname "CN=${hostNameShort}, OU=IT, O=Example, L=City, ST=State, C=CT" -ext "SAN=dns:${hostNameLong},dns:${hostNameShort},ip:${hostIp}" -validity 365 -keypass $jksPwd -keystore keystore -storepass $jksPwd
    & "${env:JAVA_HOME}bin\keytool.exe" -certreq -alias securekey -file "$env:TEMP\${hostNameShort}.csr" -keystore keystore -dname "CN=${hostNameShort}, OU=IT, O=Example, L=City, ST=State, C=RU" -ext "SAN=dns:${hostNameLong},dns:${hostNameShort},ip:${hostIp}" -storepass $jksPwd
    
    # Sign CSR and retrieve P7B
    & "certreq.exe" -submit -f -q -attrib "CertificateTemplate:${pkiTpl}" -config "${pkiHost}\${pkiSubj}" "$env:TEMP\${hostNameShort}.csr" "$env:TEMP\${hostNameShort}.crt" "$env:TEMP\${hostNameShort}.p7b" "$env:TEMP\${hostNameShort}.rsp"
    
    # Import P7B
    & "${env:JAVA_HOME}bin\keytool.exe" -import -noprompt -trustcacerts -alias securekey -file "$env:TEMP\${hostNameShort}.p7b" -keystore keystore -storepass $jksPwd
    

    导入证书包的一般问题与 keystore.exe 文件本身有关。似乎存在某种阻止导入有效证书链(CRT+CRT+CRT)的错误。根据 keytool 源代码,该实用程序还支持导入 P7B 文件。其他工具,如 KeyStore Explorer 可能可以解决这个问题,但它们需要在企业系统上安装/使用

    更新:修复了密钥库和 CSR 中的 SAN 字段

    【讨论】:

      最近更新 更多