@sebastienrousseau/crypto-middleware 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +8 -0
- package/README.md +277 -0
- package/dist/common.d.ts +7 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +115 -0
- package/dist/express.d.ts +4 -0
- package/dist/express.d.ts.map +1 -0
- package/dist/express.js +70 -0
- package/dist/fastify.d.ts +6 -0
- package/dist/fastify.d.ts.map +1 -0
- package/dist/fastify.js +100 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/types.d.ts +23 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/package.json +96 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: Apache-2.0 OR MIT -->
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/sebastienrousseau/crypto-service/main/assets/crypto-middleware-logo.svg" alt="crypto-middleware logo" width="360" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">@sebastienrousseau/crypto-middleware</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
Framework-agnostic cryptographic middleware for Express, Fastify, and Koa applications.
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="https://github.com/sebastienrousseau/crypto-service/actions"><img src="https://img.shields.io/github/actions/workflow/status/sebastienrousseau/crypto-service/ci.yml?branch=main&style=for-the-badge&logo=github" alt="Build" /></a>
|
|
15
|
+
<a href="https://coveralls.io/github/sebastienrousseau/crypto-service?branch=main"><img src="https://img.shields.io/coveralls/github/sebastienrousseau/crypto-service?branch=main&style=for-the-badge" alt="Coverage" /></a>
|
|
16
|
+
<a href="https://www.npmjs.com/package/@sebastienrousseau/crypto-middleware"><img src="https://img.shields.io/npm/v/@sebastienrousseau/crypto-middleware.svg?style=for-the-badge&color=f14041&logo=npm" alt="Registry" /></a>
|
|
17
|
+
<a href="https://sebastienrousseau.github.io/crypto-service/"><img src="https://img.shields.io/badge/docs-TypeDoc-blue.svg?style=for-the-badge&labelColor=555555&logo=typescript" alt="Docs" /></a>
|
|
18
|
+
<a href="https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/crypto-service" title="ossf-scorecard"><img src="https://img.shields.io/badge/OpenSSF-Scorecard-blue?style=for-the-badge&logo=openssf" alt="OpenSSF Scorecard" /></a>
|
|
19
|
+
<a href="https://github.com/sebastienrousseau/crypto-service/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0%20OR%20MIT-blue.svg?style=for-the-badge" alt="License: Apache-2.0 OR MIT" /></a>
|
|
20
|
+
<a href="https://github.com/sebastienrousseau/crypto-service/blob/main/docs/POLICIES.md"><img src="https://img.shields.io/badge/Node.js-%3E%3D22-93450a.svg?style=for-the-badge&logo=node.js" alt="Node.js 22 or newer" /></a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Contents
|
|
26
|
+
|
|
27
|
+
**Getting started**
|
|
28
|
+
|
|
29
|
+
- [Install](#install) — installation via pnpm, npm, or yarn
|
|
30
|
+
- [Requirements](#requirements) — runtime floor and environment prerequisites
|
|
31
|
+
- [Quick Start](#quick-start) — minimal working usage sample
|
|
32
|
+
|
|
33
|
+
**The Crypto Service ecosystem**
|
|
34
|
+
|
|
35
|
+
- [The Crypto Service ecosystem](#the-crypto-service-ecosystem) — full 14-package suite overview
|
|
36
|
+
|
|
37
|
+
**Package reference**
|
|
38
|
+
|
|
39
|
+
- [Reference & Usage](#overview) — features, configuration, and capabilities
|
|
40
|
+
- [Examples](#examples) — runnable sample code
|
|
41
|
+
|
|
42
|
+
**Operational**
|
|
43
|
+
|
|
44
|
+
- [Development](#development) — build, lint, format, and test targets
|
|
45
|
+
- [Security](#security) — vulnerability disclosure and cryptographic invariants
|
|
46
|
+
- [Documentation](#documentation) — TypeDoc API docs and ecosystem guides
|
|
47
|
+
- [Stability guarantees](#stability-guarantees) — SemVer axis and release policy
|
|
48
|
+
- [License](#license)
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pnpm add @sebastienrousseau/crypto-middleware
|
|
56
|
+
# or
|
|
57
|
+
npm install @sebastienrousseau/crypto-middleware
|
|
58
|
+
# or
|
|
59
|
+
yarn add @sebastienrousseau/crypto-middleware
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Requirements
|
|
67
|
+
|
|
68
|
+
- **Node.js**: `^22.0.0` or `>=24.0.0` (active and maintenance LTS releases)
|
|
69
|
+
- **Package Manager**: `pnpm >=9` (recommended) or `npm >=10`
|
|
70
|
+
- **TypeScript**: `>=5.0` (when compiling with TypeScript)
|
|
71
|
+
|
|
72
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import express from "express";
|
|
80
|
+
import { createCryptoMiddleware } from "@sebastienrousseau/crypto-middleware";
|
|
81
|
+
|
|
82
|
+
const app = express();
|
|
83
|
+
app.use(express.json());
|
|
84
|
+
|
|
85
|
+
app.use(
|
|
86
|
+
createCryptoMiddleware({
|
|
87
|
+
key: process.env.CRYPTO_KEY, // 256-bit hex key
|
|
88
|
+
operations: ["decrypt-request", "encrypt-response"],
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
app.post("/api/data", (req, res) => {
|
|
93
|
+
// req.body is already decrypted
|
|
94
|
+
res.json({ received: req.body });
|
|
95
|
+
// response is automatically encrypted
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
app.listen(3000);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## The Crypto Service ecosystem
|
|
106
|
+
|
|
107
|
+
Crypto Service provides a complete cryptography stack across 14 specialized packages:
|
|
108
|
+
|
|
109
|
+
| Package | Role | Description |
|
|
110
|
+
| :---------------------------------------------------------------------------------- | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------- |
|
|
111
|
+
| [`@sebastienrousseau/crypto-api`](../crypto-api) | API Schemas | Shared TypeScript types and utilities for the Crypto Service Suite, defining the canonical API surface. |
|
|
112
|
+
| [`@sebastienrousseau/crypto-cli`](../crypto-cli) | Terminal CLI | An interactive command-line interface for cryptographic operations, supporting both legacy OpenPGP and modern post-quantum algorithms. |
|
|
113
|
+
| [`@sebastienrousseau/crypto-edge`](../crypto-edge) | Edge Runtime | Edge-runtime cryptographic operations using the Web Crypto API, optimized for Cloudflare Workers, Vercel Edge, and Deno. |
|
|
114
|
+
| [`@sebastienrousseau/crypto-kms`](../crypto-kms) | Cloud KMS | Unified Key Management Service interface for AWS KMS, GCP Cloud KMS, Azure Key Vault, and HashiCorp Vault. |
|
|
115
|
+
| [`@sebastienrousseau/crypto-lib`](../crypto-lib) | Core Library | A modern cryptographic library for TypeScript, with post-quantum support, zero unsafe dependencies, and 100% test coverage. |
|
|
116
|
+
| **[`@sebastienrousseau/crypto-middleware`](../crypto-middleware)** _(this package)_ | **Middleware** | **Framework-agnostic cryptographic middleware for Express, Fastify, and Koa applications.** |
|
|
117
|
+
| [`@sebastienrousseau/crypto-prisma`](../crypto-prisma) | ORM Adapter | Transparent field-level encryption extension for Prisma Client, using XChaCha20-Poly1305. |
|
|
118
|
+
| [`@sebastienrousseau/crypto-react`](../crypto-react) | React Hooks | React hooks and context provider for client-side cryptographic operations with zero boilerplate. |
|
|
119
|
+
| [`@sebastienrousseau/crypto-sdk`](../crypto-sdk) | Client SDK | A zero-dependency, typed HTTP client for the Crypto Service REST API, with full post-quantum support. |
|
|
120
|
+
| [`@sebastienrousseau/crypto-server`](../crypto-server) | HTTP API | A hardened Fastify REST API for cryptographic operations, with rate limiting, OpenAPI schemas, and post-quantum endpoints. |
|
|
121
|
+
| [`@sebastienrousseau/crypto-testing`](../crypto-testing) | Test Support | Deterministic keys, fast mocks, and test fixtures for crypto-lib |
|
|
122
|
+
| [`@sebastienrousseau/crypto-typeorm`](../crypto-typeorm) | ORM Adapter | TypeORM column-level encryption with a single decorator, powered by crypto-lib. |
|
|
123
|
+
| [`@sebastienrousseau/crypto-vue`](../crypto-vue) | Vue Composables | Vue 3 composables for client-side cryptography |
|
|
124
|
+
| [`@sebastienrousseau/crypto-wasm`](../crypto-wasm) | Acceleration | WebAssembly performance accelerator for crypto-lib |
|
|
125
|
+
|
|
126
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Overview
|
|
131
|
+
|
|
132
|
+
crypto-middleware provides transparent cryptographic operations for
|
|
133
|
+
Express and Fastify applications. It can auto-decrypt incoming
|
|
134
|
+
request bodies, encrypt outgoing responses, verify HMAC signatures
|
|
135
|
+
on webhooks, and validate HS256 JWT bearer tokens -- all via a
|
|
136
|
+
single middleware registration. Route matching via glob patterns
|
|
137
|
+
lets you scope protection to specific endpoints.
|
|
138
|
+
|
|
139
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
140
|
+
|
|
141
|
+
## Express
|
|
142
|
+
|
|
143
|
+
### Configuration
|
|
144
|
+
|
|
145
|
+
| Option | Type | Required | Description |
|
|
146
|
+
| :----------- | :--------- | :------- | :------------------------------------------------ |
|
|
147
|
+
| `key` | `string` | \* | Hex-encoded 256-bit key for encryption/decryption |
|
|
148
|
+
| `routes` | `string[]` | No | Glob patterns for routes to apply middleware to |
|
|
149
|
+
| `operations` | `string[]` | No | Operations to perform (see below) |
|
|
150
|
+
| `hmacKey` | `string` | \* | Hex-encoded HMAC key for signature verification |
|
|
151
|
+
| `jwtSecret` | `string` | \* | Secret for HS256 JWT verification |
|
|
152
|
+
|
|
153
|
+
\* Required when the corresponding operation is enabled.
|
|
154
|
+
|
|
155
|
+
### Operations
|
|
156
|
+
|
|
157
|
+
| Operation | Description |
|
|
158
|
+
| :----------------- | :----------------------------------------------------- |
|
|
159
|
+
| `decrypt-request` | Decrypts incoming JSON bodies |
|
|
160
|
+
| `encrypt-response` | Encrypts outgoing JSON responses |
|
|
161
|
+
| `verify-signature` | Verifies HMAC-SHA256 from `x-signature` header |
|
|
162
|
+
| `verify-jwt` | Verifies HS256 JWT from `Authorization: Bearer` header |
|
|
163
|
+
|
|
164
|
+
### Route Matching
|
|
165
|
+
|
|
166
|
+
| Pattern | Matches |
|
|
167
|
+
| :---------- | :--------------------------------------- |
|
|
168
|
+
| `/api/data` | Exact match only |
|
|
169
|
+
| `/api/*` | One path segment: `/api/users`, `/api/1` |
|
|
170
|
+
| `/api/**` | Any depth: `/api/users/1/profile` |
|
|
171
|
+
|
|
172
|
+
When `routes` is omitted or empty, middleware applies to all routes.
|
|
173
|
+
|
|
174
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
175
|
+
|
|
176
|
+
## Fastify
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import Fastify from "fastify";
|
|
180
|
+
import { cryptoPlugin } from "@sebastienrousseau/crypto-middleware";
|
|
181
|
+
|
|
182
|
+
const app = Fastify();
|
|
183
|
+
|
|
184
|
+
app.register(cryptoPlugin, {
|
|
185
|
+
key: process.env.CRYPTO_KEY,
|
|
186
|
+
operations: ["decrypt-request", "encrypt-response"],
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
app.post("/api/data", async (request) => {
|
|
190
|
+
return { received: request.body };
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
app.listen({ port: 3000 });
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The `cryptoPlugin` accepts the same configuration options as
|
|
197
|
+
`createCryptoMiddleware`.
|
|
198
|
+
|
|
199
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
200
|
+
|
|
201
|
+
## Examples
|
|
202
|
+
|
|
203
|
+
All examples are self-contained TypeScript files in the `examples/`
|
|
204
|
+
directory. Run any example with:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npx ts-node examples/<name>.ts
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
| Category | Example | Purpose |
|
|
211
|
+
| :-------- | :------------------------------------ | :--------------------------------------- |
|
|
212
|
+
| Express | [express.ts](examples/express.ts) | Full Express setup with encrypt/decrypt |
|
|
213
|
+
| Fastify | [fastify.ts](examples/fastify.ts) | Fastify plugin registration |
|
|
214
|
+
| Webhook | [webhook.ts](examples/webhook.ts) | HMAC signature verification for webhooks |
|
|
215
|
+
| JWT | [jwt.ts](examples/jwt.ts) | JWT Bearer token verification |
|
|
216
|
+
| Encrypted | [encrypted.ts](examples/encrypted.ts) | Full encrypted request/response pipeline |
|
|
217
|
+
|
|
218
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
219
|
+
|
|
220
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Development
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
pnpm --filter @sebastienrousseau/crypto-middleware run build
|
|
228
|
+
pnpm --filter @sebastienrousseau/crypto-middleware run test
|
|
229
|
+
pnpm --filter @sebastienrousseau/crypto-middleware run lint
|
|
230
|
+
pnpm --filter @sebastienrousseau/crypto-middleware run format
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
All 18 packages in the Crypto Service workspace maintain a **100% coverage floor** across statements, branches, functions, and lines.
|
|
234
|
+
|
|
235
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Security
|
|
240
|
+
|
|
241
|
+
Report vulnerabilities privately via [GitHub Security Advisories](https://github.com/sebastienrousseau/crypto-service/security/advisories) or according to [`SECURITY.md`](../../SECURITY.md). Never report security issues publicly.
|
|
242
|
+
|
|
243
|
+
Cryptographic operations use the `@noble/*` libraries, Node.js `crypto` and OpenPGP.js. `@noble/post-quantum` has not been independently audited and does not guarantee constant-time execution, and no module in this suite is FIPS 140-3 validated. Key zeroization is limited: JavaScript strings and garbage-collected buffers cannot be reliably wiped. See [`SECURITY.md`](../../SECURITY.md).
|
|
244
|
+
|
|
245
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Documentation
|
|
250
|
+
|
|
251
|
+
- [Full Suite Documentation](https://sebastienrousseau.github.io/crypto-service/)
|
|
252
|
+
- [API Reference (TypeDoc)](https://sebastienrousseau.github.io/crypto-service/)
|
|
253
|
+
- [Developer Guide](../../DEVELOPMENT.md)
|
|
254
|
+
- [Security Policy](../../SECURITY.md)
|
|
255
|
+
- [Architecture & Design](../../ARCHITECTURE.md)
|
|
256
|
+
|
|
257
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Stability guarantees
|
|
262
|
+
|
|
263
|
+
Versions advance strictly one step at a time on the `0.0.x` line (`v0.0.1` → `v0.0.2` → `v0.0.3` ... → `v0.0.999` → `v0.1.0`). Work for every release iteration begins on a dedicated `feat/v<version>` branch.
|
|
264
|
+
|
|
265
|
+
All 18 packages in the workspace move in lockstep. Public API signatures, cipher output formats, and serialization schemas are strictly versioned. Breaking changes to serialized formats or algorithm defaults are considered major breaking changes. Minimum toolchain upgrades (e.g. Node.js LTS floor) are governed by [POLICIES.md](../../docs/POLICIES.md).
|
|
266
|
+
|
|
267
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## License
|
|
272
|
+
|
|
273
|
+
Dual-licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) or [MIT](https://opensource.org/licenses/MIT), at your option.
|
|
274
|
+
|
|
275
|
+
Copyright (c) 2022-2026 Sebastien Rousseau and The Crypto Service Suite contributors.
|
|
276
|
+
|
|
277
|
+
<p align="right"><a href="#contents">Back to Top</a></p>
|
package/dist/common.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { JwtPayload } from "./types";
|
|
2
|
+
export declare function encryptPayload(key: string, data: unknown): string;
|
|
3
|
+
export declare function decryptPayload(key: string, sealed: string): unknown;
|
|
4
|
+
export declare function verifyHmacSignature(hmacKey: string, body: string, signature: string): boolean;
|
|
5
|
+
export declare function verifyJwt(jwtSecret: string, token: string): JwtPayload;
|
|
6
|
+
export declare function matchRoute(path: string, routes: string[]): boolean;
|
|
7
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAyB,UAAU,EAAE,MAAM,SAAS,CAAC;AAgB5D,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAIjE;AAgBD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAYnE;AAsBD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CA4BT;AA6BD,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAqGtE;AAoBD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAYlE"}
|
package/dist/common.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.encryptPayload = encryptPayload;
|
|
4
|
+
exports.decryptPayload = decryptPayload;
|
|
5
|
+
exports.verifyHmacSignature = verifyHmacSignature;
|
|
6
|
+
exports.verifyJwt = verifyJwt;
|
|
7
|
+
exports.matchRoute = matchRoute;
|
|
8
|
+
const crypto_lib_1 = require("@sebastienrousseau/crypto-lib");
|
|
9
|
+
const types_1 = require("./types");
|
|
10
|
+
function encryptPayload(key, data) {
|
|
11
|
+
const plaintext = typeof data === "string" ? data : JSON.stringify(data);
|
|
12
|
+
const result = crypto_lib_1.secretbox.seal(key, plaintext);
|
|
13
|
+
return result.sealed;
|
|
14
|
+
}
|
|
15
|
+
function decryptPayload(key, sealed) {
|
|
16
|
+
try {
|
|
17
|
+
const plainBytes = crypto_lib_1.secretbox.open(key, sealed);
|
|
18
|
+
const plaintext = Buffer.from(plainBytes).toString("utf8");
|
|
19
|
+
return JSON.parse(plaintext);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
throw new types_1.CryptoMiddlewareError(`Decryption failed: ${err.message}`, 400, "DECRYPTION_FAILED");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function verifyHmacSignature(hmacKey, body, signature) {
|
|
26
|
+
if (!signature) {
|
|
27
|
+
throw new types_1.CryptoMiddlewareError("Missing signature header", 401, "MISSING_SIGNATURE");
|
|
28
|
+
}
|
|
29
|
+
const sig = signature.startsWith("sha256=") ? signature.slice(7) : signature;
|
|
30
|
+
const result = (0, crypto_lib_1.verifyHmac)({
|
|
31
|
+
algorithm: "sha256",
|
|
32
|
+
key: hmacKey,
|
|
33
|
+
data: body,
|
|
34
|
+
mac: sig,
|
|
35
|
+
});
|
|
36
|
+
if (!result.valid) {
|
|
37
|
+
throw new types_1.CryptoMiddlewareError("Invalid HMAC signature", 401, "INVALID_SIGNATURE");
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
function base64urlDecode(input) {
|
|
42
|
+
const padded = input + "=".repeat((4 - (input.length % 4)) % 4);
|
|
43
|
+
return Buffer.from(padded, "base64").toString("utf8");
|
|
44
|
+
}
|
|
45
|
+
function verifyJwt(jwtSecret, token) {
|
|
46
|
+
if (!token) {
|
|
47
|
+
throw new types_1.CryptoMiddlewareError("Missing JWT token", 401, "MISSING_TOKEN");
|
|
48
|
+
}
|
|
49
|
+
const parts = token.split(".");
|
|
50
|
+
if (parts.length !== 3) {
|
|
51
|
+
throw new types_1.CryptoMiddlewareError("Malformed JWT: expected 3 parts", 401, "MALFORMED_TOKEN");
|
|
52
|
+
}
|
|
53
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
54
|
+
let header;
|
|
55
|
+
try {
|
|
56
|
+
header = JSON.parse(base64urlDecode(headerB64));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
throw new types_1.CryptoMiddlewareError("Malformed JWT header", 401, "MALFORMED_TOKEN");
|
|
60
|
+
}
|
|
61
|
+
if (header.alg !== "HS256") {
|
|
62
|
+
throw new types_1.CryptoMiddlewareError(`Unsupported JWT algorithm: ${header.alg}. Only HS256 is supported.`, 401, "UNSUPPORTED_ALGORITHM");
|
|
63
|
+
}
|
|
64
|
+
const signingInput = `${headerB64}.${payloadB64}`;
|
|
65
|
+
const keyHex = Buffer.from(jwtSecret, "utf8").toString("hex");
|
|
66
|
+
const computed = (0, crypto_lib_1.computeHmac)({
|
|
67
|
+
algorithm: "sha256",
|
|
68
|
+
key: keyHex,
|
|
69
|
+
data: signingInput,
|
|
70
|
+
});
|
|
71
|
+
const sigPadded = signatureB64 + "=".repeat((4 - (signatureB64.length % 4)) % 4);
|
|
72
|
+
const sigHex = Buffer.from(sigPadded, "base64").toString("hex");
|
|
73
|
+
const computedBytes = Buffer.from(computed.mac, "hex");
|
|
74
|
+
const signatureBytes = Buffer.from(sigHex, "hex");
|
|
75
|
+
if (!(0, crypto_lib_1.timingSafeEqual)(computedBytes, signatureBytes)) {
|
|
76
|
+
throw new types_1.CryptoMiddlewareError("Invalid JWT signature", 401, "INVALID_TOKEN");
|
|
77
|
+
}
|
|
78
|
+
let payload;
|
|
79
|
+
try {
|
|
80
|
+
payload = JSON.parse(base64urlDecode(payloadB64));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
throw new types_1.CryptoMiddlewareError("Malformed JWT payload", 401, "MALFORMED_TOKEN");
|
|
84
|
+
}
|
|
85
|
+
if (payload.exp !== undefined) {
|
|
86
|
+
const now = Math.floor(Date.now() / 1000);
|
|
87
|
+
if (now >= payload.exp) {
|
|
88
|
+
throw new types_1.CryptoMiddlewareError("JWT has expired", 401, "TOKEN_EXPIRED");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (payload.nbf !== undefined) {
|
|
92
|
+
const now = Math.floor(Date.now() / 1000);
|
|
93
|
+
if (now < payload.nbf) {
|
|
94
|
+
throw new types_1.CryptoMiddlewareError("JWT is not yet valid", 401, "TOKEN_NOT_YET_VALID");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return payload;
|
|
98
|
+
}
|
|
99
|
+
function matchRoute(path, routes) {
|
|
100
|
+
if (routes.length === 0)
|
|
101
|
+
return true;
|
|
102
|
+
for (const pattern of routes) {
|
|
103
|
+
if (pattern === path)
|
|
104
|
+
return true;
|
|
105
|
+
const regexStr = pattern
|
|
106
|
+
.replace(/\*\*/g, "___GLOBSTAR___")
|
|
107
|
+
.replace(/\*/g, "[^/]+")
|
|
108
|
+
.replace(/___GLOBSTAR___/g, ".*");
|
|
109
|
+
const regex = new RegExp(`^${regexStr}$`);
|
|
110
|
+
if (regex.test(path))
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from "express";
|
|
2
|
+
import { MiddlewareConfig } from "./types";
|
|
3
|
+
export declare function createCryptoMiddleware(config: MiddlewareConfig): (req: Request, res: Response, next: NextFunction) => void;
|
|
4
|
+
//# sourceMappingURL=express.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAyB,MAAM,SAAS,CAAC;AA6BlE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,IAK3D,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,MAAM,YAAY,KACjB,IAAI,CA0FR"}
|
package/dist/express.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCryptoMiddleware = createCryptoMiddleware;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const common_1 = require("./common");
|
|
6
|
+
function createCryptoMiddleware(config) {
|
|
7
|
+
const operations = config.operations ?? [];
|
|
8
|
+
const routes = config.routes ?? [];
|
|
9
|
+
return function cryptoMiddleware(req, res, next) {
|
|
10
|
+
if (!(0, common_1.matchRoute)(req.path, routes)) {
|
|
11
|
+
next();
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
if (operations.includes("verify-jwt")) {
|
|
16
|
+
if (!config.jwtSecret) {
|
|
17
|
+
throw new types_1.CryptoMiddlewareError("jwtSecret is required for verify-jwt operation", 500, "MISSING_CONFIG");
|
|
18
|
+
}
|
|
19
|
+
const authHeader = req.headers.authorization ?? "";
|
|
20
|
+
const token = authHeader.startsWith("Bearer ")
|
|
21
|
+
? authHeader.slice(7)
|
|
22
|
+
: "";
|
|
23
|
+
const payload = (0, common_1.verifyJwt)(config.jwtSecret, token);
|
|
24
|
+
req.jwtPayload = payload;
|
|
25
|
+
}
|
|
26
|
+
if (operations.includes("verify-signature")) {
|
|
27
|
+
if (!config.hmacKey) {
|
|
28
|
+
throw new types_1.CryptoMiddlewareError("hmacKey is required for verify-signature operation", 500, "MISSING_CONFIG");
|
|
29
|
+
}
|
|
30
|
+
const signature = req.headers["x-signature"] ??
|
|
31
|
+
req.headers["x-hub-signature-256"] ??
|
|
32
|
+
"";
|
|
33
|
+
const rawBody = typeof req.body === "string" ? req.body : JSON.stringify(req.body);
|
|
34
|
+
(0, common_1.verifyHmacSignature)(config.hmacKey, rawBody, signature);
|
|
35
|
+
}
|
|
36
|
+
if (operations.includes("decrypt-request")) {
|
|
37
|
+
if (!config.key) {
|
|
38
|
+
throw new types_1.CryptoMiddlewareError("key is required for decrypt-request operation", 500, "MISSING_CONFIG");
|
|
39
|
+
}
|
|
40
|
+
if (req.body &&
|
|
41
|
+
typeof req.body === "object" &&
|
|
42
|
+
"encrypted" in req.body) {
|
|
43
|
+
req.body = (0, common_1.decryptPayload)(config.key, req.body.encrypted);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (operations.includes("encrypt-response")) {
|
|
47
|
+
if (!config.key) {
|
|
48
|
+
throw new types_1.CryptoMiddlewareError("key is required for encrypt-response operation", 500, "MISSING_CONFIG");
|
|
49
|
+
}
|
|
50
|
+
const originalJson = res.json.bind(res);
|
|
51
|
+
res.json = function encryptedJson(body) {
|
|
52
|
+
const sealed = (0, common_1.encryptPayload)(config.key, body);
|
|
53
|
+
return originalJson({ encrypted: sealed });
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
next();
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (err instanceof types_1.CryptoMiddlewareError) {
|
|
60
|
+
res.status(err.statusCode).json({
|
|
61
|
+
error: err.message,
|
|
62
|
+
code: err.code,
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
next(err);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=express.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import { MiddlewareConfig } from "./types";
|
|
3
|
+
declare function cryptoPluginImpl(fastify: FastifyInstance, opts: MiddlewareConfig): Promise<void>;
|
|
4
|
+
export declare const cryptoPlugin: typeof cryptoPluginImpl;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=fastify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../src/fastify.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAE7E,OAAO,EAAE,gBAAgB,EAAyB,MAAM,SAAS,CAAC;AAyBlE,iBAAe,gBAAgB,CAC7B,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,IAAI,CAAC,CAiHf;AAGD,eAAO,MAAM,YAAY,yBAGvB,CAAC"}
|
package/dist/fastify.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.cryptoPlugin = void 0;
|
|
7
|
+
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
|
|
8
|
+
const types_1 = require("./types");
|
|
9
|
+
const common_1 = require("./common");
|
|
10
|
+
async function cryptoPluginImpl(fastify, opts) {
|
|
11
|
+
const operations = opts.operations ?? [];
|
|
12
|
+
const routes = opts.routes ?? [];
|
|
13
|
+
fastify.addHook("onRequest", async (request, reply) => {
|
|
14
|
+
if (!(0, common_1.matchRoute)(request.url, routes))
|
|
15
|
+
return;
|
|
16
|
+
try {
|
|
17
|
+
if (operations.includes("verify-jwt")) {
|
|
18
|
+
if (!opts.jwtSecret) {
|
|
19
|
+
throw new types_1.CryptoMiddlewareError("jwtSecret is required for verify-jwt operation", 500, "MISSING_CONFIG");
|
|
20
|
+
}
|
|
21
|
+
const authHeader = request.headers.authorization ?? "";
|
|
22
|
+
const token = authHeader.startsWith("Bearer ")
|
|
23
|
+
? authHeader.slice(7)
|
|
24
|
+
: "";
|
|
25
|
+
const payload = (0, common_1.verifyJwt)(opts.jwtSecret, token);
|
|
26
|
+
request.jwtPayload = payload;
|
|
27
|
+
}
|
|
28
|
+
if (operations.includes("verify-signature")) {
|
|
29
|
+
if (!opts.hmacKey) {
|
|
30
|
+
throw new types_1.CryptoMiddlewareError("hmacKey is required for verify-signature operation", 500, "MISSING_CONFIG");
|
|
31
|
+
}
|
|
32
|
+
const signature = request.headers["x-signature"] ??
|
|
33
|
+
request.headers["x-hub-signature-256"] ??
|
|
34
|
+
"";
|
|
35
|
+
const rawBody = typeof request.body === "string"
|
|
36
|
+
? request.body
|
|
37
|
+
: JSON.stringify(request.body);
|
|
38
|
+
(0, common_1.verifyHmacSignature)(opts.hmacKey, rawBody, signature);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (err instanceof types_1.CryptoMiddlewareError) {
|
|
43
|
+
reply.code(err.statusCode).send({
|
|
44
|
+
error: err.message,
|
|
45
|
+
code: err.code,
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (operations.includes("decrypt-request")) {
|
|
53
|
+
fastify.addHook("preHandler", async (request, reply) => {
|
|
54
|
+
if (!(0, common_1.matchRoute)(request.url, routes))
|
|
55
|
+
return;
|
|
56
|
+
if (!opts.key) {
|
|
57
|
+
reply.code(500).send({
|
|
58
|
+
error: "key is required for decrypt-request operation",
|
|
59
|
+
code: "MISSING_CONFIG",
|
|
60
|
+
});
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const body = request.body;
|
|
65
|
+
if (body && typeof body === "object" && "encrypted" in body) {
|
|
66
|
+
request.body =
|
|
67
|
+
(0, common_1.decryptPayload)(opts.key, body.encrypted);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
if (err instanceof types_1.CryptoMiddlewareError) {
|
|
72
|
+
reply.code(err.statusCode).send({
|
|
73
|
+
error: err.message,
|
|
74
|
+
code: err.code,
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (operations.includes("encrypt-response")) {
|
|
83
|
+
fastify.addHook("preSerialization", async (request, _reply, payload) => {
|
|
84
|
+
if (!(0, common_1.matchRoute)(request.url, routes))
|
|
85
|
+
return payload;
|
|
86
|
+
if (!opts.key)
|
|
87
|
+
return payload;
|
|
88
|
+
if (payload !== null && typeof payload === "object") {
|
|
89
|
+
const sealed = (0, common_1.encryptPayload)(opts.key, payload);
|
|
90
|
+
return { encrypted: sealed };
|
|
91
|
+
}
|
|
92
|
+
return payload;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.cryptoPlugin = (0, fastify_plugin_1.default)(cryptoPluginImpl, {
|
|
97
|
+
name: "crypto-middleware",
|
|
98
|
+
fastify: "4.x",
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=fastify.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { MiddlewareConfig, JwtPayload } from "./types";
|
|
2
|
+
export { CryptoMiddlewareError } from "./types";
|
|
3
|
+
export { encryptPayload, decryptPayload, verifyHmacSignature, verifyJwt, matchRoute, } from "./common";
|
|
4
|
+
export { createCryptoMiddleware } from "./express";
|
|
5
|
+
export { cryptoPlugin } from "./fastify";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAGhD,OAAO,EACL,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,SAAS,EACT,UAAU,GACX,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAGnD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cryptoPlugin = exports.createCryptoMiddleware = exports.matchRoute = exports.verifyJwt = exports.verifyHmacSignature = exports.decryptPayload = exports.encryptPayload = exports.CryptoMiddlewareError = void 0;
|
|
4
|
+
var types_1 = require("./types");
|
|
5
|
+
Object.defineProperty(exports, "CryptoMiddlewareError", { enumerable: true, get: function () { return types_1.CryptoMiddlewareError; } });
|
|
6
|
+
var common_1 = require("./common");
|
|
7
|
+
Object.defineProperty(exports, "encryptPayload", { enumerable: true, get: function () { return common_1.encryptPayload; } });
|
|
8
|
+
Object.defineProperty(exports, "decryptPayload", { enumerable: true, get: function () { return common_1.decryptPayload; } });
|
|
9
|
+
Object.defineProperty(exports, "verifyHmacSignature", { enumerable: true, get: function () { return common_1.verifyHmacSignature; } });
|
|
10
|
+
Object.defineProperty(exports, "verifyJwt", { enumerable: true, get: function () { return common_1.verifyJwt; } });
|
|
11
|
+
Object.defineProperty(exports, "matchRoute", { enumerable: true, get: function () { return common_1.matchRoute; } });
|
|
12
|
+
var express_1 = require("./express");
|
|
13
|
+
Object.defineProperty(exports, "createCryptoMiddleware", { enumerable: true, get: function () { return express_1.createCryptoMiddleware; } });
|
|
14
|
+
var fastify_1 = require("./fastify");
|
|
15
|
+
Object.defineProperty(exports, "cryptoPlugin", { enumerable: true, get: function () { return fastify_1.cryptoPlugin; } });
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface MiddlewareConfig {
|
|
2
|
+
key?: string;
|
|
3
|
+
routes?: string[];
|
|
4
|
+
operations?: Array<"decrypt-request" | "encrypt-response" | "verify-signature" | "verify-jwt">;
|
|
5
|
+
hmacKey?: string;
|
|
6
|
+
jwtSecret?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface JwtPayload {
|
|
9
|
+
sub?: string;
|
|
10
|
+
iss?: string;
|
|
11
|
+
aud?: string | string[];
|
|
12
|
+
exp?: number;
|
|
13
|
+
nbf?: number;
|
|
14
|
+
iat?: number;
|
|
15
|
+
jti?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
export declare class CryptoMiddlewareError extends Error {
|
|
19
|
+
readonly statusCode: number;
|
|
20
|
+
readonly code: string;
|
|
21
|
+
constructor(message: string, statusCode: number, code: string);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,gBAAgB;IAE/B,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,UAAU,CAAC,EAAE,KAAK,CAChB,iBAAiB,GAAG,kBAAkB,GAAG,kBAAkB,GAAG,YAAY,CAC3E,CAAC;IAEF,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAcD,MAAM,WAAW,UAAU;IAEzB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAUD,qBAAa,qBAAsB,SAAQ,KAAK;IAE9C,SAAgB,UAAU,EAAE,MAAM,CAAC;IAEnC,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAGjB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAM9D"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CryptoMiddlewareError = void 0;
|
|
4
|
+
class CryptoMiddlewareError extends Error {
|
|
5
|
+
statusCode;
|
|
6
|
+
code;
|
|
7
|
+
constructor(message, statusCode, code) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "CryptoMiddlewareError";
|
|
10
|
+
this.statusCode = statusCode;
|
|
11
|
+
this.code = code;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.CryptoMiddlewareError = CryptoMiddlewareError;
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
package/package.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sebastienrousseau/crypto-middleware",
|
|
3
|
+
"version": "0.0.7",
|
|
4
|
+
"description": "Plug-and-play cryptographic middleware for Express and Fastify -- auto-decrypt requests, verify signatures, and encrypt responses.",
|
|
5
|
+
"author": "Sebastien Rousseau <sebastienrousseau@users.noreply.github.com>",
|
|
6
|
+
"license": "MIT OR Apache-2.0",
|
|
7
|
+
"homepage": "https://crypto-service.co",
|
|
8
|
+
"repository": {
|
|
9
|
+
"directory": "packages/crypto-middleware",
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git@github.com:sebastienrousseau/crypto-service.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/sebastienrousseau/crypto-service/issues"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.0.0"
|
|
18
|
+
},
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"require": "./dist/index.js",
|
|
26
|
+
"import": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/**/*.js",
|
|
31
|
+
"dist/**/*.d.ts",
|
|
32
|
+
"dist/**/*.d.ts.map"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@sebastienrousseau/crypto-lib": "0.0.7"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"express": "^4.0.0",
|
|
39
|
+
"fastify": "^4.0.0",
|
|
40
|
+
"fastify-plugin": "^4.0.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"express": {
|
|
44
|
+
"optional": true
|
|
45
|
+
},
|
|
46
|
+
"fastify": {
|
|
47
|
+
"optional": true
|
|
48
|
+
},
|
|
49
|
+
"fastify-plugin": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@sebastienrousseau/mocha-config": "^0.0.5",
|
|
55
|
+
"@types/chai": "^4.3.7",
|
|
56
|
+
"@types/chai-as-promised": "^8.0.2",
|
|
57
|
+
"@types/express": "^4.17.21",
|
|
58
|
+
"@types/mocha": "^10.0.2",
|
|
59
|
+
"@types/node": "^26.4.1",
|
|
60
|
+
"c8": "^12.0.0",
|
|
61
|
+
"chai": "^4.5.0",
|
|
62
|
+
"chai-as-promised": "^7.1.2",
|
|
63
|
+
"express": "^4.21.0",
|
|
64
|
+
"fastify": "^5.12.5",
|
|
65
|
+
"fastify-plugin": "^6.0.0",
|
|
66
|
+
"mocha": "^10.8.2",
|
|
67
|
+
"rimraf": "^6.1.3",
|
|
68
|
+
"ts-node": "^10.9.2",
|
|
69
|
+
"typedoc": "^0.28.20",
|
|
70
|
+
"typescript": "~5.9.3"
|
|
71
|
+
},
|
|
72
|
+
"keywords": [
|
|
73
|
+
"crypto-middleware",
|
|
74
|
+
"cryptography",
|
|
75
|
+
"express",
|
|
76
|
+
"fastify",
|
|
77
|
+
"encryption",
|
|
78
|
+
"hmac",
|
|
79
|
+
"jwt",
|
|
80
|
+
"middleware"
|
|
81
|
+
],
|
|
82
|
+
"publishConfig": {
|
|
83
|
+
"access": "public"
|
|
84
|
+
},
|
|
85
|
+
"private": false,
|
|
86
|
+
"scripts": {
|
|
87
|
+
"build": "tsc --build tsconfig.json",
|
|
88
|
+
"clean": "rimraf ./coverage ./dist ./docs",
|
|
89
|
+
"test": "c8 --check-coverage --lines 100 --branches 100 --functions 100 --reporter=lcov --reporter=text mocha --config=.mocharc.cjs",
|
|
90
|
+
"docs": "typedoc",
|
|
91
|
+
"lint": "eslint --ext .ts src __tests__",
|
|
92
|
+
"lint:fix": "eslint --cache --fix --ext .ts src __tests__",
|
|
93
|
+
"format": "prettier --write src/**/*.ts",
|
|
94
|
+
"format:check": "prettier --check \"src/**/*.ts\""
|
|
95
|
+
}
|
|
96
|
+
}
|