jose/README.md
2019-02-24 18:41:23 +01:00

15 KiB

@panva/jose

build codecov

"JSON Web Almost Everything" - JWA, JWS, JWE, JWK, JWKS for Node.js with minimal dependencies

See the @panva/jwt package for JWT.

Table of Contents

Implemented specs & features

The following specifications are implemented by @panva/jose

The test suite utilizes examples defined in RFC7520 to confirm its JOSE implementation is correct.

Detailed feature matrix (Click to expand)

Legend:

  • Implemented
  • Missing node crypto support / won't implement / not planned / PR welcome
JWK Key Types Supported
RSA RSA
Elliptic Curve EC
Octet sequence oct
Serialization JWS Sign JWS Verify JWE Encrypt JWE Decrypt
Compact
General JSON
Flattened JSON
JWS Algorithms Supported
RSASSA-PKCS1-v1_5 RS256, RS384, RS512
RSASSA-PSS PS256, PS384, PS512
ECDSA ES256, ES384, ES512
HMAC with SHA-2 HS256, HS384, HS512
JWE Key Management Algorithms Supported
AES A128KW, A192KW, A256KW
AES GCM A128GCMKW, A192GCMKW, A256GCMKW
Direct Key Agreement dir
RSAES OAEP * RSA-OAEP (*RSA-OAEP-256 is not supported due to its lack of support in Node.JS)
RSAES-PKCS1-v1_5 RSA1_5
PBES2 PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW
ECDH-ES ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW
JWE Content Encryption Algorithms Supported
AES GCM A128GCM, A192GCM, A256GCM
AES_CBC_HMAC_SHA2 A128CBC-HS256, A192CBC-HS384, A256CBC-HS512

