X.509 Certificate Structure and Analysis Methods


Introduction

X.509 certificates are widely deployed in JDK applications to support authentication and other functionality in security systems. An X.509 certificate is comprised of a number of fields. Some of the more common fields include (RFC 1422):

  1. Version: Specifies the version of the X.509 standard the certificate complies with.

  2. Serial Number: A unique identifier assigned to the certificate by the certificate authority (CA). This helps to identify a certificate.

  3. Signature (Algorithm ID and Parameters): The algorithm used to sign the certificate, along with any parameters needed for that signature algorithm (such as RSA or ECDSA).

  4. Issuer Name: The name of the entity that issued the certificate, typically a CA. This is often represented as a Distinguished Name (DN).

  5. Validity Period: The time span during which the certificate is valid, including a “Not Before” date and an “Expires On” date.

  6. Subject Name: The entity (individual, organization, or system) to whom the certificate is issued. This is also usually represented as a Distinguished Name (DN).

  7. Subject Public Key (and Associated Algorithm ID): The public key corresponding to the subject’s private key, along with the algorithm used (such as RSA or ECDSA).

The values of these fields have an impact on the underlying security configurations in the environments where they are used. As a result, it’s useful to know the structures of the certificates in use in a Java application. The validity period of a certificate, for example, is an important piece of data because expired certificates can often lead to production-down scenarios. The issue is exacerbated by the fact that expiry dates can often catch administrators off guard by disrupting production applications from a specific date onwards.

This page describes three methods for obtaining X.509 certificate information: the keytool command, JDK Debug Logs, and Java Flight Recorder events.


keytool

The keytool command is a command-line utility provided by Java for managing keystores, keys, and certificates, including the ability to view certificate details. It allows users to manage their public/private key pairs and associated certificates. These keys and certificates can be used for various purposes, such as:

  • Self-authentication: Enabling a user to authenticate themselves to other users or services.
  • Data integrity and authentication: Ensuring the integrity and authenticity of data through digital signatures.

In addition, keytool allows users to store and manage the public keys (in the form of certificates) of their communicating peers, enabling secure communication through public key infrastructure (PKI).

From a static analysis point of view, keytool can be used to query certificates. The keytool binary can be found in the <JDK_HOME>/bin/ folder.

    $keytool  -help

    Key and Certificate Management Tool

    Commands:

     -certreq            Generates a certificate request
     -changealias        Changes an entry's alias
     -delete             Deletes an entry
     -exportcert         Exports certificate
     -genkeypair         Generates a key pair
     -genseckey          Generates a secret key
     -gencert            Generates certificate from a certificate request
     -importcert         Imports a certificate or a certificate chain
     -importpass         Imports a password
     -importkeystore     Imports one or all entries from another keystore
     -keypasswd          Changes the key password of an entry
     -list               Lists entries in a keystore
     -printcert          Prints the content of a certificate
     -printcertreq       Prints the content of a certificate request
     -printcrl           Prints the content of a CRL file
     -storepasswd        Changes the store password of a keystore
     -showinfo           Displays security-related information
     -version            Prints the program version

    Use "keytool -?, -h, or --help" for this help message
    Use "keytool -command_name --help" for usage of command_name.
    Use the -conf <url> option to specify a pre-configured options file.

For example, to view verbose details about every certificate contained in the default JDK truststore (<JDK_HOME>/lib/security/cacerts in JDK 9 and later), use the following command:

$keytool -keystore <path_to_cacerts> -list -storepass changeit -v

The default cacerts keystore password is “changeit”.

More Information To learn more, see the keytool documentation for your version of the JDK:

Or see our tutorials on Oracle LiveLabs:

JDK Debug Logs

While the previous methods are useful for analyzing certificates stored in a specific keystore or truststore, what about retrieving details of certificates currently in use by a JDK application? JDK debug logs can be enabled to provide detailed information about the Java runtime’s handling of certificates, including SSL/TLS connections.

The -Djava.security.debug=certpath and -Djavax.net.debug=all debug system properties are useful for printing verbose X.509 certificate information to standard error stream during the lifetime of a JDK application. The application should be configured to launch with these system properties if such debugging information is required.

