diff --git a/lib/cert-info.js b/lib/cert-info.js new file mode 100644 index 0000000..50bd31c --- /dev/null +++ b/lib/cert-info.js @@ -0,0 +1,62 @@ +'use strict'; + +var certInfo = module.exports; + +// 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(b64, 'base64'); + var ab = new Uint8Array(buf).buffer; // WORKS + //var ab = buf.buffer // Doesn't work + + return ab; +}; +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.getCertInfoFromFile = function (pemFile) { + return require('fs').readFileSync(pemFile, 'ascii'); +}; + +certInfo.testGetCertInfo = function () { + var path = require('path'); + var pemFile = path.join(__dirname, '..', 'tests', 'example.cert.pem'); + return certInfo.getCertInfo(certInfo.getCertInfoFromFile(pemFile)); +}; + +if (require.main === module) { + var c = certInfo.testGetCertInfo(); + + console.log(''); + + console.log(c.notBefore.value); + console.log(Date(c.notBefore.value).valueOf()); + + console.log(''); + + console.log(c.notAfter.value); + console.log(Date(c.notAfter.value).valueOf()); + + console.log(''); +} diff --git a/lib/common.js b/lib/common.js index 4c67d9f..1351d17 100644 --- a/lib/common.js +++ b/lib/common.js @@ -89,13 +89,18 @@ module.exports.fetchFromDisk = function (args) { // stat the file, not the link , fs.statAsync(args.certPath) // 3 ]).then(function (arr) { + var cert = arr[1]; + var getCertInfo = require('./cert-info').getCertInfo; + + // XXX Note: Parsing the certificate info comes at a great cost (~500kb) + var certInfo = getCertInfo(cert); return { key: arr[0] // privkey.pem , privkey: arr[0] // privkey.pem , fullchain: arr[1] + '\n' + arr[2] // fullchain.pem - , cert: arr[1] // cert.pem + , cert: cert // cert.pem , chain: arr[2] // chain.pem , ca: arr[2] // chain.pem @@ -105,7 +110,9 @@ module.exports.fetchFromDisk = function (args) { , certPath: args.certPath , chainPath: args.chainPath - , issuedAt: arr[3].mtime.valueOf() // ??? TODO parse to determine expiresAt and lifetime + //, issuedAt: arr[3].mtime.valueOf() + , issuedAt: Date(certInfo.notBefore.value).valueOf() // Date.now() + , expiresAt: Date(certInfo.notAfter.value).valueOf() , lifetime: args.lifetime }; }, function (err) { diff --git a/lib/core.js b/lib/core.js index aa2b4b5..969d094 100644 --- a/lib/core.js +++ b/lib/core.js @@ -222,6 +222,10 @@ function writeCertificateAsync(args, defaults, handlers) { return writeRenewalConfig(args); }).then(function () { + var getCertInfo = require('./cert-info').getCertInfo; + + // XXX Note: Parsing the certificate info comes at a great cost (~500kb) + var certInfo = getCertInfo(result.cert); return { certPath: certPath @@ -240,7 +244,8 @@ function writeCertificateAsync(args, defaults, handlers) { // especially this one... might be cert only, might be fullchain , cert: result.cert - , issuedAt: Date.now() + , issuedAt: Date(certInfo.notBefore.value).valueOf() // Date.now() + , expiresAt: Date(certInfo.notAfter.value).valueOf() , lifetime: defaults.lifetime || handlers.lifetime }; }); @@ -352,7 +357,7 @@ function getOrCreateDomainCertificate(args, defaults, handlers) { // no certs, seems like a good time to get some return getCertificateAsync(args, defaults, handlers); } - else if (certs.issuedAt > (27 * 24 * 60 * 60 * 1000)) { + else if ((Date.now() - certs.issuedAt) > (27 * 24 * 60 * 60 * 1000)) { // cert is at least 27 days old we can renew that return getCertificateAsync(args, defaults, handlers); } diff --git a/package.json b/package.json index c976a5a..70f9046 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "letsencrypt", - "version": "1.5.0", + "version": "1.5.1", "description": "Let's Encrypt for node.js on npm", "main": "index.js", "scripts": { diff --git a/tests/example.cert.pem b/tests/example.cert.pem new file mode 100644 index 0000000..c9470c3 --- /dev/null +++ b/tests/example.cert.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE+DCCA+CgAwIBAgISA2ZPXaADSdfNg48RtgfQGS9IMA0GCSqGSIb3DQEBCwUA +MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD +ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNjA1MTMyMzM4MDBaFw0x +NjA4MTEyMzM4MDBaMBUxEzARBgNVBAMTCm9hdXRoMy5vcmcwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDpm3D2yi79yHcnyv7JdNs7fVUO7Kcxq52qruyI +svMfq1gd7W1m6L7OPlRNvsae3/Yuca2Ip+JPXcCphhhb63/ChUSp5efbo0JYg6EZ +L/5TaV8HyovONEfleuYWSaBZ6RaRAZYBDclIJ13wgsYbJPYE5lSV2ufdAr9OIYrk +myo5+WPVxZpDS7+fBY+fUnxJ8BOs1R7q/xfnDaipTc0ZsNQlQwOIkvQOy0D4otwx +61MsrjPoQf686fex/HPwWi5sfKmH3YyB2ClnaIFv2wFs9fxCyb2htBn79Y98l4rV +Ved21MllyReMKsk9J2Sx+3ONHr8Qpo1chHEu56MbbMXgqsmlAgMBAAGjggILMIIC +BzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC +MAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFK8RJxCWMQgo8OHf2ILIIqatdHZkMB8G +A1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMHAGCCsGAQUFBwEBBGQwYjAv +BggrBgEFBQcwAYYjaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0Lm9yZy8w +LwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcv +MBUGA1UdEQQOMAyCCm9hdXRoMy5vcmcwgf4GA1UdIASB9jCB8zAIBgZngQwBAgEw +geYGCysGAQQBgt8TAQEBMIHWMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNl +bmNyeXB0Lm9yZzCBqwYIKwYBBQUHAgIwgZ4MgZtUaGlzIENlcnRpZmljYXRlIG1h +eSBvbmx5IGJlIHJlbGllZCB1cG9uIGJ5IFJlbHlpbmcgUGFydGllcyBhbmQgb25s +eSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIENlcnRpZmljYXRlIFBvbGljeSBmb3Vu +ZCBhdCBodHRwczovL2xldHNlbmNyeXB0Lm9yZy9yZXBvc2l0b3J5LzANBgkqhkiG +9w0BAQsFAAOCAQEAfD/fMRxCZqMeQKFjyM6LIt9k84aHDdkem0ZmMUlYDuiz9iI5 +ZeL20gYopLQ+vcKe/1vHnODnEcEhBjzNM/aVXQVHi/xokDf4Loks6fP2cslGMMFy +Kqgz3JaEcIs3ENjBBIU0xGQGuN67eZK8yhfrQxQuZOIx9J+IyP1jyFQSGA2c9wQD +KRPUCef3EZhBaL1DXlMB8fqQOq0EP0IF2Qsp5MlkYaM9N3U/xbjku74lGBkJnS5n +f2GE45RdY8KlIkJtkNhbGNX+nYHgbATUoO5uTKlcBslC+uwVqDDF3gbpdvAKE4a8 +eh6155o4h8lnhZD4Okr0KvdZT17jH+j4cbkRXw== +-----END CERTIFICATE-----