certificate - 如何证明一个证书是另一证书的颁发者

标签 certificate x509certificate bouncycastle x509 digital-certificate

我有两张证书。一个证书是另一证书的颁发者。

我怎样才能用java代码看到我的颁发者证书确实是颁发者?

我知道我的证书的AuthorityKeyIdentifier 和颁发者证书的SubjectKeyIdentifie 必须相同。我检查过,它们相同

但是使用 java 代码我得到了这个结果:

    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");

    InputStream usrCertificateIn = new FileInputStream("/usr.cer");
    X509Certificate cert = (X509Certificate) certFactory.generateCertificate(usrCertificateIn);

    InputStream SiningCACertificateIn = new FileInputStream("/siningCA.cer");
    X509Certificate issuer = (X509Certificate) certFactory.generateCertificate(SiningCACertificateIn);

    byte[] octets = (ASN1OctetString.getInstance(cert.getExtensionValue("2.5.29.35")).getOctets());     
    System.out.println(Arrays.toString(octets) + " bouncycastle, AuthorityKeyIdentifier");
    System.out.println(Arrays.toString(cert.getExtensionValue("2.5.29.35")) + "java.security, AuthorityKeyIdentifier");

    octets = ASN1OctetString.getInstance(issuer.getExtensionValue("2.5.29.14")).getOctets();
    System.out.println((Arrays.toString(octets) + "bouncycastle, SubjectKeyIdentifie "));
    System.out.println(Arrays.toString(issuer.getExtensionValue("2.5.29.14")) + "java.security, SubjectKeyIdentifie ");

结果是:

[48, 22, -128, 20, 52, -105, 49, -70, -24, 78, 127, -113, -25, 55, 39, 99, 46, 6, 31 , 66, -55, -86, -79, 113] bouncycaSTLe, AuthorityKeyIdentifier

[4、24、48、22、-128、20、52、-105、49、-70、-24、78、127、-113、-25、 55, 39, 99, 46, 6, 31, 66, -55, -86, -79, 113]java.security,AuthorityKeyIdentifier

另一个字节数组必须相同,但不同在数组的开头添加另一个字节。

[4、20、52、-105、49、-70、-24、78、127、-113、-25、55、39、99、46、6、31、66、-55 ,-86,-79,113]bouncycaSTLe,SubjectKeyIdentifie

[4, 22, 4, 20, 52, -105, 49, -70, -24, 78, 127, -113, -25, 55, 39, 99, 46, 6, 31, 66、-55、-86、-79、113]java.security,SubjectKeyIdentifie

问题1) 我可以计算关键标识符以获得相同的数组吗?

问题2) 是否有另一种方法可以证明一个证书是另一个证书的颁发者

最佳答案

AuthorityKeyIdentifierSubjectKeyIdentifier 的定义不同:

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

SubjectKeyIdentifier ::= KeyIdentifier

KeyIdentifier ::= OCTET STRING

(sections 4.2.1.1 and 4.2.1.2 of RFC 5280)

因此,仅仅比较扩展值是行不通的,您必须提取 KeyIdentifier 内容并比较它们,例如使用 BouncyCaSTLe ASN.1 帮助器类。

顺便说一句,实际的 key 标识符字节只是

52, -105, 49, -70, -24, 78, 127, -113, -25, 55, 39, 99, 46, 6, 31, 66, -55, -86, -79, 113

前面的4、20表示一个OCTET STRING,20字节长。在 AuthorityKeyIdentifier 中,由于隐式标记,4 被标记 [0](字节 -128)替换。

AuthorityKeyIdentifier 中的 48、22 表示(构造的)SEQUENCE,22 字节长。

等等。等等

因此,

Can I calculates the key Identifiers to get the same Arrays?

是的,深入了解实际的 KeyIdentifier OCTET STRING 值。

is there another way in order to prove that one certificate is issuer of another certificates

那么,您可以通过验证该证书的公钥来检查证书中的签名是否由与假定的颁发者证书关联的私钥签名。

PS:关于评论中的问题

is key identifier's length always 20? is it fixed? may be no, is not it?

不,事实并非如此。前面提到的RFC 5280说:

For CA certificates, subject key identifiers SHOULD be derived from
the public key or a method that generates unique values.  Two common
methods for generating key identifiers from the public key are:

  (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
       value of the BIT STRING subjectPublicKey (excluding the tag,
       length, and number of unused bits).
  (2) The keyIdentifier is composed of a four-bit type field with
       the value 0100 followed by the least significant 60 bits of
       the SHA-1 hash of the value of the BIT STRING
       subjectPublicKey (excluding the tag, length, and number of
       unused bits).

Other methods of generating unique numbers are also acceptable.

我假设您的 CA 使用方法 1(160 位 = 20 字节),但这只是一种常见方法,甚至不是明确推荐的方法,更不用说必需。因此,不,您不能指望标识符的长度为 20 个字节。

PPS:关于评论中的问题

Isn't the signature the only way to truly prove one cert is issued by another?

这也不是颁发者与颁发者关系的证明,它只是证明(至少在某种程度上)与假定的颁发者证书关联的私钥签署了检查的证书,但有在多个证书中使用相同的私钥-公钥对的情况。

本质上,您需要进行多个补充测试,即使如此,也必须相信 CA 不会做奇怪的事情。不久前,例如Swisscom 更改了他们的 CA 证书之一以包含额外的扩展或关键属性(我必须查找详细信息;我认为证明他们的人要求进行更改),并且通过证书签名验证测试,旧的签名者证书现在似乎由新的 CA 证书颁发,即使签名者证书的所有者可能不知道该新的扩展/关键属性。

所以最终现实生活并不像人们希望的那么简单......

关于certificate - 如何证明一个证书是另一证书的颁发者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17877412/

相关文章:

iOS - 将证书添加到应用程序

azure - 允许我从 key 保管库读取证书的最小 Azure 角色 (RBAC) 是什么?

Java 的 BouncyCaSTLe 并不总是验证 OpenSSL ECDSA 签名

java - 在 Java 中读取 OpenSSL 生成的 PEM/DER 格式的 S/MIME 消息

iphone - 过期证书 iPhone "in house"企业部署

ssl - 使用 openssl 创建由中间证书签名的新 TLS 证书

ssl - 您可以同时在同一个商店中拥有多个有效的 SSL 证书吗?

java - X500Principal Distinguished Name 命令

ios - App Store证书/ key 对代码签名过程中是否存在 "screw it up permanently"情况?

java - 从信任库验证 Java 中的证书链