2

How can I extract the common name from a hex string representing a certificate in DER format? I need to display the name of the certificate so a client can choose which certificate they wish to use in the web application.

Constraints:

  • I need to perform this extraction client-side in a web-browser. OpenSSL will not be available.
  • Total size of solution with 3rd-party libraries should be as small as possible.
Joseph238
  • 1,174
  • 1
  • 14
  • 22

1 Answers1

3

Here's one solution using ASN1js and PKI.js. I've added a random raw hex certificate in DER format for demonstration purposes. In my testing the libraries add about 85 kB of unminified code to the build, which isn't too bad considering the complexity of this operation.

// Import only required components of 3rd-party libraries
import Certificate from 'pkijs/src/Certificate';
import {fromBER} from 'asn1js';

const X509_COMMON_NAME_KEY = '2.5.4.3';
const hexCertificateString = '308204273082030fa003020102020211e1300d06092a864886f70d01010b05003081bd310b3009060355040613025553310d300b06035504080c0455746168310e300c06035504070c0550726f766f3121301f060355040a0c184d6963726f666f63757320496e7465726e6174696f6e616c311a3018060355040b0c11416363657373204d616e6167656d656e74311f301d06035504030c164175746f6d6174696f6e20456e67696e656572696e67312f302d06092a864886f70d01090116206368726973746f706865722e6b656c6c79406d6963726f666f6375732e636f6d301e170d3139303330343137333430365a170d3231303330333137333430365a307b311d301b06035504030c147365727665722e6d79636f6d70616e792e636f6d310d300b06035504080c0455746168310b300906035504061302555331223020060355040a0c194d6963726f20466f63757320496e7465726e6174696f6e616c311a3018060355040b0c11416363657373204d616e6167656d656e7430820122300d06092a864886f70d01010105000382010f003082010a0282010100e3ed299a22551d3b4ae0e86a438f33ad3749a1152b3b6f50c39ae48f0a99550ac87287c7e5904ae466aacd72d044090a479554bce473c6b6342d0c2bf718d89656f33414daf599065d8610cb3ca74bed95149379608b3e0ec7db2916901e09099ad31d5f13f25f2db6fbc6fa479c6613ac35766cd6562555580f1ddcc57f4ab46a61bc682c40a06be060e620c92f167613584f34d3efb39cd29ebcb24c084554e5759ad814886f0b2c1b863565736113650a76b05f9d755f1fa3c9aa82e9cebf21155d2b481096036888641a5910d4feb3eb23a1d2900a84587047708033aed977200753fa15edac6960626dbc203baf084770e50e8a4c5dc3fb2cbb19c438c70203010001a3723070300c0603551d130101ff04023000301d0603551d0e04160414737228fc878e6e592d60b0c39cac757fcc4a9e1a301f0603551d230418301680144db5ee67429dcd2643d92d15a65efc681f399723300b0603551d0f0404030201a630130603551d25040c300a06082b06010505070301300d06092a864886f70d01010b05000382010100c9b8844b92e239c26f29d55fc2d969f1f977e8ad3967fd4274cf023668abed35b7c13d8cfc109711f48f13c0bbc2181abbad5ef1982ae17f6f7ef7de0b221d109327ed667d3a2e8ab0e1e39093798f236a70f16338bea07f6f74e1a07755768db6c3312083acf3e6ef6c4f1711ddea2049bbfb4dd262d692ad7146e29f83d19de3132b243de5e73bd537f2bd8198ee875fc2b64a52a9a600b870fd9a9a0d9569c44a6725244ce51d659100e26c22c42db72ad42ed9dc5ab40640d94e2f55ee082dd6f4221f2e23394e2c9c0c10590d67b0ec0e7af455724d1f5811c3728a9432ba161526bba500c9c37fc3d34afe9fbe108c9c6863a2b7b502b9fd5cf0c4ac50';

let commonName = '';    // Default in case no subject is found

try {
    // Convert to ArrayBuffer
    const typedArray = new Uint8Array(hexCertificateString.match(/[\da-f]{2}/gi)
        .map(h => parseInt(h, 16)));
    const certificateBuffer = typedArray.buffer;

    // Parse certificate. See example at
    // https://github.com/PeculiarVentures/PKI.js#parse-a-x509-certificate
    const asn1 = fromBER(certificateBuffer);
    const certificate = new Certificate({ schema: asn1.result });

    // Search the subject's attributes for the common name of the certificate
    const subjectAttributes = certificate.subject.typesAndValues;
    for (let index = 0; index < subjectAttributes.length; index++) {
        const attribute = subjectAttributes[index];
        if (attribute.type === X509_COMMON_NAME_KEY) {
            commonName = attribute.value.valueBlock.value;
            break;
        }
    }
}
catch (error) {
    console.error('Error parsing certificate:', error);
}


console.log('Certificate name:', commonName);
Joseph238
  • 1,174
  • 1
  • 14
  • 22