• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer

Mister PKI

SSL Certificates * SSL Tools * Certificate Decoder

  • PKI Training
  • OpenSSL
  • Keytool
  • PKI Tools
    • Apereo CAS
    • SAML
    • OpenID Connect
  • Get expert help

PKIjs – JavaScript PKI

February 9, 2021 by Mister PKI 2 Comments

PKIjs is a JavaScript PKI (Public Key Infrastructure) library used for decoding and parsing SSL certificates directly on the client or browser, eliminating in many cases the need to do this work on the server side. PKIjs is built on top of the Web Cryptography API. The PKIjs library goes almost hand in hand with the ASN1.js JavaScript Library.

PKIjs was used to create our Certificate Decoder.

Install PKIjs

PKIjs is available in the Node Package Manager (npm). To install, simply run npm i pkijs, assuming npm has already been installed.

ASN1js is also available in the Node Package Manager (npm) and can be installed similarily. This package is required for some of the examples below. npm i ans1js

PKIjs Examples

The following are examples of how to use this PKI JavaScript in your code. The list of examples is not exhaustive so please let us know in the comments if we have not covered an example that will help you in your project.

PKIjs parse certificate

To parse an x509 certificate with JavaScript, it’s first important to understand what data you are looking for. The library is based on RFC-5280 for more information on each component of an X509 SSL Certificate.

In order to parse specific components of the certificate, it is first necessary to convert the PEM encoded certificate to the PKIjs Certificate object.

// 1. Strip off the header and footer of the PEM encoding
const b64 = pem.replace(/(-----(BEGIN|END) CERTIFICATE-----|[\n\r])/g, '');
// 2. Convert to the binary DER format
const der = Buffer.from(b64, 'base64');
// 3. Convert to BER encoding
const ber = new Uint8Array(der).buffer;
// 4. Create the asn1js Certificate object
const asn1 = asn1js.fromBER(ber);
const { Certificate } = pkijs;
return new Certificate({ schema: asn1.result });

After creating the Certificate object, you can begin to parse each component of the certificate.

Example of how to parse the the Subject DN (distinguished name):

The Subject DN may consist of many different parts. This example will focus on a few of them, based on their OID (Object Identifier). For this example, the following object identifiers and their DN value will be used:

2.5.4.3Common Name
2.5.4.6Country
2.5.4.10Organizational Unit
2.5.4.11Organization
2.5.4.7Locality
2.5.4.8State
2.5.4.9Street
2.5.4.17Postal Code
Subject DN Object Identifiers (OID)

Here is an example function of how to decode the subject dn:

