From 6c991b58d220f7c11d7e0274f2faa3c788db24eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20Fr=C3=B6hle?= Date: Fri, 22 Sep 2017 11:01:43 +0200 Subject: [PATCH] feat: add createEcparam to create EC private keys --- README.md | 11 +++++++++++ lib/pem.js | 42 ++++++++++++++++++++++++++++++++++++++++-- package.json | 3 +-- test/pem.helper.js | 12 ++++++++++++ test/pem.spec.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 324c587e..8d6e4811 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,17 @@ Where * **keyBitsize** is an optional size of the key, defaults to 512 (bit) * **callback** is a callback function with an error object and `{dhparam}` +### Create a ecparam key + +Use `createEcparam` for creating ecparam keys + + pem.createEcparam(keyName, callback) + +Where + + * **keyName** is an optional name of the key curves name, defaults to secp256k1 + * **callback** is a callback function with an error object and `{ecparam}` + ### Create a private key Use `createPrivateKey` for creating private keys diff --git a/lib/pem.js b/lib/pem.js index 9b206ff4..5952194a 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -15,6 +15,7 @@ var tempDir = process.env.PEMJS_TMPDIR || osTmpdir() module.exports.createPrivateKey = createPrivateKey module.exports.createDhparam = createDhparam +module.exports.createEcparam = createEcparam module.exports.createCSR = createCSR module.exports.createCertificate = createCertificate module.exports.readCertificateInfo = readCertificateInfo @@ -113,6 +114,38 @@ function createDhparam (keyBitsize, callback) { }) } +/** + * Creates a ecparam key + * + * @param {String} [keyName=secp256k1] Name of the key, defaults to secp256k1 + * @param {Function} callback Callback function with an error object and {ecparam} + */ +function createEcparam (keyName, callback) { + if (!callback && typeof keyName === 'function') { + callback = keyName + keyName = undefined + } + + keyName = keyName || 'secp256k1' + + var params = ['ecparam', + '-name', + keyName, + '-genkey', + '-param_enc', + 'explicit' + ] + + execOpenSSL(params, 'EC PARAMETERS', function (error, ecparam) { + if (error) { + return callback(error) + } + return callback(null, { + ecparam: ecparam + }) + }) +} + /** * Creates a Certificate Signing Request * @@ -1227,7 +1260,7 @@ function spawnWrapper (params, tmpfiles, binary, callback) { contents: tmpfiles.shift() }) params[i] = fpath - delTempPWFiles[i] = fpath + delTempPWFiles[delTempPWFiles.length] = fpath } }) } @@ -1239,7 +1272,7 @@ function spawnWrapper (params, tmpfiles, binary, callback) { spawnOpenSSL(params, binary, function (err, code, stdout, stderr) { helper.helperDeleteTempFiles(delTempPWFiles, function (fsErr) { - callback(err, code, stdout, stderr) + callback(err || fsErr, code, stdout, stderr) }) }) } @@ -1266,6 +1299,11 @@ function execOpenSSL (params, searchStr, tmpfiles, callback) { start = -1 } + // To get the full EC key with parameters and private key + if (searchStr === 'EC PARAMETERS') { + searchStr = 'EC PRIVATE KEY' + } + if ((end = stdout.match(new RegExp('^\\-+END ' + searchStr + '\\-+', 'm')))) { end = end.index + (end[0] || '').length } else { diff --git a/package.json b/package.json index 6f9c8eda..78cc1da4 100644 --- a/package.json +++ b/package.json @@ -53,8 +53,7 @@ "eslint-plugin-standard": "^3.0.1", "mocha": "^3.5.3", "nyc": "^11.2.1", - "semantic-release": "^8.0.0", - "semantic-release-tamia": "^1.0.0" + "semantic-release": "^8.0.3" }, "engines": { "node": ">=4.0.0" diff --git a/test/pem.helper.js b/test/pem.helper.js index a68d395a..34ca9794 100644 --- a/test/pem.helper.js +++ b/test/pem.helper.js @@ -21,6 +21,17 @@ function checkError (error, expectError) { } else { expect(error).to.not.be.ok() } } +function checkEcparam (data, min, max) { + expect(data).to.be.an('object').that.has.property('ecparam') + expect(data.ecparam).to.be.a('string') + expect(/^\n*-----BEGIN EC PARAMETERS-----\n/.test(data.ecparam)).to.be.true() + expect(/\n-----END EC PARAMETERS-----\n/.test(data.ecparam)).to.be.true() + expect(/\n-----BEGIN EC PRIVATE KEY-----\n/.test(data.ecparam)).to.be.true() + expect(/\n-----END EC PRIVATE KEY-----\n*$/.test(data.ecparam)).to.be.true() + var matchup = /-----BEGIN EC PRIVATE KEY-----[\s\S]+-----END EC PRIVATE KEY-----/.exec(data.ecparam) + expect(matchup[0].trim().length).to.be.within(min + 1, max - 1) +} + function checkDhparam (data, min, max) { expect(data).to.be.an('object').that.has.property('dhparam') expect(data.dhparam).to.be.a('string') @@ -94,6 +105,7 @@ module.exports = { checkTmpEmpty: checkTmpEmpty, checkError: checkError, checkDhparam: checkDhparam, + checkEcparam: checkEcparam, checkPrivateKey: checkPrivateKey, checkCSR: checkCSR, checkCertificate: checkCertificate, diff --git a/test/pem.spec.js b/test/pem.spec.js index b1ce9be7..29c03804 100644 --- a/test/pem.spec.js +++ b/test/pem.spec.js @@ -63,6 +63,49 @@ describe('General Tests', function () { }) }) + describe('#.createEcparam tests', function () { + it('Create default ecparam key', function (done) { + pem.createEcparam(function (error, data) { + hlp.checkError(error) + hlp.checkEcparam(data, 430, 440) + hlp.checkTmpEmpty() + done() + }) + }) + it('Create secp521k1 ecparam key', function (done) { + pem.createEcparam('secp521r1', function (error, data) { + hlp.checkError(error) + hlp.checkEcparam(data, 960, 980) + hlp.checkTmpEmpty() + done() + }) + }) + it('Create brainpoolP256r1 ecparam key', function (done) { + pem.createEcparam('brainpoolP256r1', function (error, data) { + hlp.checkError(error) + hlp.checkEcparam(data, 520, 530) + hlp.checkTmpEmpty() + done() + }) + }) + it('Create brainpoolP512t1 ecparam key', function (done) { + pem.createEcparam('brainpoolP512t1', function (error, data) { + hlp.checkError(error) + hlp.checkEcparam(data, 920, 980) + hlp.checkTmpEmpty() + done() + }) + }) + it('Create prime256v1 ecparam key', function (done) { + pem.createEcparam('prime256v1', function (error, data) { + hlp.checkError(error) + hlp.checkEcparam(data, 430, 560) + hlp.checkTmpEmpty() + done() + }) + }) + }) + describe('#.createPrivateKey tests', function () { describe('default sized private key', function () { var pkey