# Keypairs for node.js Lightweight JavaScript RSA and ECDSA utils that work on Windows, Mac, and Linux using modern node.js APIs (no need for C compiler). A thin wrapper around [Eckles.js (ECDSA)](https://git.coolaj86.com/coolaj86/eckles.js/) and [Rasha.js (RSA)](https://git.coolaj86.com/coolaj86/rasha.js/). # Features * [x] Generate keypairs * [x] RSA * [x] ECDSA (P-256, P-384) * [x] PEM-to-JWK * [x] JWK-to-PEM * [x] SHA256 JWK Thumbprints * [ ] JWK fetching. See [Keyfetch.js](https://npmjs.com/packages/keyfetch/) * [ ] OIDC * [ ] Auth0 # Usage A brief (albeit somewhat nonsensical) introduction to the APIs: ``` Keypairs.generate().then(function (pair) { return Keypairs.export({ jwk: pair.private }).then(function (pem) { return Keypairs.import({ pem: pem }).then(function (jwk) { return Keypairs.thumbprint({ jwk: jwk }).then(function (thumb) { console.log(thumb); return Keypairs.signJwt({ jwk: keypair.private , claims: { iss: 'https://example.com' , sub: 'jon.doe@gmail.com' , exp: Math.round(Date.now()/1000) + (3 * 24 * 60 * 60) } }); }); }); }); }); ``` By default ECDSA keys will be used since they've had native support in node _much_ longer than RSA has, and they're smaller, and faster to generate. ## API Overview #### Keypairs.generate(options) Generates a public/private pair of JWKs as `{ private, public }` Option examples: * RSA `{ kty: 'RSA', modulusLength: 2048 }` * ECDSA `{ kty: 'ECDSA', namedCurve: 'P-256' }` When no options are supplied EC P-256 (also known as `prime256v1` and `secp256r1`) is used by default. #### Keypairs.import({ pem: '...' } Takes a PEM in pretty much any format (PKCS1, SEC1, PKCS8, SPKI) and returns a JWK. #### Keypairs.export(options) Exports a JWK as a PEM. Exports PEM in PKCS8 (private) or SPKI (public) by default. Options ```js { jwk: jwk , public: true , encoding: 'pem' // or 'der' , format: 'pkcs8' // or 'ssh', 'pkcs1', 'sec1', 'spki' } ``` #### Keypairs.thumbprint({ jwk: jwk }) Promises a JWK-spec thumbprint: URL Base64-encoded sha256 #### Keypairs.signJwt({ jwk, header, claims }) Returns a JWT (otherwise known as a protected JWS in "compressed" format). ```js { jwk: jwk , claims: { } } ``` Header defaults: ```js { kid: thumbprint , alg: 'xS256' , typ: 'JWT' } ``` Payload notes: * `iat: now` is added by default (set `false` to disable) * `exp` must be set (set `false` to disable) * `iss` should be the base URL for JWK lookup (i.e. via OIDC, Auth0) Notes: `header` is actually the JWS `protected` value, as all JWTs use protected headers (yay!) and `claims` are really the JWS `payload`. #### Keypairs.signJws({ jwk, header, protected, payload }) This is provided for APIs like ACME (Let's Encrypt) that use uncompressed JWS (instead of JWT, which is compressed). Options: * `header` not what you think. Leave undefined unless you need this for the spec you're following. * `protected` is the typical JWT-style header * `kid` and `alg` will be added by default (these are almost always required), set `false` explicitly to disable * `payload` can be JSON, a string, or even a buffer (which gets URL Base64 encoded) * you must set this to something, even if it's an empty string, object, or Buffer # Additional Documentation 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`. That is to say that any option you pass to Keypairs will be passed directly to the corresponding API of either Rasha or Eckles. * 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/)