2019-02-23 09:27:20 +00:00
|
|
|
# Keypairs for node.js
|
2018-11-11 06:59:59 +00:00
|
|
|
|
2019-02-23 09:27:20 +00:00
|
|
|
Lightweight JavaScript RSA and ECDSA utils that work on Windows, Mac, and Linux
|
|
|
|
using modern node.js APIs (no need for C compiler).
|
2018-12-03 07:57:41 +00:00
|
|
|
|
2019-02-23 09:27:20 +00:00
|
|
|
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
|
2018-11-11 06:59:59 +00:00
|
|
|
|
|
|
|
<!--
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-23 09:27:20 +00:00
|
|
|
* [ ] sign JWS
|
|
|
|
* [ ] generate CSR (DER as PEM or base64url)
|
|
|
|
|
|
|
|
-->
|
|
|
|
|
|
|
|
# Usage
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-23 09:27:20 +00:00
|
|
|
A brief (albeit somewhat nonsensical) introduction to the APIs:
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-23 09:27:20 +00:00
|
|
|
```
|
2019-02-27 07:11:50 +00:00
|
|
|
Keypairs.generate().then(function (pair) {
|
|
|
|
return Keypairs.export({ jwk: pair.private }).then(function (pem) {
|
2019-02-23 09:27:20 +00:00
|
|
|
return Keypairs.import({ pem: pem }).then(function (jwk) {
|
|
|
|
return Keypairs.thumbprint({ jwk: jwk }).then(function (thumb) {
|
|
|
|
console.log(thumb);
|
2019-02-27 07:11:50 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
});
|
2019-02-23 09:27:20 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
```
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-23 09:27:20 +00:00
|
|
|
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.
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
## API Overview
|
2019-02-23 09:27:20 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
#### Keypairs.generate(options)
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
Generates a public/private pair of JWKs as `{ private, public }`
|
2019-02-23 09:27:20 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
Option examples:
|
2019-02-23 09:27:20 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
* RSA `{ kty: 'RSA', modulusLength: 2048 }`
|
|
|
|
* ECDSA `{ kty: 'ECDSA', namedCurve: 'P-256' }`
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
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.
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
Options
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
```js
|
|
|
|
{ jwk: jwk
|
|
|
|
, public: true
|
|
|
|
, encoding: 'pem' // or 'der'
|
|
|
|
, format: 'pkcs8' // or 'ssh', 'pkcs1', 'sec1', 'spki'
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Keypairs.thumbprint({ jwk: jwk })
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
Promises a JWK-spec thumbprint: URL Base64-encoded sha256
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
#### Keypairs.signJwt({ jwk, header, claims })
|
2018-05-10 21:19:09 +00:00
|
|
|
|
2019-02-27 07:11:50 +00:00
|
|
|
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
|
2019-02-23 09:27:20 +00:00
|
|
|
of either Rasha or Eckles.
|
2019-02-27 07:11:50 +00:00
|
|
|
|
|
|
|
* 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/)
|
|
|
|
|