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):
-
Version: Specifies the version of the X.509 standard the certificate complies with.
-
Serial Number: A unique identifier assigned to the certificate by the certificate authority (CA). This helps to identify a certificate.
-
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).
-
Issuer Name: The name of the entity that issued the certificate, typically a CA. This is often represented as a Distinguished Name (DN).
-
Validity Period: The time span during which the certificate is valid, including a “Not Before” date and an “Expires On” date.
-
Subject Name: The entity (individual, organization, or system) to whom the certificate is issued. This is also usually represented as a Distinguished Name (DN).
-
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)