v1.2.5: fix multiple bugs with conversion
This commit is contained in:
		
							parent
							
								
									a5236f6c2f
								
							
						
					
					
						commit
						ad312edfa6
					
				
							
								
								
									
										110
									
								
								bin/keypairs.js
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								bin/keypairs.js
									
									
									
									
									
								
							@ -13,7 +13,7 @@ var Keypairs = require('../');
 | 
			
		||||
var pkg = require('../package.json');
 | 
			
		||||
 | 
			
		||||
var args = process.argv.slice(2);
 | 
			
		||||
var opts = { jwks: [], jwts: [], jwss: [], payloads: [], names: [], filenames: [], files: [], pems: [] };
 | 
			
		||||
var opts = { keys: [], jwts: [], jwss: [], payloads: [], names: [], filenames: [], files: [] };
 | 
			
		||||
var conflicts = {
 | 
			
		||||
  'namedCurve': 'modulusLength'
 | 
			
		||||
, 'public': 'private'
 | 
			
		||||
@ -187,13 +187,7 @@ args.forEach(function (arg) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Possibly the output file
 | 
			
		||||
  if (!opts.extra1) {
 | 
			
		||||
    opts.extra1 = arg;
 | 
			
		||||
    opts.names.push({ taken: false, name: arg });
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (!opts.extra2) {
 | 
			
		||||
    opts.extra2 = arg;
 | 
			
		||||
  if (opts.names.length < 3) {
 | 
			
		||||
    opts.names.push({ taken: false, name: arg });
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
@ -220,7 +214,7 @@ function guess(txt, filename) {
 | 
			
		||||
  try {
 | 
			
		||||
    var json = JSON.parse(txt);
 | 
			
		||||
    if (-1 !== [ 'RSA', 'EC' ].indexOf(json.kty)) {
 | 
			
		||||
      opts.jwks.push({ jwk: json, filename: filename });
 | 
			
		||||
      opts.keys.push({ raw: txt, jwk: json, filename: filename });
 | 
			
		||||
      return true;
 | 
			
		||||
    } else if (json.signature && json.payload && (json.header || json.protected)) {
 | 
			
		||||
      opts.jwss.push(json);
 | 
			
		||||
@ -231,15 +225,15 @@ function guess(txt, filename) {
 | 
			
		||||
    }
 | 
			
		||||
  } catch(e) {
 | 
			
		||||
    try {
 | 
			
		||||
      var pem = Eckles.importSync({ pem: txt });
 | 
			
		||||
      var jwk = Eckles.importSync({ pem: txt });
 | 
			
		||||
      // pem._string = txt;
 | 
			
		||||
      opts.pems.push(pem);
 | 
			
		||||
      opts.keys.push({ jwk: jwk, pem: true, raw: txt });
 | 
			
		||||
      return true;
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
      try {
 | 
			
		||||
        var pem = Rasha.importSync({ pem: txt });
 | 
			
		||||
        var jwk = Rasha.importSync({ pem: txt });
 | 
			
		||||
        // pem._string = txt;
 | 
			
		||||
        opts.pems.push(pem);
 | 
			
		||||
        opts.keys.push({ jwk: jwk, pem: true, raw: txt });
 | 
			
		||||
        return true;
 | 
			
		||||
      } catch(e) {
 | 
			
		||||
        // ignore
 | 
			
		||||
@ -348,8 +342,8 @@ if ('sign' === opts.action) {
 | 
			
		||||
 | 
			
		||||
function readKeypair() {
 | 
			
		||||
  // note that the jwk may be a string
 | 
			
		||||
  var jwkopts = opts.jwks.shift();
 | 
			
		||||
  var jwk = jwkopts && jwkopts.jwk;
 | 
			
		||||
  var keyopts = opts.keys.shift();
 | 
			
		||||
  var jwk = keyopts && keyopts.jwk;
 | 
			
		||||
  if (!jwk) {
 | 
			
		||||
    console.error("no keys could be parsed from the given arguments");
 | 
			
		||||
    console.error(opts.names.map(function (t) { return t.name; }));
 | 
			
		||||
@ -358,13 +352,13 @@ function readKeypair() {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // omit the primary private key from the list of actual (or soon-to-be) files
 | 
			
		||||
  if (jwkopts.filename) {
 | 
			
		||||
  if (keyopts.filename) {
 | 
			
		||||
    opts.names = opts.names.filter(function (name) {
 | 
			
		||||
      return name.name !== jwkopts.filename;
 | 
			
		||||
      return name.name !== keyopts.filename;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var pair = { private: null, public: null };
 | 
			
		||||
  var pair = { private: null, public: null, pem: keyopts.pem, raw: keyopts.raw };
 | 
			
		||||
  if (jwk.d) {
 | 
			
		||||
    pair.private = jwk;
 | 
			
		||||
  }
 | 
			
		||||
@ -372,69 +366,91 @@ function readKeypair() {
 | 
			
		||||
  return pair;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Note: some of the conditions can be factored out
 | 
			
		||||
// this was all built in high-speed iterative during the 3ams+
 | 
			
		||||
function convertKeypair(pair) {
 | 
			
		||||
  //var pair = readKeypair();
 | 
			
		||||
 | 
			
		||||
  var ps = [];
 | 
			
		||||
  if (pair.private && !opts.public) {
 | 
			
		||||
    if ((!opts.privEncoding || 'json' === opts.privEncoding) && (!opts.privFormat || 'jwk' === opts.privFormat)) {
 | 
			
		||||
  // if it's private only, or if it's not public-only, produce the private key
 | 
			
		||||
  if (pair.private || !opts.public) {
 | 
			
		||||
    // if it came from pem (or is explicitly json), it should go to jwk
 | 
			
		||||
    // otherwise, if it came from jwk, it should go to pem
 | 
			
		||||
    if (((!opts.privEncoding && pair.pem) || 'json' === opts.privEncoding)
 | 
			
		||||
      && ((!opts.privFormat && pair.pem) || 'jwk' === opts.privFormat)) {
 | 
			
		||||
      ps.push(Promise.resolve(pair.private));
 | 
			
		||||
    } else {
 | 
			
		||||
      ps.push(Keypairs.export({ jwk: pair.private, format: opts.privFormat, encoding: opts.privEncoding }));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // if it's not private key only, we want to produce the public key
 | 
			
		||||
  if (!opts.private) {
 | 
			
		||||
    if (opts.public) {
 | 
			
		||||
      // if it's public-only the ambigious options will fall to the private key
 | 
			
		||||
      // so we need to fix that
 | 
			
		||||
      if (!opts.pubFormat) { opts.pubFormat = opts.privFormat; }
 | 
			
		||||
      if (!opts.pubEncoding) { opts.pubEncoding = opts.privEncoding; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((!opts.pubEncoding || 'json' === opts.pubEncoding) && (!opts.pubFormat || 'jwk' === opts.pubFormat)) {
 | 
			
		||||
    // same as above - swap formats by default
 | 
			
		||||
    if (((!opts.pubEncoding && pair.pem) || 'json' === opts.pubEncoding)
 | 
			
		||||
      && ((!opts.pubFormat && pair.pem) || 'jwk' === opts.pubFormat)) {
 | 
			
		||||
      ps.push(Promise.resolve(pair.public));
 | 
			
		||||
    } else {
 | 
			
		||||
      ps.push(Keypairs.export({ jwk: pair.public, format: opts.pubFormat, encoding: opts.pubEncoding, public: true }));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return Promise.all(ps).then(function (arr) {
 | 
			
		||||
    // only use the first key
 | 
			
		||||
    var key = convert(0, opts.public);
 | 
			
		||||
 | 
			
		||||
  return Promise.all(ps).then(function (exported) {
 | 
			
		||||
    // start with the first key, annotating if it should be public
 | 
			
		||||
    var index = 0;
 | 
			
		||||
    var key = stringifyIfJson(index, opts.public);
 | 
			
		||||
 | 
			
		||||
    // re: opts.names
 | 
			
		||||
    // if we're only doing the public key we can end early
 | 
			
		||||
    // (if the source key was from a file and was in opts.names,
 | 
			
		||||
    // we're safe here because we already removed it earlier)
 | 
			
		||||
 | 
			
		||||
    if (opts.public) {
 | 
			
		||||
      // end early
 | 
			
		||||
      if (opts.names.length) {
 | 
			
		||||
        writeFile(opts.names[0].name, key, !opts.public); // todo make pub/priv param consistent, not flip-flop
 | 
			
		||||
        writeFile(opts.names[index].name, key, !opts.public);
 | 
			
		||||
      } else {
 | 
			
		||||
      console.warn(key + "\n");
 | 
			
		||||
        // output public keys to stderr
 | 
			
		||||
        printPublic(key);
 | 
			
		||||
      }
 | 
			
		||||
      // end <-- we're not outputting other keys
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // private key stuff
 | 
			
		||||
    if (opts.names.length) {
 | 
			
		||||
      writeFile(opts.names[0].name, key, true);
 | 
			
		||||
    if (opts.names.length >= 1) {
 | 
			
		||||
      writeFile(opts.names[index].name, key, true);
 | 
			
		||||
    } else {
 | 
			
		||||
      console.info(key + "\n");
 | 
			
		||||
      printPrivate(key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // pub key stuff
 | 
			
		||||
    if (!opts.private) {
 | 
			
		||||
      if (opts.names.length >= 2) {
 | 
			
		||||
        writeFile(opts.names[1].name, key, false);
 | 
			
		||||
      } else {
 | 
			
		||||
        console.warn(key + "\n");
 | 
			
		||||
      }
 | 
			
		||||
    // we have to output the private key,
 | 
			
		||||
    // but the public key can be derived at any time
 | 
			
		||||
    // so we don't need to put the same noise to the screen
 | 
			
		||||
    if (!opts.private && opts.names.length >= 2) {
 | 
			
		||||
      index = 1;
 | 
			
		||||
      key = stringifyIfJson(index, false);
 | 
			
		||||
      writeFile(opts.names[index].name, key, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return pair;
 | 
			
		||||
 | 
			
		||||
    function convert(i, pub) {
 | 
			
		||||
      if (arr[i].kty) {
 | 
			
		||||
    function stringifyIfJson(i, pub) {
 | 
			
		||||
      if (exported[i].kty) {
 | 
			
		||||
        if (pub) {
 | 
			
		||||
          if (opts.expiresAt) { arr[i].exp = opts.expiresAt; }
 | 
			
		||||
          arr[i].use = "sig";
 | 
			
		||||
          if (opts.expiresAt) { exported[i].exp = opts.expiresAt; }
 | 
			
		||||
          exported[i].use = "sig";
 | 
			
		||||
        }
 | 
			
		||||
        arr[i] = JSON.stringify(arr[i]);
 | 
			
		||||
        exported[i] = JSON.stringify(exported[i]);
 | 
			
		||||
      }
 | 
			
		||||
      return arr[i];
 | 
			
		||||
      return exported[i];
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
@ -445,6 +461,7 @@ function genKeypair() {
 | 
			
		||||
  , modulusLength: opts.modulusLength
 | 
			
		||||
  , namedCurve: opts.namedCurve
 | 
			
		||||
  }).then(function (pair) {
 | 
			
		||||
    // always generate as jwk by default
 | 
			
		||||
    var ps = [];
 | 
			
		||||
    if ((!opts.privEncoding || 'json' === opts.privEncoding) && (!opts.privFormat || 'jwk' === opts.privFormat)) {
 | 
			
		||||
      ps.push(Promise.resolve(pair.private));
 | 
			
		||||
@ -488,8 +505,10 @@ function writeFile(name, key, priv) {
 | 
			
		||||
    overwrite = opts.overwrite;
 | 
			
		||||
    if (!opts.overwrite) {
 | 
			
		||||
      if (priv) {
 | 
			
		||||
        // output private keys to stdout
 | 
			
		||||
        console.info(key + "\n");
 | 
			
		||||
      } else {
 | 
			
		||||
        // output public keys to stderr
 | 
			
		||||
        console.warn(key + "\n");
 | 
			
		||||
      }
 | 
			
		||||
      console.error("'" + name + "' exists! force overwrite with 'overwrite'");
 | 
			
		||||
@ -583,3 +602,10 @@ function decodeJwt(jwt) {
 | 
			
		||||
  , signature: parts[2] //Buffer.from(parts[2], 'base64')
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function printPrivate(key) {
 | 
			
		||||
  console.info(key + "\n");
 | 
			
		||||
}
 | 
			
		||||
function printPublic(key) {
 | 
			
		||||
  console.warn(key + "\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "keypairs",
 | 
			
		||||
  "version": "1.2.2",
 | 
			
		||||
  "version": "1.2.5",
 | 
			
		||||
  "description": "Lightweight RSA/ECDSA keypair generation and JWK <-> PEM",
 | 
			
		||||
  "main": "keypairs.js",
 | 
			
		||||
  "files": [
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user