subject = decodeDn(certificate.subject.typesAndValues);
decodeDn(subject) {
      const localSubject = {};
      subject.forEach((item) => {
        if (item.type === '2.5.4.3') {
          localSubject.commonName = item.value.valueBlock.value;
        } else if (item.type === '2.5.4.6') {
          localSubject.country = item.value.valueBlock.value;
        } else if (item.type === '2.5.4.10') {
          localSubject.orgUnit = item.value.valueBlock.value;
        } else if (item.type === '2.5.4.11') {
          localSubject.org = item.value.valueBlock.value;
        } else if (item.type === '2.5.4.7') {
          localSubject.locality = item.value.valueBlock.value;
        } else if (item.type === '2.5.4.8') {
          localSubject.state = item.value.valueBlock.value;
        } else if (item.type === '2.5.4.9') {
          localSubject.street = item.value.valueBlock.value;
        } else if (item.type === '2.5.4.17') {
          localSubject.postalCode = item.value.valueBlock.value;
        }
      });
      return localSubject;

Note that the Issuer DN may be decoded the same way. The decodeDn function above is general purpose for any DN.

PKIjs fingerprint

The fingerprint is a complex example and requires use of the Web Crypto API. It is an async function and takes in the BER encoded PKIjs Certificate object to compute the fingerprint of.

async computeFingerprint(certificate) {
      const hash = async (algo, buffer) => {
        const hashBuffer = await crypto.subtle.digest(algo, buffer);
        const hashArray = Array.from(new Uint8Array(hashBuffer));
        return hashArray
          .map((b) => (`00${b.toString(16)}`).slice(-2))
          .join(':')
          .toUpperCase();
      };
      this.fingerprint256 = await hash('SHA-256', certificate);
      this.fingerprint128 = await hash('SHA-1', certificate);
    }

Validate the before and after (expiration) date of the certificate

The notAfter and notBefore values hang directly on the PKIjs Certificate object. The following example will compute whether or not the certificate validity is valid based on these values. The moment package is required for this computation. npm install moment

notAfter = certificate.notAfter.value.toUTCString();
notBefore = certificate.notBefore.value.toUTCString();
if (!moment(certificate.notBefore.value).isBefore(new Date())) {
  preValid = true;
} else if (!moment(certificate.notAfter.value).isAfter(new Date())) {
  expired = true;
}

Please let us know of any additional PKIjs examples you would like to see.

Read more of our content on secure web technologies including our crypto-js article.

Uncategorized

Reader Interactions

Comments

  1. Muthu Selvi.C says

    April 24, 2023 at 12:28 pm

    Hi,
    I want to know how to get the key size of the EC public key algorithm using pkijs library. Could you please share this?

    Reply
  2. rob cordes says

    December 15, 2023 at 6:21 pm

    by any chance, do you have a solution for PKIjs not parsing the X509 AIA / (Authoritative Information Acces) extension correctly?

    this below code snippet code produces this:
    InfoAccess {
    accessDescriptions: [
    AccessDescription {
    accessMethod: ‘1.3.6.1.5.5.7.48.1’,
    accessLocation: [GeneralName] <<< ext.extnID === ‘1.3.6.1.5.5.7.1.1’ // id-ad-ocsp
    );

    if (ocspUrlExtension) {
    const ocspResponderUrl = ocspUrlExtension.parsedValue;
    console.log(‘\nOCSP Responder URL:’, ocspResponderUrl);
    // Generate and display OCSP request (implement this part based on your needs)
    const ocspRequest = generateOCSPRequest(certificate);
    console.log(‘OCSP Request:\n’, ocspRequest);
    } else {
    console.log(‘\nOCSP Responder URL not found in AIA extension.’);
    }
    } else {
    console.log(‘\nNo extensions found in the certificate.’);
    }

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

Popular Posts

PKCS12

openssl s_client

Keytool

Keytool list

ECDSA vs RSA

OpenSSL

PKCS7

Certificate Decoder

PKI for DevOps Engineers – Free Training Series

PKI for DevOps Training Hub

Lesson 1 – How TLS and PKI Work

Lesson 2 – Understanding X.509 Certificates

Lesson 3 – Certificate Chains Explained

Lesson 4 – Debug TLS with OpenSSL

Lesson 5 – Verify Certificate Chains

Lesson 6 – Creating CSRs with OpenSSL

Lesson 7 – Working with PKCS12 Certificates

Lesson 8 – Java Keystores and keytool

Lesson 9 – Certificate Expiration Monitoring

Lesson 10 – Automating Certificate Renewal

Lesson 11 – Common TLS Errors

Lesson 12 – PKI Architecture for DevOps

Recent Posts

  • Apache mod_auth_cas: Protect Web Applications with Apereo CAS and Docker
  • Apache mod_auth_mellon: Configure SAML SSO & Docker
  • Configure OpenID Connect (OIDC) in Apereo CAS 7.3 and 8
  • Certificate Ownership Is an Operating Model Problem, Not a Tooling Problem
  • OpenSSL dgst: Create Checksums and Verify Digital Signatures

Footer

  • Twitter
  • YouTube
Mister PKI

Practical security engineering for the systems that establish trust.

Learn OpenSSL Keytool Free training
Work together PKI consulting CAS consulting Sponsored contributions
Site About Support Mister PKI Cookie policy Search
© 2026 Mister PKI Secure systems. Clear guidance.