Certificate super detailed parsing of cer Certificate (serial number, issuer, public key, etc.)

We generally say that certificate is digital certificate: digital certificate refers to a digital authentication that marks the identity information of all communication parties in Internet communication. People can use it to identify each other on the Internet

There are generally two kinds: PFX certificate and CER certificate

PFX certificate:
Defined by Public Key Cryptography Standards #12 and PKCS#12 standards, it contains the certificate form in binary format of public key and private key, with pfx as the suffix of the certificate file.

Generally, there are many RSA certificates. Now the domestic RSA root certificate has expired, and some enterprises have not used it.

SM2 certificate:
1. Binary coded certificate
There is no private key in the certificate. The certificate file is in the binary format of DER encoding, with cer as the suffix of the certificate file.
2.Base64 encoded certificate
There is no private key in the certificate. The certificate file in BASE64 encoding format also takes cer as the suffix of the certificate file.

Generally referred to as SM2 certificate, also known as cer certificate

Now let's focus on SM2 certificate
Application process:
Generally, individuals / enterprises generate csr files on the device and submit them to Ca together with identity information. CA will make a certificate for you. This certificate has certain legal effect.

Certificate information
Generally, the CA returns the base64 encoded form of the certificate, which is directly saved to Notepad for reference At the end of cer, double-click to see the relevant information of the certificate

The following is an example of a certificate:


Whether you can see the relevant information of the certificate.

We can use certificates for signature verification, encryption and decryption and other operations; We will also extract the relevant information of the certificate.

Here's the focus. Let's talk about how to obtain the relevant information of the certificate, which is the top priority of this article

We cannot resolve certificates without a dependent package, which is the bc package. This bc package is very important

		<dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.64</version>
        </dependency>

Some methods in this bc package, such as Certificate, are specially used for Certificate services, which are essential in the Certificate industry and engineering

step

  1. Convert certificate base64 encoding to byte type
byte[] buffer = Base64.decodeBase64(certBase64);

2. Convert byte to normal stream

ByteArrayInputStream bIn = new ByteArrayInputStream(buffer);

3. Specific stream type required to convert ordinary stream to certificate service

ASN1InputStream dIn = new ASN1InputStream(bIn);
ASN1Sequence asq = (ASN1Sequence) dIn.readObject();

4. Transfer certificate

 Certificate certificate = Certificate.getInstance(asq);

5. Analyze the contents of the certificate

//            Serial number resolution
            String serialNo = certificate.getSerialNumber().getValue().toString(16);
            System.out.println("serial number:" + serialNo);

Parsing signature algorithm: generally, the actual signature algorithm of a certificate is a string, but what is parsed is a specific form. This specific form is used internationally to represent a certain algorithm, so we should pay special attention to it

// Signature algorithm 1.2.156.10197.1.501 represents SM2 algorithm
            String algorithm = certificate.getSignatureAlgorithm().getAlgorithm().toString();
            System.out.println("algorithm:" + algorithm);
 // Issuer
            String issuer = certificate.getIssuer().toString();
            System.out.println("Issuer:" + issuer);

The parsed time is of date type. If you don't want the date type but get the string type, you must pay attention to: what you get is a string in GMT format. The string is 8 hours different from the actual background time, so you should get the date in the same way and then convert the format

DateUtils.getDateString is a time conversion tool class written by myself. I'll post it in the next article.

Date startTime = certificate.getStartDate().getDate();
            String startTimeStr = DateUtils.getDateString(startTime, "yyyy-MM-dd HH:mm:ss");
            System.out.println("term of validity:" + startTimeStr);
Date endTime = certificate.getEndDate().getDate();
            String endTimeStr = DateUtils.getDateString(endTime, "yyyy-MM-dd HH:mm:ss");
            System.out.println("Expiration date:" + endTimeStr);

This is to get the CN item in the user. If you don't want CN but want to get the whole user, you can go directly to certificate Until getsubject()

org.bouncycastle.asn1.x500.RDN rdn = certificate.getSubject().getRDNs(BCStyle.CN)[0];
            String cn = rdn.getFirst().getValue().toString();
            System.out.println("CN:" + cn);

