diff --git a/README.md b/README.md index aecdf41a..6266fbcf 100644 --- a/README.md +++ b/README.md @@ -61,11 +61,13 @@ Where Use `createPrivateKey` for creating private keys - pem.createPrivateKey(keyBitsize, callback) + pem.createPrivateKey(keyBitsize, [options,] callback) Where * **keyBitsize** is an optional size of the key, defaults to 2048 (bit) + * **options** is an optional object of the cipher and password (both required for encryption), defaults {cipher:'',password:''} + (ciphers:["aes128", "aes192", "aes256", "camellia128", "camellia192", "camellia256", "des", "des3", "idea"]) * **callback** is a callback function with an error object and `{key}` ### Create a Certificate Signing Request diff --git a/lib/pem.js b/lib/pem.js index 60b6ab0d..a9e83a82 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -26,23 +26,43 @@ module.exports.config = config; * Creates a private key * * @param {Number} [keyBitsize=2048] Size of the key, defaults to 2048bit + * @param {Object} [options] object of cipher and password {cipher:'aes128',password:'xxx'}, defaults empty object * @param {Function} callback Callback function with an error object and {key} */ -function createPrivateKey(keyBitsize, callback) { - if (!callback && typeof keyBitsize === 'function') { +function createPrivateKey(keyBitsize, options, callback) { + var fpath; + if (!callback && !options && typeof keyBitsize === 'function') { callback = keyBitsize; keyBitsize = undefined; + options = {}; + } + else if (!callback && keyBitsize && typeof options === 'function') { + callback = options; + options = {}; } keyBitsize = Number(keyBitsize) || 2048; var params = ['genrsa', '-rand', - '/var/log/mail:/var/log/messages', - keyBitsize + '/var/log/mail:/var/log/messages' ]; - + var cipher = ["aes128", "aes192", "aes256", "camellia128", "camellia192", "camellia256", "des", "des3", "idea"]; + + if (options && options.cipher && ( -1 !== Number(cipher.indexOf(options.cipher)) ) && options.password){ + fpath = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex')); + fs.writeFileSync(fpath, options.password); + params.push( '-' + options.cipher ); + params.push( '-passout' ); + params.push( 'file:' + fpath ); + } + + params.push(keyBitsize); + execOpenSSL(params, 'RSA PRIVATE KEY', function(error, key) { + if(fpath) { + fs.unlink(fpath); + } if (error) { return callback(error); } diff --git a/test/pem.js b/test/pem.js index 1399685b..d188dac1 100644 --- a/test/pem.js +++ b/test/pem.js @@ -63,6 +63,20 @@ exports['General Tests'] = { }); }, + 'Create 2048bit Private key with Password': function(test) { + pem.createPrivateKey(2048,{cipher:'des',password:'TestMe'}, function(error, data) { + var key = (data && data.key || '').toString(); + test.ifError(error); + test.ok(key); + test.ok(key.match(/ENCRYPTED\n/)); + test.ok(key.match(/^\n*\-\-\-\-\-BEGIN RSA PRIVATE KEY\-\-\-\-\-\n/)); + test.ok(key.match(/\n\-\-\-\-\-END RSA PRIVATE KEY\-\-\-\-\-\n*$/)); + test.ok(key.trim().length > 1700 && key.trim().length < 1780); + test.ok(fs.readdirSync('./tmp').length === 0); + test.done(); + }); + }, + 'Create default CSR': function(test) { pem.createCSR(function(error, data) { var csr = (data && data.csr || '').toString();