Comparing version 1.0.1 to 1.1.0
@@ -19,5 +19,60 @@ 'use strict'; | ||
Keypairs.parse = function (opts) { | ||
opts = opts || {}; | ||
var err; | ||
var jwk; | ||
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); | ||
}); | ||
} | ||
return p.then(function (jwk) { | ||
var pubopts = JSON.parse(JSON.stringify(opts)); | ||
pubopts.jwk = jwk; | ||
return Keypairs.publish(pubopts).then(function (pub) { | ||
// 'd' happens to be the name of a private part of both RSA and ECDSA keys | ||
if (opts.public || opts.publish || !jwk.d) { | ||
if (opts.private) { | ||
// TODO test that it can actually sign? | ||
err = new Error("Not a private key '" + JSON.stringify(jwk) + "'"); | ||
err.code = "ENOTPRIVATE"; | ||
return Promise.reject(err); | ||
} | ||
return { public: pub }; | ||
} else { | ||
return { private: jwk, public: pub }; | ||
} | ||
}); | ||
}); | ||
}; | ||
Keypairs.parseOrGenerate = function (opts) { | ||
if (!opts.key) { return Keypairs.generate(opts); } | ||
opts.private = true; | ||
return Keypairs.parse(opts).catch(function (e) { | ||
console.warn(e.message); | ||
return Keypairs.generate(opts); | ||
}); | ||
}; | ||
Keypairs.import = function (opts) { | ||
return Eckles.import(opts.pem).catch(function () { | ||
return Rasha.import(opts.pem); | ||
return Eckles.import(opts).catch(function () { | ||
return Rasha.import(opts); | ||
}); | ||
@@ -36,2 +91,23 @@ }; | ||
Keypairs.publish = function (opts) { | ||
if ('object' !== typeof opts.jwk || !opts.jwk.kty) { throw new Error("invalid jwk: " + JSON.stringify(opts.jwk)); } | ||
// trying to find the best balance of an immutable copy with custom attributes | ||
var jwk = {}; | ||
Object.keys(opts.jwk).forEach(function (k) { | ||
// 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])); | ||
}); | ||
if (!jwk.exp) { | ||
if (opts.expiresIn) { jwk.exp = Math.round(Date.now()/1000) + opts.expiresIn; } | ||
else { jwk.exp = opts.expiresAt; } | ||
} | ||
if (!jwk.use && false !== jwk.use) { jwk.use = "sig"; } | ||
if (jwk.kid) { return Promise.resolve(jwk); } | ||
return Keypairs.thumbprint({ jwk: jwk }).then(function (thumb) { jwk.kid = thumb; return jwk; }); | ||
}; | ||
Keypairs.thumbprint = function (opts) { | ||
@@ -38,0 +114,0 @@ return Promise.resolve().then(function () { |
{ | ||
"name": "keypairs", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "Lightweight RSA/ECDSA keypair generation and JWK <-> PEM", | ||
@@ -8,3 +8,3 @@ "main": "keypairs.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "node test.js" | ||
}, | ||
@@ -25,5 +25,5 @@ "repository": { | ||
"dependencies": { | ||
"eckles": "^1.4.0", | ||
"rasha": "^1.2.1" | ||
"eckles": "^1.4.1", | ||
"rasha": "^1.2.4" | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
# Keypairs for node.js | ||
# Keypairs.js | ||
@@ -16,2 +16,3 @@ Lightweight JavaScript RSA and ECDSA utils that work on Windows, Mac, and Linux | ||
* [x] JWK-to-PEM | ||
* [x] Create JWTs (and sign JWS) | ||
* [x] SHA256 JWK Thumbprints | ||
@@ -24,3 +25,2 @@ * [ ] JWK fetching. See [Keyfetch.js](https://npmjs.com/packages/keyfetch/) | ||
* [ ] sign JWS | ||
* [ ] generate CSR (DER as PEM or base64url) | ||
@@ -59,2 +59,12 @@ | ||
* generate | ||
* parse | ||
* parseOrGenerate | ||
* import (PEM-to-JWK) | ||
* export (JWK-to-PEM, private or public) | ||
* publish (Private JWK to Public JWK) | ||
* thumbprint (JWK SHA256) | ||
* signJwt | ||
* signJws | ||
#### Keypairs.generate(options) | ||
@@ -71,2 +81,46 @@ | ||
#### Keypairs.parse(options) | ||
Parses either a JWK (encoded as JSON) or an x509 (encdode as PEM) and gives | ||
back the JWK representation. | ||
Option Examples: | ||
* JWK { key: '{ "kty":"EC", ... }' } | ||
* PEM { key: '-----BEGIN PRIVATE KEY-----\n...' } | ||
* Public Key Only { key: '-----BEGIN PRIVATE KEY-----\n...', public: true } | ||
* Must Have Private Key { key: '-----BEGIN PUBLIC KEY-----\n...', private: true } | ||
Example: | ||
```js | ||
Keypairs.parse({ key: '...' }).catch(function (e) { | ||
// could not be parsed or was a public key | ||
console.warn(e); | ||
return Keypairs.generate(); | ||
}); | ||
``` | ||
#### Keypairs.parseOrGenerate({ key, throw, [generate opts]... }) | ||
Parses the key. Logs a warning on failure, marches on. | ||
(a shortcut for the above, with `private: true`) | ||
Option Examples: | ||
* parse key if exist, otherwise generate `{ key: process.env["PRIVATE_KEY"] }` | ||
* generated key curve `{ key: null, namedCurve: 'P-256' }` | ||
* generated key modulus `{ key: null, modulusLength: 2048 }` | ||
Example: | ||
```js | ||
Keypairs.parseOrGenerate({ key: process.env["PRIVATE_KEY"] }).then(function (pair) { | ||
console.log(pair.public); | ||
}) | ||
``` | ||
Great for when you have a set of shared keys for development and randomly | ||
generated keys in | ||
#### Keypairs.import({ pem: '...' } | ||
@@ -92,2 +146,6 @@ | ||
#### Keypairs.publish({ jwk: jwk }) | ||
**Synchronously** strips a key of its private parts and returns the public version. | ||
#### Keypairs.thumbprint({ jwk: jwk }) | ||
@@ -142,10 +200,14 @@ | ||
Keypairs.js provides a 1-to-1 mapping to the Rasha.js and Eckles.js APIs, | ||
but it also includes the additional convenience methods `signJwt` and `signJws`. | ||
Keypairs.js provides a 1-to-1 mapping to the Rasha.js and Eckles.js APIs for the following: | ||
That is to say that any option you pass to Keypairs will be passed directly to the corresponding API | ||
of either Rasha or Eckles. | ||
* generate(options) | ||
* import({ pem: '---BEGIN...' }) | ||
* export({ jwk: { kty: 'EC', ... }) | ||
* thumbprint({ jwk: jwk }) | ||
If you want to know the algorithm-specific options that are available for those | ||
you'll want to take a look at the corresponding documentation: | ||
* See ECDSA documentation at [Eckles.js](https://git.coolaj86.com/coolaj86/eckles.js/) | ||
* See RSA documentation at [Rasha.js](https://git.coolaj86.com/coolaj86/rasha.js/) | ||
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
13226
210
1
208
Updatedeckles@^1.4.1
Updatedrasha@^1.2.4