This is the analysis of public key, which is generally important. The public key format of each CA may be different, so the results obtained are slightly different, that is, whether the prefix is marked with: 04

DERBitString publicKeyData = certificate.getSubjectPublicKeyInfo().getPublicKeyData();
            String publicKeyDataStr = publicKeyData.toString().replaceAll("#034200", "");
            System.out.println("Public key:" + publicKeyDataStr);

Additional parsing: now the mainstream CA will have a home extension, which is oid. Sometimes we need to parse the value of oid. The oid is usually parsed in a circular way.

			Extensions exes=  certificate.getTBSCertificate().getExtensions();
            ASN1ObjectIdentifier[] list = exes.getExtensionOIDs();

            for (ASN1ObjectIdentifier a:list) {

                Extension el = exes.getExtension(a);

                String oid = el.getExtnId().toString();
                String value = new String(el.getExtnValue().getOctets());

                System.out.println("oid:" + oid + "->" + "value:" + value);
            }

Special note: in the extensions, we resolve all extensions. The value of some extensions is garbled. At present, we don't know what coding format these extensions of each CA are. I've tried the mainstream coding format, but it doesn't work. It's all random code. Only pure string is normal.

Let's see the actual effect:

As the certificate is an important thing, it is generally not disclosed casually, so the important information has been coded and known.

There are two types of extensions commonly used: personal extension and enterprise extension, both of which have international standards
Personal identification code
oid fixation: 1.2.156.10260.4.1.1
Enterprise organization code
oid fixed: 1.2.156 10260.4.1.4

This is practiced by yourself. At present, the detailed analysis method is not known on various websites. Respect the original, thank you!!

Finally, attach all the source code

package jp.utils;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.Extensions;

import java.io.ByteArrayInputStream;
import java.util.Date;

public class DecodeCertUtils {

    public static void main(String[] args) {

        String certBase64 = "";

        try {

            byte[] buffer = Base64.decodeBase64(certBase64);
            ByteArrayInputStream bIn = new ByteArrayInputStream(buffer);
            ASN1InputStream dIn = new ASN1InputStream(bIn);
            ASN1Sequence asq = (ASN1Sequence) dIn.readObject();

            Certificate certificate = Certificate.getInstance(asq);

            Extensions exes=  certificate.getTBSCertificate().getExtensions();
            ASN1ObjectIdentifier[] list = exes.getExtensionOIDs();

            for (ASN1ObjectIdentifier a:list) {

                Extension el = exes.getExtension(a);

                String oid = el.getExtnId().toString();
                String value = new String(el.getExtnValue().getOctets());

                System.out.println("oid:" + oid + "->" + "value:" + value);
            }

//            Serial number resolution
            String serialNo = certificate.getSerialNumber().getValue().toString(16);
            System.out.println("serial number:" + serialNo);

            // Signature algorithm 1.2.156.10197.1.501 represents SM2 algorithm
            String algorithm = certificate.getSignatureAlgorithm().getAlgorithm().toString();
            System.out.println("algorithm:" + algorithm);

            // Issuer
            String issuer = certificate.getIssuer().toString();
            System.out.println("Issuer:" + issuer);

            Date startTime = certificate.getStartDate().getDate();
            String startTimeStr = DateUtils.getDateString(startTime, "yyyy-MM-dd HH:mm:ss");
            System.out.println("term of validity:" + startTimeStr);

            Date endTime = certificate.getEndDate().getDate();
            String endTimeStr = DateUtils.getDateString(endTime, "yyyy-MM-dd HH:mm:ss");
            System.out.println("Expiration date:" + endTimeStr);

            org.bouncycastle.asn1.x500.RDN rdn = certificate.getSubject().getRDNs(BCStyle.CN)[0];
            String cn = rdn.getFirst().getValue().toString();
            System.out.println("CN:" + cn);

            DERBitString publicKeyData = certificate.getSubjectPublicKeyInfo().getPublicKeyData();
            String publicKeyDataStr = publicKeyData.toString().replaceAll("#034200", "");
            System.out.println("Public key:" + publicKeyDataStr);

            bIn.close();
            dIn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Keywords: Java Data Analysis security Web Security

Added by evdawg80 on Wed, 02 Mar 2022 12:28:49 +0200