'use strict' var openssl = require('./openssl.js') var helper = require('./helper.js') // PEM format: .pem, .crt, .cer (!bin), .key // base64 encoded; the cert file might also include the private key; so key file is optional // DER format: .der, .cer (bin) // binary encoded format; cannot include key file // PKCS#7 / P7B format: .p7b, .p7c // contains cert and ca chain cert files, but not the key file // A PKCS7 certificate is serialized using either PEM or DER format. // PKCS#12 / PFX format: .pfx, .p12 // contains all files: key file, cert and ca chain cert files /** * pem convert module * * @module convert */ /** * conversion from PEM to DER format * if private key is included in PEM encoded file, it won't be included in DER file * use this method with type 'rsa' to export private key in that case * @param {String} pathIN path of the PEM encoded certificate file * @param {String} pathOUT path of the DER encoded certificate file to generate * @param {String} [type] type of file, use 'rsa' for key file, 'x509' otherwise or leave this parameter out * @param {Function} callback callback method called with error, boolean result */ module.exports.PEM2DER = function (pathIN, pathOUT, type, callback) { if (!callback && typeof type === 'function') { callback = type type = 'x509' } var params = [ type, '-outform', 'der', '-in', pathIN, '-out', pathOUT ] openssl.spawnWrapper(params, false, function (error, code) { if (error) { callback(error) } else { callback(null, code === 0) } }) } /** * conversion from DER to PEM format * @param {String} pathIN path of the DER encoded certificate file * @param {String} pathOUT path of the PEM encoded certificate file to generate * @param {String} [type] type of file, use 'rsa' for key file, 'x509' otherwise or leave this parameter out * @param {Function} callback callback method called with error, boolean result */ module.exports.DER2PEM = function (pathIN, pathOUT, type, callback) { if (!callback && typeof type === 'function') { callback = type type = 'x509' } var params = [ type, '-inform', 'der', '-in', pathIN, '-out', pathOUT ] openssl.spawnWrapper(params, false, function (error, code) { if (error) { callback(error) } else { callback(null, code === 0) } }) } /** * conversion from PEM to P7B format * @param {Object} pathBundleIN paths of the PEM encoded certificate files ({cert: '...', ca: '...' or ['...', ...]}) * @param {String} pathOUT path of the P7B encoded certificate file to generate * @param {Function} callback callback method called with error, boolean result */ module.exports.PEM2P7B = function (pathBundleIN, pathOUT, callback) { var params = [ 'crl2pkcs7', '-nocrl', '-certfile', pathBundleIN.cert, '-out', pathOUT ] if (pathBundleIN.ca) { if (!Array.isArray(pathBundleIN.ca)) { pathBundleIN.ca = [ pathBundleIN.ca ] } pathBundleIN.ca.forEach(function (ca) { params.push('-certfile') params.push(ca) }) } openssl.spawnWrapper(params, false, function (error, code) { if (error) { callback(error) } else { callback(null, code === 0) } }) } /** * conversion from P7B to PEM format * @param {String} pathIN path of the P7B encoded certificate file * @param {String} pathOUT path of the PEM encoded certificate file to generate * @param {Function} callback callback method called with error, boolean result */ module.exports.P7B2PEM = function (pathIN, pathOUT, callback) { var params = [ 'pkcs7', '-print_certs', '-in', pathIN, '-out', pathOUT ] openssl.spawnWrapper(params, false, function (error, code) { if (error) { callback(error) } else { callback(null, code === 0) } }) }// TODO: CA also included? /** * conversion from PEM to PFX * @param {Object} pathBundleIN paths of the PEM encoded certificate files ({cert: '...', key: '...', ca: '...' or ['...', ...]}) * @param {String} pathOUT path of the PFX encoded certificate file to generate * @param {String} password password to set for accessing the PFX file * @param {Function} callback callback method called with error, boolean result */ module.exports.PEM2PFX = function (pathBundleIN, pathOUT, password, callback) { var params = [ 'pkcs12', '-export', '-out', pathOUT, '-inkey', pathBundleIN.key, '-in', pathBundleIN.cert ] if (pathBundleIN.ca) { if (!Array.isArray(pathBundleIN.ca)) { pathBundleIN.ca = [ pathBundleIN.ca ] } pathBundleIN.ca.forEach(function (ca) { params.push('-certfile') params.push(ca) }) } var delTempPWFiles = [] helper.createPasswordFile({ 'cipher': '', 'password': password, 'passType': 'in' }, params, delTempPWFiles) helper.createPasswordFile({ 'cipher': '', 'password': password, 'passType': 'out' }, params, delTempPWFiles) openssl.spawnWrapper(params, false, function (error, code) { function done (error) { if (error) { callback(error) } else { callback(null, code === 0) } } helper.deleteTempFiles(delTempPWFiles, function (fsErr) { done(error || fsErr) }) }) } /** * conversion from PFX to PEM * @param {Object} pathIN path of the PFX encoded certificate file * @param {String} pathOUT path of the PEM encoded certificate file to generate * @param {String} password password to set for accessing the PFX file * @param {Function} callback callback method called with error, boolean result */ module.exports.PFX2PEM = function (pathIN, pathOUT, password, callback) { var params = [ 'pkcs12', '-in', pathIN, '-out', pathOUT, '-nodes' ] var delTempPWFiles = [] helper.createPasswordFile({ 'cipher': '', 'password': password, 'passType': 'in' }, params, delTempPWFiles) helper.createPasswordFile({ 'cipher': '', 'password': password, 'passType': 'out' }, params, delTempPWFiles) openssl.spawnWrapper(params, false, function (error, code) { function done (error) { if (error) { callback(error) } else { callback(null, code === 0) } } helper.deleteTempFiles(delTempPWFiles, function (fsErr) { done(error || fsErr) }) }) } /** * conversion from P7B to PFX/PKCS#12 * @param {Object} pathBundleIN paths of the PEM encoded certificate files ({cert: '...', key: '...', ca: '...' or ['...', ...]}) * @param {String} pathOUT path of the PFX certificate file to generate * @param {String} password password to be set for the PFX file and to be used to access the key file * @param {Function} callback callback method called with error, boolean result */ module.exports.P7B2PFX = function (pathBundleIN, pathOUT, password, callback) { var tmpfile = pathBundleIN.cert.replace(/\.[^.]+$/, '.cer') var params = [ 'pkcs7', '-print_certs', '-in', pathBundleIN.cert, '-out', tmpfile ] openssl.spawnWrapper(params, false, function (error, code) { if (error) { callback(error) } else { var params = [ 'pkcs12', '-export', '-in', tmpfile, '-inkey', pathBundleIN.key, '-out', pathOUT ] if (pathBundleIN.ca) { if (!Array.isArray(pathBundleIN.ca)) { pathBundleIN.ca = [ pathBundleIN.ca ] } pathBundleIN.ca.forEach(function (ca) { params.push('-certfile') params.push(ca) }) } var delTempPWFiles = [tmpfile] helper.createPasswordFile({ 'cipher': '', 'password': password, 'passType': 'in' }, params, delTempPWFiles) helper.createPasswordFile({ 'cipher': '', 'password': password, 'passType': 'out' }, params, delTempPWFiles) openssl.spawnWrapper(params, false, function (error, code) { function done (error) { if (error) { callback(error) } else { callback(null, code === 0) } } helper.deleteTempFiles(delTempPWFiles, function (fsErr) { done(error || fsErr) }) }) } }) }