{"size": 1603, "ext": "js", "max_stars_repo_path": "index.js", "max_stars_repo_name": "aledbf/smime", "max_stars_repo_stars_event_min_datetime": "2015-01-23T09:46:57.000Z", "max_stars_repo_stars_event_max_datetime": "2017-01-03T14:27:15.000Z", "max_issues_repo_path": "index.js", "max_issues_repo_name": "aledbf/smime", "max_issues_repo_issues_event_min_datetime": "2016-06-20T19:25:50.000Z", "max_issues_repo_issues_event_max_datetime": "2017-01-15T18:35:48.000Z", "max_forks_repo_path": "index.js", "max_forks_repo_name": "aledbf/smime", "max_forks_repo_forks_event_min_datetime": "2017-09-23T18:47:09.000Z", "max_forks_repo_forks_event_max_datetime": "2019-04-05T09:55:28.000Z"}
{"max_stars_count": 7, "max_issues_count": 1, "max_forks_count": 4, "avg_line_length": 23.9253731343, "max_line_length": 76, "alphanum_fraction": 0.6138490331}
var util = require('util');
var spawn = require('child_process').spawn;
var Promise = require('promise');

// Expose methods.
exports.sign = sign;

/**
 * Sign a file.
 *
 * @param {object} options Options
 * @param {stream.Readable} options.content Content stream
 * @param {string} options.key Key path
 * @param {string} options.cert Cert path
 * @param {string} [options.password] Key password
 * @param {function} [cb] Optional callback
 * @returns {object} result Result
 * @returns {string} result.der Der signature
 * @returns {ChildProcess} result.child Child process
 */

function sign(options, cb) {
  return new Promise(function (resolve, reject) {
    options = options || {};

    if (!options.content)
      throw new Error('Invalid content.');

    if (!options.key)
      throw new Error('Invalid key.');

    if (!options.cert)
      throw new Error('Invalid certificate.');

    var command = util.format(
      'openssl smime -sign -text -signer %s -inkey %s -outform DER -binary',
      options.cert,
      options.key
    );

    if (options.password)
      command += util.format(' -passin pass:%s', options.password);

    var args = command.split(' ');
    var child = spawn(args[0], args.splice(1));

    var der = [];

    child.stdout.on('data', function (chunk) {
      der.push(chunk);
    });

    child.on('close', function (code) {
      if (code !== 0)
        reject(new Error('Process failed.'));
      else
        resolve({
          child: child,
          der: Buffer.concat(der)
        });
    });

    options.content.pipe(child.stdin);
  })
  .nodeify(cb);
}
