From 0e017e011e0b6542b776aca203add02ee7192246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20Fr=C3=B6hle?= Date: Thu, 27 Mar 2014 14:09:27 +0100 Subject: [PATCH] Change default settings for future requirements + EV Fix changed the default settings: keyBitsize set to 2048 (befor: 1024) Hash set to SHA256 (befor: SHA1) readCertificateInfo return now a `san` object {dns, ip} if the csr/cert have san entries. readCertificateInfo returns now EV Cert informations README.md updated --- README.md | 10 +++++--- lib/pem.js | 71 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 52 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index aa5d938a..b746f393 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Use `createPrivateKey` for creating private keys Where - * **keyBitsize** is an optional size of the key, defaults to 1024 (bit) + * **keyBitsize** is an optional size of the key, defaults to 2048 (bit) * **callback** is a callback function with an error object and `{key}` ### Create a Certificate Signing Request @@ -71,8 +71,8 @@ Where Possible options are the following * **clientKey** is an optional client key to use - * **keyBitsize** - if `clientKey` is undefined, bit size to use for generating a new key (defaults to 1024) - * **hash** is a hash function to use (either `md5` or `sha1`, defaults to `sha1`) + * **keyBitsize** - if `clientKey` is undefined, bit size to use for generating a new key (defaults to 2048) + * **hash** is a hash function to use (either `md5`, `sha1` or `sha256`, defaults to `sha256`) * **country** is a CSR country field * **state** is a CSR state field * **locality** is a CSR locality field @@ -123,7 +123,9 @@ Use `readCertificateInfo` for reading subject data from a certificate or a CSR Where * **certificate** is a PEM encoded CSR or a certificate - * **callback** is a callback function with an error object and `{country, state, locality, organization, organizationUnit, commonName, emailAddress, validity{start, end} }` + * **callback** is a callback function with an error object and `{country, state, locality, organization, organizationUnit, commonName, emailAddress, validity{start, end}, san{dns, ip}? }` + +? *san* is only present if the CSR or certificate has SAN entries. ### Get fingerprint diff --git a/lib/pem.js b/lib/pem.js index 3e14da7a..39e74199 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -19,7 +19,7 @@ module.exports.getModulus = getModulus; /** * Creates a private key * - * @param {Number} [keyBitsize=1024] Size of the key, defaults to 1024bit + * @param {Number} [keyBitsize=2048] Size of the key, defaults to 2048bit * @param {Function} callback Callback function with an error object and {key} */ function createPrivateKey(keyBitsize, callback){ @@ -28,7 +28,7 @@ function createPrivateKey(keyBitsize, callback){ keyBitsize = undefined; } - keyBitsize = Number(keyBitsize) || 1024; + keyBitsize = Number(keyBitsize) || 2048; var params = ["genrsa", "-rand", @@ -52,8 +52,8 @@ function createPrivateKey(keyBitsize, callback){ * * @param {Object} [options] Optional options object * @param {String} [options.clientKey] Optional client key to use - * @param {Number} [options.keyBitsize] If clientKey is undefined, bit size to use for generating a new key (defaults to 1024) - * @param {String} [options.hash] Hash function to use (either md5 or sha1, defaults to sha1) + * @param {Number} [options.keyBitsize] If clientKey is undefined, bit size to use for generating a new key (defaults to 2048) + * @param {String} [options.hash] Hash function to use (either md5 sha1 or sha256, defaults to sha256) * @param {String} [options.country] CSR country field * @param {String} [options.state] CSR state field * @param {String} [options.locality] CSR locality field @@ -72,7 +72,7 @@ function createCSR(options, callback){ } options = options || {}; - + // http://stackoverflow.com/questions/14089872/why-does-node-js-accept-ip-addresses-in-certificates-only-for-san-not-for-cn if (options.commonName && (net.isIPv4(options.commonName) || net.isIPv6(options.commonName))) { if (!options.altNames) { @@ -80,10 +80,10 @@ function createCSR(options, callback){ } else if (options.altNames.indexOf(options.commonName) == -1) { options.altNames = options.altNames.concat([options.commonName]) } - } + } if(!options.clientKey){ - createPrivateKey(options.keyBitsize || 1024, function(error, keyData){ + createPrivateKey(options.keyBitsize || 2048, function(error, keyData){ if(error){ return callback(error); } @@ -95,7 +95,7 @@ function createCSR(options, callback){ var params = ["req", "-new", - "-" + (options.hash || "sha1"), + "-" + (options.hash || "sha256"), "-subj", generateCSRSubject(options), "-key", @@ -185,7 +185,7 @@ function createCertificate(options, callback){ if(options.selfSigned){ options.serviceKey = options.clientKey; }else{ - createPrivateKey(options.keyBitsize || 1024, function(error, keyData){ + createPrivateKey(options.keyBitsize || 2048, function(error, keyData){ if(error){ return callback(error); } @@ -382,49 +382,47 @@ function getFingerprint(certificate, callback){ function fetchCertificateData(certData, callback){ certData = (certData || "").toString(); - var subject, extra, tmp, certValues = {}; + var subject,subject2, extra, tmp, certValues = {}; var validity = {}; if((subject = certData.match(/Subject:([^\n]*)\n/)) && subject.length>1){ + subject2 = linebrakes(subject[1]+'\n'); subject = subject[1]; extra = subject.split("/"); subject = extra.shift()+"\n"; extra = extra.join("/")+"\n"; // country - tmp = subject.match(/\sC=([^,\n].*?)[,\n]/); + tmp = subject2.match(/\sC=([^\n].*?)[\n]/); certValues.country = tmp && tmp[1] || ""; // state - tmp = subject.match(/\sST=([^,\n].*?)[,\n]/); + tmp = subject2.match(/\sST=([^\n].*?)[\n]/); certValues.state = tmp && tmp[1] || ""; // locality - tmp = subject.match(/\sL=([^,\n].*?)[,\n]/); + tmp = subject2.match(/\sL=([^\n].*?)[\n]/); certValues.locality = tmp && tmp[1] || ""; // organization - tmp = subject.match(/\sO=([^,\n].*?)[,\n]/); + tmp = subject2.match(/\sO=([^\n].*?)[\n]/); certValues.organization = tmp && tmp[1] || ""; // unit - tmp = subject.match(/\sOU=([^,\n].*?)[,\n]/); + tmp = subject2.match(/\sOU=([^\n].*?)[\n]/); certValues.organizationUnit = tmp && tmp[1] || ""; // common name - tmp = subject.match(/\sCN=([^,\n].*?)[,\n]/); + tmp = subject2.match(/\sCN=([^\n].*?)[\n]/); certValues.commonName = tmp && tmp[1] || ""; //email - tmp = extra.match(/emailAddress=([^,\n\/].*?)[,\n\/]/); + tmp = extra.match(/emailAddress=([^\n\/].*?)[\n\/]/); certValues.emailAddress = tmp && tmp[1] || ""; - } + } if((san = certData.match(/X509v3 Subject Alternative Name: \n([^\n]*)\n/)) && san.length>1){ san = san[1].trim()+'\n'; - extra = subject.split("/"); - subject = extra.shift()+"\n"; - extra = extra.join("/")+"\n"; - + certValues.san = {}; // country tmp = preg_match_all('DNS:([^,\n].*?)[,\n]',san); - certValues.SAN_DNS = tmp || ""; + certValues.san.dns = tmp || ""; // country tmp = preg_match_all('IP Address:([^,\n].*?)[,\n\s]',san); - certValues.SAN_IP = tmp || ""; + certValues.san.ip = tmp || ""; } if ((tmp = certData.match(/Not Before\s?:\s?([^\n]*)\n/)) && tmp.length>1) validity.start = Date.parse(tmp && tmp[1] || ""); @@ -436,6 +434,29 @@ function fetchCertificateData(certData, callback){ callback(null, certValues); } + + +function linebrakes (content){ +var helper_x, p,subject; +helper_x = content.replace(/(C|L|O|OU|ST|CN)=/g, "\n$1="); +helper_x = preg_match_all('((C|L|O|OU|ST|CN)=[^\n].*)',helper_x); +for(p in helper_x){ + subject = helper_x[p].trim(); + content = subject.split("/"); + subject = content.shift(); + helper_x[p] = rtrim(subject,','); +} +return " " + helper_x.join('\n') + "\n"; +} + +function rtrim(str, charlist) { + charlist = !charlist ? ' \\s\u00A0' : (charlist + '') + .replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\\$1'); + var re = new RegExp('[' + charlist + ']+$', 'g'); + return (str + '') + .replace(re, ''); +} + function preg_match_all(regex, haystack) { var globalRegex = new RegExp(regex, 'g'); var globalMatch = haystack.match(globalRegex); @@ -604,4 +625,4 @@ function execOpenSSL(params, searchStr, tmpfiles, callback){ return callback(new Error(searchStr + " not found from openssl output:\n---stdout---\n" + stdout + "\n---stderr---\n" + stderr + "\ncode: " + code + "\nsignal: " + signal)); } }); -} +} \ No newline at end of file