Skip to content

Commit

Permalink
feat: add createEcparam to create EC private keys
Browse files Browse the repository at this point in the history
  • Loading branch information
Dexus committed Sep 29, 2017
1 parent a7c5654 commit 6c991b5
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 4 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
42 changes: 40 additions & 2 deletions lib/pem.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -1227,7 +1260,7 @@ function spawnWrapper (params, tmpfiles, binary, callback) {
contents: tmpfiles.shift()
})
params[i] = fpath
delTempPWFiles[i] = fpath
delTempPWFiles[delTempPWFiles.length] = fpath
}
})
}
Expand All @@ -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)
})
})
}
Expand All @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 12 additions & 0 deletions test/pem.helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -94,6 +105,7 @@ module.exports = {
checkTmpEmpty: checkTmpEmpty,
checkError: checkError,
checkDhparam: checkDhparam,
checkEcparam: checkEcparam,
checkPrivateKey: checkPrivateKey,
checkCSR: checkCSR,
checkCertificate: checkCertificate,
Expand Down
43 changes: 43 additions & 0 deletions test/pem.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 6c991b5

Please sign in to comment.