Details of X.509 certificates encountered are printed during certificate path validation attempts:

      Trusted CA cert: [
    [
      Version: V3
      Subject: CN=DigiCert Global Root CA, OU=<DOMAIN_NAME>, O=DigiCert Inc, C=US
      Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

      Key:  Sun RSA public key, 2048 bits
      params: null
      modulus: 28559384442792876273280274398620578979733786817784174960112400169719065906301471912340204391164075730987771255281479191858503912379974443363319206013285922932969143082114108995903507302607372164107846395526169928849546930352778612946811335349917424469188917500996253619438384218721744278787164274625243781917237444202229339672234113350935948264576180342492691117960376023738627349150441152487120197333042448834154779966801277094070528166918968412433078879939664053044797116916260095055641583506170045241549105022323819314163625798834513544420165235412105694681616578431019525684868803389424296613694298865514217451303
      public exponent: 65537
      Validity: [From: Fri Nov 10 00:00:00 UTC 2006,
                   To: Mon Nov 10 00:00:00 UTC 2031]
      Issuer: CN=DigiCert Global Root CA, OU=<DOMAIN_NAME>, O=DigiCert Inc, C=US
      SerialNumber: [    083be056 904246b1 a1756ac9 5991c74a]

Certificate details are also printed during TLS handshake messages:

       "certificate" : {
        "version"            : "v3",
        "serial number"      : "083BE056904246B1A1756AC95991C74A",
        "signature algorithm": "SHA1withRSA",
        "issuer"             : "CN=DigiCert Global Root CA, OU=<DOMAIN_NAME>, O=DigiCert Inc, C=US",
        "not before"         : "2006-11-10 24:00:00.000 UTC",
        "not  after"         : "2031-11-10 24:00:00.000 UTC",
        "subject"            : "CN=DigiCert Global Root CA, OU=<DOMAIN_NAME>, O=DigiCert Inc, C=US",
        "subject public key" : "RSA",

Java Flight Recorder (JFR) Events

A less well-known but quite useful option for capturing X.509 certificate data is via the JFR profiler that ships with the JDK. The jdk.X509Certificate event captures information about every X.509 certificate generated by the JDK security libraries. To enable it, configure the JFR options or edit the default configuration file in the JDK itself. The default JFR configuration file is located at <JDK_HOME>/lib/jfr/default.jfc in JDK 11 and later. Simply switch the enabled option to true.

    <event name="jdk.X509Certificate">
       <setting name="enabled">true</setting>
       <setting name="stackTrace">true</setting>
    </event>

This event has been available since the release of Oracle JDK 8u231 (JDK-8148188). For JDK 8u, the event name is java/x509_certificate.

Start your JFR recording via application start-up arguments or attach remotely via jcmd, Java Mission Control (JMC) or one of your other favourite tools that supports the JFR attach option. For example, add (in JDK 11 and later) -XX:StartFlightRecording=filename=X509Info.jfr to your application start up arguments. Use JMC or the <JDK_HOME>/bin/jfr tool (available since JDK 12) to analyze the recording.

Here’s a example dump of such a captured event:

    $JDK/bin/jfr print  --events jdk.X509Certificate /tmp/myTLSApp.jfr
    jdk.X509Certificate {
      startTime = 09:59:25.672 (2022-11-10)
      algorithm = "SHA1withRSA"
      serialNumber = "18dad19e267de8bb4a2158cdcc6b3b4a"
      subject = "CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US"
      issuer = "CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US"
      keyType = "RSA"
      keyLength = 2048
      certificateId = 303010488
      validFrom = 00:00:00.000 (2006-11-08)
      validUntil = 23:59:59.000 (2036-07-16)
      eventThread = "main" (javaThreadId = 1)
      stackTrace = [
        sun.security.jca.JCAUtil.tryCommitCertEvent(Certificate) line: 126
        java.security.cert.CertificateFactory.generateCertificate(InputStream) line: 356
        sun.security.pkcs12.PKCS12KeyStore.loadSafeContents(DerInputStream) line: 2428
        sun.security.pkcs12.PKCS12KeyStore.engineLoad(InputStream, char[]) line: 2038
        sun.security.util.KeyStoreDelegator.engineLoad(InputStream, char[]) line: 228
        java.security.KeyStore.load(InputStream, char[]) line: 1500
        java.security.KeyStore.getInstance(File, char[], KeyStore$LoadStoreParameter, boolean) line: 1828
        java.security.KeyStore.getInstance(File, char[]) line: 1709
        sun.security.tools.KeyStoreUtil.getCacertsKeyStore() line: 137
        sun.security.tools.keytool.Main.buildTrustedCerts() line: 5072
        sun.security.tools.keytool.Main.doCommands(PrintStream) line: 1122
        sun.security.tools.keytool.Main.run(String[], PrintStream) line: 419
        ...
      ]
    }

Given the remote diagnostic ability of JFR, the jdk.X509Certificate event is a useful means of analyzing X.509 certificate data at runtime. Event fields such as algorithm and validUntil offer an insight into the security configuration in place.


Last reviewed on Sat Feb 01 2025 00:00:00 GMT+0000 (Coordinated Universal Time)