v1.2.8: allow non-stringified jwk in parse, ignore undefineds when neutering
This commit is contained in:
		
							parent
							
								
									885a00c3ae
								
							
						
					
					
						commit
						083cc6d73e
					
				
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							@ -51,6 +51,7 @@ return Keypairs.export({ jwk: pair.private, format: 'pkcs8' }).then(function (pe
 | 
			
		||||
```
 | 
			
		||||
// PEM to JWK
 | 
			
		||||
return Keypairs.import({ pem: pem }).then(function (jwk) {
 | 
			
		||||
  console.log(jwk);
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -164,9 +165,22 @@ Options
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Keypairs.publish({ jwk: jwk })
 | 
			
		||||
#### Keypairs.publish({ jwk: jwk, exp: '3d', use: 'sig' })
 | 
			
		||||
 | 
			
		||||
**Synchronously** strips a key of its private parts and returns the public version.
 | 
			
		||||
Promises a public key that adheres to the OIDC and Auth0 spec (plus expiry), suitable to be published to a JWKs URL:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
{ "kty": "EC"
 | 
			
		||||
, "crv": "P-256"
 | 
			
		||||
, "x": "..."
 | 
			
		||||
, "y": "..."
 | 
			
		||||
, "kid": "..."
 | 
			
		||||
, "use": "sig"
 | 
			
		||||
, "exp": 1552074208
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In particular this adds "use" and "exp".
 | 
			
		||||
 | 
			
		||||
#### Keypairs.thumbprint({ jwk: jwk })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										57
									
								
								keypairs.js
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								keypairs.js
									
									
									
									
									
								
							@ -10,10 +10,19 @@ var Keypairs = module.exports;
 | 
			
		||||
Keypairs.generate = function (opts) {
 | 
			
		||||
  opts = opts || {};
 | 
			
		||||
  var kty = opts.kty || opts.type;
 | 
			
		||||
  var p;
 | 
			
		||||
  if ('RSA' === kty) {
 | 
			
		||||
    return Rasha.generate(opts);
 | 
			
		||||
    p = Rasha.generate(opts);
 | 
			
		||||
  } else {
 | 
			
		||||
    p = Eckles.generate(opts);
 | 
			
		||||
  }
 | 
			
		||||
  return Eckles.generate(opts);
 | 
			
		||||
  return p.then(function (pair) {
 | 
			
		||||
    return Keypairs.thumbprint({ jwk: pair.public }).then(function (thumb) {
 | 
			
		||||
      pair.private.kid = thumb; // maybe not the same id on the private key?
 | 
			
		||||
      pair.public.kid = thumb;
 | 
			
		||||
      return pair;
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Keypairs.parse = function (opts) {
 | 
			
		||||
@ -24,22 +33,26 @@ Keypairs.parse = function (opts) {
 | 
			
		||||
  var pem;
 | 
			
		||||
  var p;
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    jwk = JSON.parse(opts.key);
 | 
			
		||||
    p = Keypairs.export({ jwk: jwk }).catch(function (e) {
 | 
			
		||||
      pem = opts.key;
 | 
			
		||||
      err = new Error("Not a valid jwk '" + JSON.stringify(jwk) + "':" + e.message);
 | 
			
		||||
      err.code = "EINVALID";
 | 
			
		||||
      return Promise.reject(err);
 | 
			
		||||
    }).then(function () {
 | 
			
		||||
      return jwk;
 | 
			
		||||
    });
 | 
			
		||||
  } catch(e) {
 | 
			
		||||
    p = Keypairs.import({ pem: opts.key }).catch(function (e) {
 | 
			
		||||
      err = new Error("Could not parse key (type " + typeof opts.key + ") '" + opts.key + "': " + e.message);
 | 
			
		||||
      err.code = "EPARSE";
 | 
			
		||||
      return Promise.reject(err);
 | 
			
		||||
    });
 | 
			
		||||
  if (!opts.key || !opts.key.kty) {
 | 
			
		||||
    try {
 | 
			
		||||
      jwk = JSON.parse(opts.key);
 | 
			
		||||
      p = Keypairs.export({ jwk: jwk }).catch(function (e) {
 | 
			
		||||
        pem = opts.key;
 | 
			
		||||
        err = new Error("Not a valid jwk '" + JSON.stringify(jwk) + "':" + e.message);
 | 
			
		||||
        err.code = "EINVALID";
 | 
			
		||||
        return Promise.reject(err);
 | 
			
		||||
      }).then(function () {
 | 
			
		||||
        return jwk;
 | 
			
		||||
      });
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
      p = Keypairs.import({ pem: opts.key }).catch(function (e) {
 | 
			
		||||
        err = new Error("Could not parse key (type " + typeof opts.key + ") '" + opts.key + "': " + e.message);
 | 
			
		||||
        err.code = "EPARSE";
 | 
			
		||||
        return Promise.reject(err);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    p = Promise.resolve(opts.key);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return p.then(function (jwk) {
 | 
			
		||||
@ -74,6 +87,11 @@ Keypairs.parseOrGenerate = function (opts) {
 | 
			
		||||
Keypairs.import = function (opts) {
 | 
			
		||||
  return Eckles.import(opts).catch(function () {
 | 
			
		||||
    return Rasha.import(opts);
 | 
			
		||||
  }).then(function (jwk) {
 | 
			
		||||
    return Keypairs.thumbprint({ jwk: jwk }).then(function (thumb) {
 | 
			
		||||
      jwk.kid = thumb;
 | 
			
		||||
      return jwk;
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -93,6 +111,7 @@ Keypairs.neuter = Keypairs._neuter = function (opts) {
 | 
			
		||||
  // trying to find the best balance of an immutable copy with custom attributes
 | 
			
		||||
  var jwk = {};
 | 
			
		||||
  Object.keys(opts.jwk).forEach(function (k) {
 | 
			
		||||
    if ('undefined' === typeof opts.jwk[k]) { return; }
 | 
			
		||||
    // ignore RSA and EC private parts
 | 
			
		||||
    if (-1 !== ['d', 'p', 'q', 'dp', 'dq', 'qi'].indexOf(k)) { return; }
 | 
			
		||||
    jwk[k] = JSON.parse(JSON.stringify(opts.jwk[k]));
 | 
			
		||||
@ -111,7 +130,7 @@ Keypairs.publish = function (opts) {
 | 
			
		||||
  } else {
 | 
			
		||||
    if (opts.exp) { jwk.exp = setTime(opts.exp); }
 | 
			
		||||
    else if (opts.expiresIn) { jwk.exp = Math.round(Date.now()/1000) + opts.expiresIn; }
 | 
			
		||||
    else { jwk.exp = opts.expiresAt; }
 | 
			
		||||
    else if (opts.expiresAt) { jwk.exp = opts.expiresAt; }
 | 
			
		||||
  }
 | 
			
		||||
  if (!jwk.use && false !== jwk.use) { jwk.use = "sig"; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "keypairs",
 | 
			
		||||
  "version": "1.2.7",
 | 
			
		||||
  "version": "1.2.8",
 | 
			
		||||
  "description": "Lightweight RSA/ECDSA keypair generation and JWK <-> PEM",
 | 
			
		||||
  "main": "keypairs.js",
 | 
			
		||||
  "files": [
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user