【问题标题】:How to know which X509 Certificate Signed another Certificate (Java)如何知道哪个 X509 证书签署了另一个证书 (Java)
【发布时间】:2023-04-08 12:52:02
【问题描述】:

在我的示例中有三个证书,假设它们形成一个链,但我还不知道它们中的哪一个签署了哪个:

X509Certificate c1 = ....
X509Certificate c2 = ....
X509Certificate c2 = ....

我想知道哪个证书负责签署另一个证书。

计划是获取“AuthorityKeyIdentifier”并将其与“SubjectKeyIdentifier”匹配。

import org.bouncycastle.asn1. DEROctetString;

private static String decodeKey(byte[] e) {
    DEROctetString octet = new DEROctetString(e);
    return octet.toString();
}

String subjectKeyId = decodeKey(c.getExtensionValue("2.5.29.14"));
String authorityKeyId = decodeKey(c.getExtensionValue("2.5.29.35"));

我得到以下证书(按链的顺序):主题/授权密钥 ID 对

SubjectKeyIdentifier和AuthorityKeyIdentifier解码后的取值:

证书1:(链的末端)

#0416041482b7384a93aa9b10ef80bbd954e2f10ffb809cde
#04183016801482b7384a93aa9b10ef80bbd954e2f10ffb809cde

证书 2:由证书 1 签名

#04160414ab8059c365836d1d7d13bd19c3ec1a8f0d476aa3
#04183016801482b7384a93aa9b10ef80bbd954e2f10ffb809cde

证书 3:由证书 2 签名

(no SubjectKeyIdentifier - null bytes)
#041830168014ab8059c365836d1d7d13bd19c3ec1a8f0d476aa3

格式化和对齐以便于阅读(与顶部相同)

------------------------------------------------------------------------------
       01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
------------------------------------------------------------------------------
Certificate 1
#04 16 04 14       82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de
#04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de

Certificate 2
#04 16 04 14       ab 80 59 c3 65 83 6d 1d 7d 13 bd 19 c3 ec 1a 8f 0d 47 6a a3
#04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de

Certificate 3
=== == == == == == == == == == == NO DATA  == == == == == == == == == == == ==
#04 18 30 16 80 14 ab 80 59 c3 65 83 6d 1d 7d 13 bd 19 c3 ec 1a 8f 0d 47 6a a3

我期待 c3 的 AuthorityKeyIdentifier 等同于 c2 的 SubjectKeyIdentifier。这里似乎不是这样。

编辑:结果的某些部分似乎匹配,我对“SubjectKeyIdentifier”有一些想法 - 它总是以“#04”开头,后跟内容的长度(以十六进制表示)。我现在对如何解码“SubjectKeyIdentifier”有了一定的了解,但“AuthorityKeyIdentifier”对我来说仍然是一个很大的谜。

相关SO post

我的解码有什么问题吗? 为什么 AuthorityKeyIdentifier 与签署它的证书的 SubjectKeyIdentifier 不匹配?

【问题讨论】:

  • 你能把证书本身发给我们分析吗?

标签: java certificate x509 decoding subject


【解决方案1】:

如果您查看 RFC5280 中 SKI 和 AKI 的 ASN.1 定义(按照您问题中的链接),差异就很明显了:

SubjectKeyIdentifier ::= KeyIdentifier

AuthorityKeyIdentifier ::= SEQUENCE {
  keyIdentifier             [0] KeyIdentifier           OPTIONAL,
  authorityCertIssuer       [1] GeneralNames            OPTIONAL,
  authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }

KeyIdentifier ::= OCTET STRING

因此,AKI 不是八位字节串,而是三个可选元素的序列。这些元素之一是可以与 SKI 进行比较的八位字节字符串。

Distinguished Encoding Rules (DER) 确定这些 ASN.1 结构的字节表示。 AKI 扩展的各个字节具有以下含义(请参阅A Layman's Guide to a Subset of ASN.1, BER, and DER):

04 18 30 16 80 14 82 b7 38 4a 93 aa 9b 10 ef 80 bb d9 54 e2 f1 0f fb 80 9c de

04 OCTET STRING
18 LENGTH
30 SEQUENCE
16 LENGTH
80 CONTEXT-SPECIFIC PRIMITIVE TAG 0
14 LENGTH
.. DATA

前两个字节(04 18)是扩展结构的一部分(如相关问题Why doesn't my key identifier match?中所述),实际的AKI扩展内容从“30 16”开始。

您用于解码 AKI 的 Java 代码应如下所示(使用 Bouncy Castle):

byte[] extensionValue = cert.getExtensionValue("2.5.29.35");
byte[] octets = DEROctetString.getInstance(extensionValue).getOctets();
AuthorityKeyIdentifier authorityKeyIdentifier = AuthorityKeyIdentifier.getInstance(octets);
byte[] keyIdentifier = authorityKeyIdentifier.getKeyIdentifier();
String keyIdentifierHex = new String(Hex.encode(keyIdentifier));

对于解码 SKI:

extensionValue = cert.getExtensionValue("2.5.29.14");
octets = DEROctetString.getInstance(extensionValue).getOctets();
SubjectKeyIdentifier subjectKeyIdentifier = SubjectKeyIdentifier.getInstance(octets);
keyIdentifier = subjectKeyIdentifier.getKeyIdentifier();
keyIdentifierHex = new String(Hex.encode(keyIdentifier));

另外,这两个扩展都是可选的。如果您的代码应该使用任意证书,则需要使用回退机制(例如验证签名)。

【讨论】:

  • 感谢您提供非常详细的答案。昨天一个队友想通了,这正是我得到的解释。接受为答案。我对使用 java 的加密/安全模块仍然很陌生,现在它开始变得有意义了。
  • 不只是作为后备,您应该始终检查 child.Issuer 等于 parent.Subject;可以回溯到 v1,根本没有扩展。 AKI/SKI 如果存在应该是一项额外的检查,并且在一个 CA 拥有多个证书的情况下可能会有所帮助(尽管这通常是一个密钥的多个证书,而不是多个密钥的证书)。
【解决方案2】:

如果您正在寻找快速检查,只需在 Windows 中打开证书并查找名为“Certification Path”的选项卡。如果适用,它还可以让您轻松遍历证书链。 (我会发布一张图片,但显然还没有足够的声誉。)

【讨论】:

    猜你喜欢
    • 2016-08-24
    • 2018-04-22
    • 2018-07-13
    • 2019-04-12
    • 2017-12-23
    • 1970-01-01
    • 2013-08-07
    • 2019-07-16
    • 2020-05-27
    相关资源
    最近更新 更多