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

Certificate 如何证明一个证书是另一个证书的颁发者,certificate,x509certificate,bouncycastle,x509,digital-certificate,Certificate,X509certificate,Bouncycastle,X509,Digital Certificate,我有两张证书。一个证书是另一个证书的颁发者 我如何用java代码看到我的颁发者证书是真正的颁发者 我知道我的证书的AuthorityKeyIdentifier和颁发者证书的SubjectKeyIdentificate必须相同。我选中了,它们是相同的 但对于java代码,我得到了这样的结果: CertificateFactory certFactory=CertificateFactory.getInstance(“X.509”); InputStream usrCertificateIn=新文件

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

我如何用java代码看到我的颁发者证书是真正的颁发者

我知道我的证书的AuthorityKeyIdentifier和颁发者证书的SubjectKeyIdentificate必须相同。我选中了,它们是相同的

但对于java代码,我得到了这样的结果:

CertificateFactory certFactory=CertificateFactory.getInstance(“X.509”);
InputStream usrCertificateIn=新文件InputStream(“/usr.cer”);
X509Certificate cert=(X509Certificate)certFactory.generateCertificate(usrCertificateIn);
InputStream SiningCACertificateIn=新文件InputStream(“/siningCA.cer”);
X509证书颁发者=(X509证书)certFactory.generateCertificate(SiningCACertificateIn);
字节[]八位字节=(ASN1OctetString.getInstance(cert.getExtensionValue(“2.5.29.35”)).getOctets());
System.out.println(Arrays.toString(八位字节)+“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((array.toString(八位字节)+“bouncycastle,subjectKeyIdentified”);
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

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

[strong>4,20,52,105,49,70,24,78,127,113,25,55,39,99,46,6,31,66,55,86,79,113]bouncycastle,SubjectKeyIdentification

[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,SubjectKeyIdentification

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

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

AuthorityKeyIdentifier
SubjectKeyIdentifier
的定义不同:

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

SubjectKeyIdentifier ::= KeyIdentifier

KeyIdentifier ::= OCTET STRING
(第4.2.1.1节和第4.2.1.2节)

因此,仅仅比较扩展值是行不通的,相反,您必须提取
KeyIdentifier
内容并进行比较,例如使用BouncyCastle ASN.1帮助类

顺便说一句,实际的密钥标识符字节仅为

52, -105, 49, -70, -24, 78, 127, -113, -25, 55, 39, 99, 46, 6, 31, 66, -55, -86, -79, 113
前面的4,20表示八位字节字符串,长度为20字节。在AuthorityKeyIdentifier中,由于隐式标记,4被标记[0](字节-128)替换

AuthorityKeyIdentifier中前面的48、22表示(构造的)序列,22字节长

等等等等

因此,

我可以计算键标识符以获得相同的数组吗


是,向下钻取到实际的KeyIdentifier八位字节字符串值

是否有其他方法证明一个证书是另一个证书的颁发者

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

PS:关于评论中的问题

密钥标识符的长度是否始终为20?修好了吗?可能是不,不是吗

不,不是。前面提到的是:

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

PPS:关于评论中的问题


签名不是证明一个证书是由另一个证书颁发的唯一方法吗

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

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


因此,最终现实生活并不像人们希望的那么简单…

要证明一个证书是由另一个证书颁发的,您应该证明它是由颁发证书中的公钥对应的私钥签署的

让我们调用两个证书
caCert
issuedCert
。这些证书的类型为
X509Certificate

证明
issuedCert
caCert
表示的实体签名的Java代码非常简单

PublicKey caPubKey = caCert.getPublicKey();

issuedCert.verify(caPubKey);
如果该方法返回时未引发异常,则
issuedCert
为signe
PublicKey caPubKey = caCert.getPublicKey();

issuedCert.verify(caPubKey);