How to parse a X.509 certificate and extract its public key

Public keys for verifying JWS signatures can be supplied as X.509 certificates.

The Nimbus JOSE+JWT library provides a simple utility (introduced in v4.6) for parsing X.509 certificates into java.security.cert.X509Certificate objects. The two common certificate encodings are supported:

  • DER (binary) encoded certificates;
  • PEM (BASE64) encoded certificates, suitable for copy-and-paste operations, saving the certificate to a text file, or passing it via the x5c JOSE header parameter.

How to parse a certificate from a DER byte array or PEM string:

import java.security.cert.X509Certificate;
import com.nimbusds.jose.util.X509CertUtils;

X509Certificate cert = X509CertUtils.parse(encodedCert);

if (cert == null) {
    // Parsing failed
}

If the default JCA provider doesn't support a particular certificate feature and you need a custom one to parse it:

import java.security.Provider;
import java.security.cert.X509Certificate;
import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton;
import com.nimbusds.jose.util.X509CertUtils;

// Set the needed JCA provider for all parse operations
Provider jcaProvider = BouncyCastleProviderSingleton.getInstance();
X509CertUtils.setProvider(jcaProvider);

X509Certificate cert = X509CertUtils.parse(encodedCert);

The certificate must be validated before it may be used. This typically consists of validating the certificate's chain up to the root CA using its signature, checking its expiration date, and ensuring it matches the expected issuer and subject.

If the certificate passed validation and can be trusted, you can proceed by extracting the public key (RSA or EC) that comes with it, for example to a verify a JWS signature.

import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.interfaces.ECPublicKey;

PublicKey pubKey = cert.getPublicKey();

if (pubKey instanceof RSAPublicKey) {
    // We have an RSA public key
    // ...
} else if (pubKey instanceof ECPublicKey) {
    // We have an EC public key
    // ...
} else {
    // Unknown key type, should never happen
}

The extracted keys are represented in the standard Java classes. You can easily convert to a JSON Web Key (JWK) format if needed.

Version 4.33 of the library added static methods for extracting the public key of an X.509 certificate in JWK format:

import java.security.cert.X509Certificate;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.util.X509CertUtils;

// Parse X.509 certificate
X509Certificate cert = X509CertUtils.parse(encodedCert);

// Retrieve public key as RSA JWK
RSAKey rsaJWK = RSAKey.parse(cert);