request-crypto

JWK+JWE based request encryption library that lets Node services securely exchange sensitive payloads over the wire.

Library
npm
v2.0.4
7stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
43/100Fair
Development Activity60
Maintenance36
Community16
Maturity60
Momentum0

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
64/100Good
Architecture68
Code Quality62
Innovation55
Learning Curve70

request-crypto (@elastic/request-crypto) is a small TypeScript library built by Elastic for encrypting and decrypting request payloads using JSON Web Keys (JWK) and JSON Web Encryption (JWE). It exists specifically to solve the problem RSA alone can’t: RSA keys can’t efficiently encrypt large payloads and are slow compared to symmetric ciphers, so this library encrypts the actual payload with a randomly generated 32-byte AES key, then wraps that AES key with an RSA public key delivered as a JWK.

The library was built for Elastic’s own telemetry pipeline, where a Kibana server (the sender) needs to send usage metrics through a browser (the mediator) to Elastic’s telemetry service (the receiver) without exposing the data in transit or letting the mediator read it. The public JWK ships with Kibana, the matching private JWK stays with the telemetry service, and each request generates a fresh AES passphrase so a single compromised key never exposes more than one payload.

It exposes two main entry points: createRequestEncryptor for the sending side and createRequestDecryptor for the receiving side, plus lower-level createJWKManager/createJWKSManager helpers for generating and rotating JWK Sets directly. Internally it composes Elastic’s own @elastic/node-crypto for the AES layer with the node-jose library for JWK/JWE handling, base64url-packing the encrypted AES key and payload together into a single compact string for transport.

What You Get

  • createRequestEncryptor(publicJWKS) — a ready-to-use encryptor that generates a fresh AES key per call, encrypts the payload, then wraps the AES key with the given public JWK
  • createRequestDecryptor(privateJWKS) — the matching decryptor, plus getJWKMetadata() to inspect which key/algorithm encrypted a given payload
  • createJWKManager() / createJWKSManager() — lower-level JWK Set managers for generating, adding, and rotating RSA keys directly
  • Compact, transport-friendly output — the encrypted AES key and payload are packed and base64url-encoded into a single string suitable for an HTTP body
  • TypeScript types for JWK, JWKS, PublicJWK, PrivateJWK, and decrypt results out of the box

Common Use Cases

  • Encrypting telemetry payloads sent from a browser mediator to a backend collection service, as Kibana does
  • Passing sensitive request bodies through an untrusted intermediary that should never see the plaintext
  • Rotating encryption keys via JWK Sets without changing the calling code
  • Verifying which key and algorithm produced a given encrypted payload via getJWKMetadata
  • Any Node service that needs public-key-distributed encryption without RSA’s payload-size ceiling

Under The Hood

Architecture The package is organized around four small modules re-exported from src/index.ts: jwks.ts (the JWKSManager base class wrapping a node-jose key store with encrypt/decrypt/insert/remove operations), jwk.ts (a thin JWKManager subclass that fixes the RSA modulus and encryption use), random-bytes.ts (a one-line AES passphrase generator over Node’s crypto.randomBytes), and request.ts (the public-facing createRequestEncryptor/createRequestDecryptor factories that compose the other three). Data flows in one direction per role: the encryptor generates an AES passphrase, encrypts the payload with @elastic/node-crypto, encrypts the passphrase with the JWK manager, then packBody base64url-joins both into one string; the decryptor reverses each step via unpackBody. There’s no dependency injection framework — composition is done by direct construction — so the abstraction that would break under change is JWKSManager.store, which every other class assumes is a node-jose key store object.

Tech Stack TypeScript 5.1 targeting CommonJS output (tsc build, lib/ as the published entrypoint), tested with Mocha 9 + Chai 4 + ts-node, coverage via nyc, linted with the now-legacy tslint (not ESLint). Runtime dependencies are minimal and deliberate: @elastic/node-crypto for the AES layer and node-jose for JWK/JWE handling, both first-party or well-established crypto libraries rather than hand-rolled cryptography. No web framework, ORM, or database — this is a pure encryption utility meant to be embedded in a host service like Kibana.

Code Quality Tests exist and cover the meaningful paths: jwk.spec.ts checks key set creation, prepopulation from existing public/private JWKS, and encrypt/decrypt round-trips including the failure case of trying to decrypt with a public-only key set; request.spec.ts and random-bytes.spec.ts cover the higher-level encryptor/decryptor and passphrase generation. Types are used throughout (PublicJWK, PrivateJWK, JWKDecryptResult), though a few spots use any for the underlying node-jose store, and error handling is a plain throw Error(...) rather than typed error classes. CI runs via GitHub Actions (.github/workflows/prepare.yml, publish.yml).

What Makes It Unique The library isn’t attempting anything novel in cryptographic terms — hybrid AES+RSA encryption via JWK/JWE is a textbook pattern also used by TLS and PGP, and the README says so directly. Its specific value is a narrow, well-tested implementation of that pattern shaped for one real internal use case (Kibana-to-telemetry-service payloads through an untrusted browser mediator), with JWK Set-based key rotation built in from the start rather than bolted on later.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search