How to prove that one certificate is the issuer of other certificates

I have two certificates. One certificate is the issuer of another certificate.

how can I see with Java code that my issuer certificate is indeed an issuer?

I know that the AuthorityKeyIdentifier of my certificate and the SubjectKeyIdentifie of the issuer certificates must be the same. I am marked and they are the same .

but with java code I have this result:

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 "); 

and the result:

[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

and another array of bytes that MUST BE TESTED, BUT IT IS NOT at the beginning of the array another byte is added.

[ 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

question 1) Can I calculate key identifiers to get the same arrays ?

question 2) is there any other way to prove that one certificate is the issuer of other certificates .

+4
source share
2 answers

AuthorityKeyIdentifier and SubjectKeyIdentifier defined differently:

 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 )

Thus, simply comparing the extension values ​​cannot work, instead you need to extract the contents of the KeyIdentifier and compare them, for example. using helper classes BouncyCastle ASN.1.

BTW, actual key id bytes are just

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

4, 20 before this indicates an OCTET STRING of 20 bytes in length. In AuthorityKeyIdentifier 4 is replaced with the tag [0] (byte -128) due to implicit marking.

48, 22 before that in your AuthorityKeyIdentifier means (built) SEQUENCE 22 bytes long.

Etc. and etc.

Thus,

Is it possible to compute key identifiers to get the same arrays ?

Yes, go to the actual values ​​of the OCIET KeyIdentifier keywords.

there is another way to prove that one certificate is the issuer of other certificates

Well, you can verify that the signature in the certificate is signed with the private key associated with the proposed issuer certificate by checking this public key of the certificate.

PS: Regarding the question in the comments

- is the key identifier always 20? is this fixed? maybe not right?

No, it is not. The previously mentioned RFC 5280 says:

 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. 

I assume that your CA uses method 1 (160 bits = 20 bytes), but this is just a general method , not even explicitly , let alone required. Thus, no, you cannot count on the identifier having a length of 20 bytes.

PPS: Regarding the question in the comments

Not a signature, the only way to really prove that one certificate is issued by another?

This does not mean proving the relationship issued by the issuer, or simply proving (at least to a certain extent) that the private key associated with the issuer's proposed certificate signs a verified certificate, but there are situations when the same pair of private and public keys used in several certificates.

Essentially, you need to run a few extra tests, and even then you have to trust the CA to avoid doing weird things. Not so long ago. Swisscom changed one of its CA certificates to add an additional extension or critical attribute (I would have to look at the details, I think that someone who certified them has requested a change), and now it seems to issue a certificate signature authentication check a new CA certificate, even if the signatory certificate holders may not be aware of this new extension / critical attribute.

So in the end, real life is simply not as simple as we would like ...

+6
source

To prove that one certificate was issued by another, you must prove that it was signed with a private key corresponding to the public key in the certificate of issue.

Let name 2 certificates caCert and issuedCert . They are of type X509Certificate .

The Java code for validating issuedCert signed by the entity represented by caCert , which is fairly straightforward.

 PublicKey caPubKey = caCert.getPublicKey(); issuedCert.verify(caPubKey); 

If the verify method returns without exception, then issuedCert was signed with the private key corresponding to the caCert public key.

+4
source

Source: https://habr.com/ru/post/1493618/


All Articles