diff --git a/README.md b/README.md index e0686cb..872cfa4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,48 @@ -# cert-info.js +cert-info.js +============ + Read basic info from a cert.pem / x509 certificate. + +Install +======= + +```bash +# bin +npm install --global certpem + +# node.js library +npm install --save certpem +``` + +Usage +===== + +For basic info (subject, altnames, issuedAt, expiresAt): + +```bash +certpem /path/to/cert.pem +``` + +Output all info by passing `--debug` or use `--json` to see the basic info pretty-printed. + +```javascript +'use strict'; + +var certpem = require('certpem').certpem +var cert = fs.readFile('cert.pem', 'ascii', function (err, certstr) { + console.info(cert.pem.info()); + + console.info(cert.pem.debug()); +}); +``` + +```javascript +{ + "subject": "localhost.daplie.com", + "altnames": [ + "localhost.daplie.com" + ], + "issuedAt": 1465516800000, + "expiresAt": 1499731199000 +} +``` diff --git a/bin/certpem.js b/bin/certpem.js new file mode 100755 index 0000000..a5f556f --- /dev/null +++ b/bin/certpem.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +'use strict'; + +var certpem = require('../').certpem; +var path = require('path'); +var filepath = (process.cwd() + path.sep + 'cert.pem'); +var debug = false; +var json; +var cert; + +if (/--debug/.test(process.argv[2]) || /--debug/.test(process.argv[3])) { + debug = true; +} +if (/--json/.test(process.argv[2]) || /--json/.test(process.argv[3])) { + json = true; +} +if (process.argv[2] && !/^--/.test(process.argv[2])) { + filepath = process.argv[2]; +} +if (process.argv[3] && !/^--/.test(process.argv[3])) { + filepath = process.argv[3]; +} + +if (filepath.length > 256) { + cert = filepath; +} +else { + cert = require('fs').readFileSync(filepath, 'ascii'); +} + +if (debug) { + console.info(JSON.stringify(certpem.debug(cert), null, ' ')); +} else { + var c = certpem.info(cert); + + if (json) { + console.info(JSON.stringify(c, null, ' ')); + return; + } + + console.info(''); + + console.info('Certificate for', c.subject); + console.info(''); + console.info('Altnames:', c.altnames.join(', ')); + console.info(''); + console.info('Issued at', new Date(c.issuedAt)); + console.info('Expires at', new Date(c.expiresAt)); + + console.info(''); +} diff --git a/cert.pem b/cert.pem new file mode 100644 index 0000000..4d3bcb3 --- /dev/null +++ b/cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFajCCBFKgAwIBAgIQdsKX6kswrkbK7NZ/kc31vTANBgkqhkiG9w0BAQsFADBC +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS +UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE2MDYxMDAwMDAwMFoXDTE3MDcxMDIzNTk1 +OVowHzEdMBsGA1UEAwwUbG9jYWxob3N0LmRhcGxpZS5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCd49Z2PuWyX9qFlURgq8E0OzMP6szDLutkYBmW +sDdnekEw0mAUgmXcrhKcDog8ugDvcVqqOlice8rumL9OLMmRG3ObSzLV++2ETgBe +xpEawSJKj7UpCpw2EJtMFvSPXrHIMhkN4rUkh1Pzoo7+i4/MVIoDPljPgxPOtFNS +tECA/3kD2DlkIY/wOlkF8T1lg7A8Q92aVXiyIHmXubrHdT4bhr4YRbyvltEB2eA+ +z4LLyqz+kMKHN1TYhMJUGur/C/Le3sNrhF2veqOCdPBomTwpWwJ4PPmN0kqeT0N3 +D1CJVrt4Uj8W9N7fPsguYAehs5e06MCcAT3Dl1EqNNEJw/elAgMBAAGjggJ9MIIC +eTAfBgNVHREEGDAWghRsb2NhbGhvc3QuZGFwbGllLmNvbTAJBgNVHRMEAjAAMCsG +A1UdHwQkMCIwIKAeoByGGmh0dHA6Ly9ncC5zeW1jYi5jb20vZ3AuY3JsMG8GA1Ud +IARoMGYwZAYGZ4EMAQIBMFowKgYIKwYBBQUHAgEWHmh0dHBzOi8vd3d3LnJhcGlk +c3NsLmNvbS9sZWdhbDAsBggrBgEFBQcCAjAgDB5odHRwczovL3d3dy5yYXBpZHNz +bC5jb20vbGVnYWwwHwYDVR0jBBgwFoAUl8InUJ7CyewMiDLIfK3ipgFP2m8wDgYD +VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBXBggr +BgEFBQcBAQRLMEkwHwYIKwYBBQUHMAGGE2h0dHA6Ly9ncC5zeW1jZC5jb20wJgYI +KwYBBQUHMAKGGmh0dHA6Ly9ncC5zeW1jYi5jb20vZ3AuY3J0MIIBAgYKKwYBBAHW +eQIEAgSB8wSB8ADuAHYA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvswA +AAFVOonOzQAABAMARzBFAiEAzh4K7ZOSGCCFFvzAvrfl+o5AKcnmV7NHPgQZe3x4 +hZgCIH/M2LZI1OSdkQbF2wgD/xH4PvQ4i8TTOdGB0WAYVr1eAHQApLkJkLQYWBSH +uxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFVOonO8gAABAMARTBDAh84cfLQthSR +Pe6hFgL8TPSuCUxIFBcEbnIPNB7ZxQwYAiBTClbmIn81bBkwAjasJu2u+UdxGE0i +Wx5lFe5X9pqsUTANBgkqhkiG9w0BAQsFAAOCAQEAAWYuT/fTBZdXb4kwoVaUnc82 +2CEnGuOHr9QMdGRMqWJRe068StADdw1u3V6bcB7+mBiGl8C+WOLhv9WxYKqNFvyj +Eeaeekb4GqfrfuxNvoOU/vHdYaww2J9N1ESgIV4BdFF8aNgOnjpRcKSMsMgzNJdU +lh6l7jhnTeNYCyMnn+2dVQBcRQvptKmpkS4sK6NAVSMWDioImEoGj0PCdLqG8k21 +d3vNddCEQmcNUTHs38nswUKZxfQKpjo+z9jBFmurmaNqSFnd8ySmBELZjXEOXEQz +KBlUSDj3UYVmH49t0toGyHVfKHPCBLyUZhvUTy0tNVgn9Nc+/MXJnv+c5rxVeQ== +-----END CERTIFICATE----- diff --git a/index.js b/index.js new file mode 100644 index 0000000..893f9d6 --- /dev/null +++ b/index.js @@ -0,0 +1,84 @@ +'use strict'; + +var certInfo = module.exports; +module.exports.certpem = certInfo; + +require('buffer-v6-polyfill'); + +// this is really memory expensive to do +// (about half of a megabyte of loaded code) +certInfo._pemToBinAb = function (pem) { + var b64 = pem.replace(/(-----(BEGIN|END) CERTIFICATE-----|[\n\r])/g, ''); + var buf = Buffer.from(b64, 'base64'); + var ab = new Uint8Array(buf).buffer; // WORKS + //var ab = buf.buffer // Doesn't work + + return ab; +}; +certInfo.debug = certInfo.getCertInfo = function (pem) { + var ab = module.exports._pemToBinAb(pem); + var merge = require("node.extend"); + + var common = require("asn1js/org/pkijs/common"); + var _asn1js = require("asn1js"); + var _pkijs = require("pkijs"); + var _x509schema = require("pkijs/org/pkijs/x509_schema"); + + // #region Merging function/object declarations for ASN1js and PKIjs + var asn1js = merge(true, _asn1js, common); + + var x509schema = merge(true, _x509schema, asn1js); + + var pkijs_1 = merge(true, _pkijs, asn1js); + var pkijs = merge(true, pkijs_1, x509schema); + + var asn1 = pkijs.org.pkijs.fromBER(ab); + var certSimpl = new pkijs.org.pkijs.simpl.CERT({ schema: asn1.result }); + + return certSimpl; +}; + +certInfo.info = certInfo.getBasicInfo = function (pem) { + var c = certInfo.getCertInfo(pem); + var domains = []; + var sub; + + c.extensions.forEach(function (ext) { + if (ext.parsedValue && ext.parsedValue.altNames) { + ext.parsedValue.altNames.forEach(function (alt) { + domains.push(alt.Name); + }); + } + }); + + sub = c.subject.types_and_values[0].value.value_block.value || null; + + return { + subject: sub + , altnames: domains + // for debugging during console.log + // do not expect these values to be here + , _issuedAt: c.notBefore.value + , _expiresAt: c.notAfter.value + , issuedAt: new Date(c.notBefore.value).valueOf() + , expiresAt: new Date(c.notAfter.value).valueOf() + }; +}; + +certInfo.getCertInfoFromFile = function (pemFile) { + return require('fs').readFileSync(pemFile, 'ascii'); +}; + +/* +certInfo.testGetCertInfo = function (pathname) { + var path = require('path'); + var pemFile = pathname || path.join(__dirname, '..', 'tests', 'example.cert.pem'); + return certInfo.getCertInfo(certInfo.getCertInfoFromFile(pemFile)); +}; + +certInfo.testBasicCertInfo = function (pathname) { + var path = require('path'); + var pemFile = pathname || path.join(__dirname, '..', 'tests', 'example.cert.pem'); + return certInfo.getBasicInfo(certInfo.getCertInfoFromFile(pemFile)); +}; +*/ diff --git a/package.json b/package.json new file mode 100644 index 0000000..aac134c --- /dev/null +++ b/package.json @@ -0,0 +1,46 @@ +{ + "name": "certpem", + "version": "1.0.0", + "description": "Read basic info (subject, altnames, expiresAt, issuedAt) from a cert.pem / x509 certificate (tls / ssl / https) ", + "main": "index.js", + "bin": { + "certpem": "bin/certpem.js" + }, + "scripts": { + "test": "node test.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Daplie/cert-info.js.git" + }, + "keywords": [ + "cert.pem", + "cert", + "certificate", + "x509", + "subject", + "altnames", + "notBefore", + "notAfter", + "issuedAt", + "expiresAt", + "expired", + "expires", + "issued", + "at", + "asn1", + "pki" + ], + "author": "AJ ONeal (https://coolaj86.com/)", + "license": "(MIT OR Apache-2.0)", + "bugs": { + "url": "https://github.com/Daplie/cert-info.js/issues" + }, + "homepage": "https://github.com/Daplie/cert-info.js#readme", + "dependencies": { + "asn1js": "^1.2.12", + "buffer-v6-polyfill": "^1.0.3", + "node.extend": "^1.1.5", + "pkijs": "^1.3.27" + } +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..20e788f --- /dev/null +++ b/test.js @@ -0,0 +1,3 @@ +'use strict'; + +require('./bin/certpem.js');