Remaining tasks:

  • ✓ JWKS abstraction
  • crit JWE/JWS Header parameter handling
  • b64 JWS crit support
  • ✓ JWE zip handling
  • ✓ JWE/JWS decrypt/verify algorithm whitelisting
  • ◯ JWE/JWS reference (true/false for kid, name of the field for other fields)
  • ◯ whitelist additional JWK reference fields (kid, jku, x5c, x5t, x5t#S256, x5u)
  • ◯ README and documentation
  • ◯ .d.ts types
  • ◯ .github files (templates, CoC, Contributing)
  • @panva/jwt
    • compact only with convenience methods and options
    • @panva/jose as a dependency

Won't implement:

  • ✕ JWS embedded key / referenced verification - won't implement, who needs it can decode the header and pass the (x5c, jwk) to JWK.importKey and validate with that key, similarly the application can handle fetching the referenced x5u or jku
  • ✕ JWS detached content - won't implement, who needs it can remove/attach the payload after/before the respective operation
  • ✕ "none" alg support, no crypto, no use, don't bother

Missing a feature? - If it wasn't already discussed before, ask for it.
Found a bug? - report it.

Support

If you or your business use @panva/jose, please consider becoming a Patron so I can continue maintaining it and adding new features carefree. You may also donate one-time via PayPal.

Usage

The minimal Node.js version supported is v11.8.0

const {
  JWE, // JSON Web Encryption (JWE)
  JWK, // JSON Web Key (JWK)
  JWKS, // JSON Web Key Set (JWKS)
  JWS, // JSON Web Signature (JWS)
  errors // errors utilized by @panva/jose
} = require('@panva/jose')

JWK (JSON Web Key)

All @panva/jose operations require JWK.Key or JWKS.KeyStore as arguments. Here's how to get a JWK.Key.

Class: JWK <RSAKey> | <ECKey> | <OctKey>

<RSAKey>, <ECKey> and <OctKey> represent a key usable for JWS and JWE operations. The JWK.importKey() method is used to retrieve a key representation of an existing key or secret. JWK.generate() method is used to generate a new random key.

JWK #importKey(key[, options]) asymmetric key import

Imports an asymmetric private or public key. Supports importing JWK formatted keys (private, public, secrets), pem and der formatted private and public keys, pem formatted X.509 certificates. Private keys may also be passphrase protected.

API (Click to expand)
  • key: <Object> | <string> | <Buffer> | <KeyObject>
    • key: <string> | <Buffer>
    • format: <string> Must be 'pem' or 'der'. Default: 'pem'.
    • type: <string> Must be 'pkcs1', 'pkcs8' or 'sec1'. This option is required only if the format is 'der' and ignored if it is 'pem'.
    • passphrase: <string> | <Buffer> The passphrase to use for decryption.
  • options: <Object>
    • alg: <string> option identifies the algorithm intended for use with the key.
    • use: <string> option indicates whether the key is to be used for encrypting & decrypting data or signing & verifying data. Must be 'sig' or 'enc'.
    • kid: <string> Key ID Parameter. When not provided is computed using the method defined in RFC7638
  • Returns: <RSAKey> | <ECKey>

See the underlying Node.js API for details on importing private and public keys in the different formats

Example (Click to expand)
const { readFileSync } = require('fs')
const { JWK: { importKey } } = require('@panva/jose')

const key = importKey(readFileSync('path/to/key/file'))
// ECKey {
//   kty: 'EC',
//   public: true,
//   kid: [Getter],
//   crv: [Getter],
//   x: [Getter],
//   y: [Getter] }

JWK #importKey(secret[, options]) secret key import

Imports a symmetric key.

API (Click to expand)
  • secret: <string> | <Buffer> | <KeyObject>
  • options: <Object>
    • alg: <string> option identifies the algorithm intended for use with the key.
    • use: <string> option indicates whether the key is to be used for encrypting & decrypting data or signing & verifying data. Must be 'sig' or 'enc'.
    • kid: <string> Key ID Parameter. When not provided is computed using the method defined in RFC7638
  • Returns: <OctKey>
Example (Click to expand)
const { JWK: { importKey } } = require('@panva/jose')

const key = importKey(Buffer.from('8yHym6h5CG5FylbzrCn8fhxEbp3kOaTsgLaawaaJ'))
// OctKey {
//   kty: 'oct',
//   kid: [Getter],
//   k: [Getter] }

JWK #importKey(jwk) JWK-formatted key import

Imports a JWK formatted key. This supports JWK formatted EC, RSA and oct keys. Asymmetrical keys may be both private and public.

API (Click to expand)
  • jwk: <Object>
    • kty: <string> Key type. Must be 'RSA', 'EC' or 'oct'.
    • alg: <string> option identifies the algorithm intended for use with the key.
    • use: <string> option indicates whether the key is to be used for encrypting & decrypting data or signing & verifying data. Must be 'sig' or 'enc'.
    • kid: <string> Key ID Parameter. When not provided is computed using the method defined in RFC7638
    • e, n properties as <string> for RSA public keys
    • e, n, d, p, q, dp, dq, qi properties as <string> for RSA private keys
    • crv, x, y properties as <string> for EC public keys
    • crv, x, y, d properties as <string> for EC private keys
    • k properties as <string> for secret oct keys
  • Returns: <RSAKey> | <ECKey> | <OctKey>
Example (Click to expand)
const { JWK: { importKey } } = require('@panva/jose')
const jwk = {
  kty: 'RSA',
  kid: 'r1LkbBo3925Rb2ZFFrKyU3MVex9T2817Kx0vbi6i_Kc',
  use: 'sig',
  e: 'AQAB',
  n: 'xwQ72P9z9OYshiQ-ntDYaPnnfwG6u9JAdLMZ5o0dmjlcyrvwQRdoFIKPnO65Q8mh6F_LDSxjxa2Yzo_wdjhbPZLjfUJXgCzm54cClXzT5twzo7lzoAfaJlkTsoZc2HFWqmcri0BuzmTFLZx2Q7wYBm0pXHmQKF0V-C1O6NWfd4mfBhbM-I1tHYSpAMgarSm22WDMDx-WWI7TEzy2QhaBVaENW9BKaKkJklocAZCxk18WhR0fckIGiWiSM5FcU1PY2jfGsTmX505Ub7P5Dz75Ygqrutd5tFrcqyPAtPTFDk8X1InxkkUwpP3nFU5o50DGhwQolGYKPGtQ-ZtmbOfcWQ'
}

const key = importKey(jwk)
// RSAKey {
//   kty: 'RSA',
//   public: true,
//   use: 'sig',
//   kid: 'r1LkbBo3925Rb2ZFFrKyU3MVex9T2817Kx0vbi6i_Kc',
//   e: [Getter],
//   n: [Getter] }

JWK #generate(kty[, crvOrSize[, options[, private]]]) generating new keys

Securely generates a new RSA, EC or oct key.

API (Click to expand)
  • kty: <string> Key type. Must be 'RSA', 'EC' or 'oct'.
  • crvOrSize: <number> | <string> key's bit size or in case of EC keys the curve
  • options: <Object>
    • alg: <string> option identifies the algorithm intended for use with the key.
    • use: <string> option indicates whether the key is to be used for encrypting & decrypting data or signing & verifying data. Must be 'sig' or 'enc'.
    • kid: <string> Key ID Parameter. When not provided is computed using the method defined in RFC7638
  • private: <boolean> Default 'true'. Is the resulting key private or public (when asymmetrical)
  • Returns: Promise<RSAKey> | Promise<ECKey> | Promise<OctKey>

JWK #generateSync(kty[, crvOrSize[, options[, private]]])

Synchronous version of JWK #generate

API (Click to expand)
  • kty: <string> Key type. Must be 'RSA', 'EC' or 'oct'.
  • crvOrSize: <number> | <string> key's bit size or in case of EC keys the curve. Default 2048 for RSA, 'P-256' for EC and 256 for oct.
  • options: <Object>
    • alg: <string> option identifies the algorithm intended for use with the key.
    • use: <string> option indicates whether the key is to be used for encrypting & decrypting data or signing & verifying data. Must be 'sig' or 'enc'.
    • kid: <string> Key ID Parameter. When not provided is computed using the method defined in RFC7638
  • private: <boolean> Default 'true'. Is the resulting key private or public (when asymmetrical)
  • Returns: <RSAKey> | <ECKey> | <OctKey>

JWKS (JSON Web Key Set)

Class: KeyStore

KeyStore is an abstraction representing a set of JWKs

new KeyStore([keys])

Creates a new KeyStore, either empty or populated.

API (Click to expand)
  • keys: <Key[]> Array of key keys instantiated by JWK.importKey
  • Returns: <KeyStore>

keystore.all([parameters])

Retrieves an array of keys matching the provider parameters, returns all if none are provided. The returned array is sorted by relevance based on the parameters. Keys with the exact algorithm or use specified by the parameters are first.

API (Click to expand)
  • parameters: <Object>
    • kty: <string> Key Type to filter for.
    • alg: <string> Key supported algorithm to filter for.
    • use: <string> Key use to filter for.
    • kid: <string> Key ID to filter for.
  • Returns: <Key[]> Array of key instances or an empty array when none are matching the parameters.

keystore.get([parameters])

Retrieves a single key matching the provider parameters. The most relevant Key based on the parameters is returned.

API (Click to expand)
  • parameters: <Object>
    • kty: <string> Key Type to filter for.
    • alg: <string> Key supported algorithm to filter for.
    • use: <string> Key use to filter for.
    • kid: <string> Key ID to filter for.
  • Returns: <RSAKey> | <ECKey> | <OctKey> | <undefined>

keystore.add(key)

Adds a key instance to the store unless it is already included.

API (Click to expand)
  • key: <RSAKey> | <ECKey> | <OctKey>

keystore.remove(key)

Ensures a key is removed from a store.

API (Click to expand)
  • key: <RSAKey> | <ECKey> | <OctKey>

keystore.generate(...)

Asynchronously generates new random key and automatically adds it to the store. See JWK.generate for the API.

keystore.generateSync(...)

Synchronous version of keystore.generate.