@sebastienrousseau/crypto-middleware 0.0.8 → 0.0.24

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/README.md CHANGED
@@ -142,16 +142,23 @@ lets you scope protection to specific endpoints.
142
142
 
143
143
  ### Configuration
144
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 |
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
+ | `jwtIssuer` | `string` | No | Required `iss` claim for `verify-jwt` |
153
+ | `jwtAudience` | `string` | No | Required `aud` value for `verify-jwt` |
152
154
 
153
155
  \* Required when the corresponding operation is enabled.
154
156
 
157
+ `verify-jwt` accepts only HS256 (any other `alg`, including `none`, is
158
+ rejected), requires a numeric `exp` claim, checks `nbf` when present, and
159
+ checks `iss` and `aud` when `jwtIssuer` / `jwtAudience` are set. Set both
160
+ when the secret is shared with any other service.
161
+
155
162
  ### Operations
156
163
 
157
164
  | Operation | Description |
@@ -240,6 +247,8 @@ All 18 packages in the Crypto Service workspace maintain a **100% coverage floor
240
247
 
241
248
  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
249
 
250
+ The middleware verifies JWTs and HMAC signatures but does not rate-limit them. Register a rate limiter in the host application (for example [`@fastify/rate-limit`](https://github.com/fastify/fastify-rate-limit) or [`express-rate-limit`](https://github.com/express-rate-limit/express-rate-limit)) in front of the routes it protects, as `crypto-server` does.
251
+
243
252
  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
253
 
245
254
  <p align="right"><a href="#contents">Back to Top</a></p>
package/dist/common.d.ts CHANGED
@@ -1,7 +1,15 @@
1
- import { JwtPayload } from "./types";
1
+ import { JwtPayload, MiddlewareConfig } from "./types";
2
2
  export declare function encryptPayload(key: string, data: unknown): string;
3
3
  export declare function decryptPayload(key: string, sealed: string): unknown;
4
+ export declare function encryptPqPayload(recipientX25519Public: string, recipientMlKemPublic: string, data: unknown, chunkSize?: number): string;
5
+ export declare function decryptPqPayload(recipientX25519Secret: string, recipientMlKemSecret: string, sealed: string, chunkSize?: number): unknown;
4
6
  export declare function verifyHmacSignature(hmacKey: string, body: string, signature: string): boolean;
5
- export declare function verifyJwt(jwtSecret: string, token: string): JwtPayload;
7
+ export interface JwtVerifyOptions {
8
+ issuer?: string | undefined;
9
+ audience?: string | undefined;
10
+ }
11
+ export declare function verifyJwt(jwtSecret: string, token: string, options?: JwtVerifyOptions): JwtPayload;
12
+ export declare function verifyBearerJwt(config: MiddlewareConfig, authorization: string | undefined): JwtPayload;
13
+ export declare function verifyRequestSignature(config: MiddlewareConfig, headers: Record<string, string | string[] | undefined>, body: unknown): void;
6
14
  export declare function matchRoute(path: string, routes: string[]): boolean;
7
15
  //# sourceMappingURL=common.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAyB,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAgB9E,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;AAYD,wBAAgB,gBAAgB,CAC9B,qBAAqB,EAAE,MAAM,EAC7B,oBAAoB,EAAE,MAAM,EAC5B,IAAI,EAAE,OAAO,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAUR;AAYD,wBAAgB,gBAAgB,CAC9B,qBAAqB,EAAE,MAAM,EAC7B,oBAAoB,EAAE,MAAM,EAC5B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAmBT;AAsBD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CA4BT;AAWD,MAAM,WAAW,gBAAgB;IAK/B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAM5B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAiHD,wBAAgB,SAAS,CACvB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,gBAAqB,GAC7B,UAAU,CAcZ;AAUD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,gBAAgB,EACxB,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC,UAAU,CAcZ;AAUD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,EACtD,IAAI,EAAE,OAAO,GACZ,IAAI,CAcN;AAoBD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAYlE"}
package/dist/common.js CHANGED
@@ -2,10 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.encryptPayload = encryptPayload;
4
4
  exports.decryptPayload = decryptPayload;
5
+ exports.encryptPqPayload = encryptPqPayload;
6
+ exports.decryptPqPayload = decryptPqPayload;
5
7
  exports.verifyHmacSignature = verifyHmacSignature;
6
8
  exports.verifyJwt = verifyJwt;
9
+ exports.verifyBearerJwt = verifyBearerJwt;
10
+ exports.verifyRequestSignature = verifyRequestSignature;
7
11
  exports.matchRoute = matchRoute;
8
12
  const crypto_lib_1 = require("@sebastienrousseau/crypto-lib");
13
+ const streaming_1 = require("@sebastienrousseau/crypto-lib/streaming");
9
14
  const types_1 = require("./types");
10
15
  function encryptPayload(key, data) {
11
16
  const plaintext = typeof data === "string" ? data : JSON.stringify(data);
@@ -22,6 +27,34 @@ function decryptPayload(key, sealed) {
22
27
  throw new types_1.CryptoMiddlewareError(`Decryption failed: ${err.message}`, 400, "DECRYPTION_FAILED");
23
28
  }
24
29
  }
30
+ function encryptPqPayload(recipientX25519Public, recipientMlKemPublic, data, chunkSize) {
31
+ const plaintext = typeof data === "string" ? data : JSON.stringify(data);
32
+ const ptBytes = Buffer.from(plaintext, "utf8");
33
+ const res = (0, streaming_1.streamPqEncrypt)({
34
+ recipientX25519Public,
35
+ recipientMlKemPublic,
36
+ plaintext: ptBytes,
37
+ ...(chunkSize !== undefined ? { chunkSize } : {}),
38
+ });
39
+ return Buffer.from(res.ciphertext).toString("base64");
40
+ }
41
+ function decryptPqPayload(recipientX25519Secret, recipientMlKemSecret, sealed, chunkSize) {
42
+ try {
43
+ const ctBytes = Buffer.from(sealed, "base64");
44
+ const decrypted = (0, streaming_1.streamPqDecrypt)({
45
+ recipientX25519Secret,
46
+ recipientMlKemSecret,
47
+ ciphertext: ctBytes,
48
+ ...(chunkSize !== undefined ? { chunkSize } : {}),
49
+ });
50
+ const plaintext = Buffer.from(decrypted).toString("utf8");
51
+ (0, crypto_lib_1.wipeMemory)(decrypted);
52
+ return JSON.parse(plaintext);
53
+ }
54
+ catch (err) {
55
+ throw new types_1.CryptoMiddlewareError(`PQ decryption failed: ${err.message}`, 400, "DECRYPTION_FAILED");
56
+ }
57
+ }
25
58
  function verifyHmacSignature(hmacKey, body, signature) {
26
59
  if (!signature) {
27
60
  throw new types_1.CryptoMiddlewareError("Missing signature header", 401, "MISSING_SIGNATURE");
@@ -42,26 +75,32 @@ function base64urlDecode(input) {
42
75
  const padded = input + "=".repeat((4 - (input.length % 4)) % 4);
43
76
  return Buffer.from(padded, "base64").toString("utf8");
44
77
  }
45
- function verifyJwt(jwtSecret, token) {
46
- if (!token) {
47
- throw new types_1.CryptoMiddlewareError("Missing JWT token", 401, "MISSING_TOKEN");
48
- }
78
+ function reject(message, code) {
79
+ throw new types_1.CryptoMiddlewareError(message, 401, code);
80
+ }
81
+ function splitToken(token) {
82
+ if (!token)
83
+ reject("Missing JWT token", "MISSING_TOKEN");
49
84
  const parts = token.split(".");
50
85
  if (parts.length !== 3) {
51
- throw new types_1.CryptoMiddlewareError("Malformed JWT: expected 3 parts", 401, "MALFORMED_TOKEN");
86
+ reject("Malformed JWT: expected 3 parts", "MALFORMED_TOKEN");
52
87
  }
53
- const [headerB64, payloadB64, signatureB64] = parts;
54
- let header;
88
+ return parts;
89
+ }
90
+ function decodeObject(segment, name) {
91
+ let value;
55
92
  try {
56
- header = JSON.parse(base64urlDecode(headerB64));
93
+ value = JSON.parse(base64urlDecode(segment));
57
94
  }
58
95
  catch {
59
- throw new types_1.CryptoMiddlewareError("Malformed JWT header", 401, "MALFORMED_TOKEN");
96
+ value = undefined;
60
97
  }
61
- if (header.alg !== "HS256") {
62
- throw new types_1.CryptoMiddlewareError(`Unsupported JWT algorithm: ${header.alg}. Only HS256 is supported.`, 401, "UNSUPPORTED_ALGORITHM");
98
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
99
+ reject(`Malformed JWT ${name}`, "MALFORMED_TOKEN");
63
100
  }
64
- const signingInput = `${headerB64}.${payloadB64}`;
101
+ return value;
102
+ }
103
+ function checkSignature(jwtSecret, signingInput, signatureB64) {
65
104
  const keyHex = Buffer.from(jwtSecret, "utf8").toString("hex");
66
105
  const computed = (0, crypto_lib_1.computeHmac)({
67
106
  algorithm: "sha256",
@@ -69,33 +108,71 @@ function verifyJwt(jwtSecret, token) {
69
108
  data: signingInput,
70
109
  });
71
110
  const sigPadded = signatureB64 + "=".repeat((4 - (signatureB64.length % 4)) % 4);
72
- const sigHex = Buffer.from(sigPadded, "base64").toString("hex");
111
+ const signatureBytes = Buffer.from(sigPadded, "base64");
73
112
  const computedBytes = Buffer.from(computed.mac, "hex");
74
- const signatureBytes = Buffer.from(sigHex, "hex");
75
113
  if (!(0, crypto_lib_1.timingSafeEqual)(computedBytes, signatureBytes)) {
76
- throw new types_1.CryptoMiddlewareError("Invalid JWT signature", 401, "INVALID_TOKEN");
114
+ reject("Invalid JWT signature", "INVALID_TOKEN");
77
115
  }
78
- let payload;
79
- try {
80
- payload = JSON.parse(base64urlDecode(payloadB64));
116
+ }
117
+ function checkTimes(payload) {
118
+ const now = Math.floor(Date.now() / 1000);
119
+ if (typeof payload.exp !== "number") {
120
+ reject("JWT has no numeric exp claim", "MISSING_EXPIRATION");
81
121
  }
82
- catch {
83
- throw new types_1.CryptoMiddlewareError("Malformed JWT payload", 401, "MALFORMED_TOKEN");
122
+ if (now >= payload.exp)
123
+ reject("JWT has expired", "TOKEN_EXPIRED");
124
+ if (payload.nbf === undefined)
125
+ return;
126
+ if (typeof payload.nbf !== "number") {
127
+ reject("JWT nbf claim is not a number", "MALFORMED_TOKEN");
128
+ }
129
+ if (now < payload.nbf)
130
+ reject("JWT is not yet valid", "TOKEN_NOT_YET_VALID");
131
+ }
132
+ function checkIssuerAudience(payload, options) {
133
+ if (options.issuer !== undefined && payload.iss !== options.issuer) {
134
+ reject("JWT issuer is not accepted", "INVALID_ISSUER");
84
135
  }
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
- }
136
+ if (options.audience === undefined)
137
+ return;
138
+ const aud = Array.isArray(payload.aud) ? payload.aud : [payload.aud];
139
+ if (!aud.includes(options.audience)) {
140
+ reject("JWT audience is not accepted", "INVALID_AUDIENCE");
90
141
  }
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
- }
142
+ }
143
+ function verifyJwt(jwtSecret, token, options = {}) {
144
+ const [headerB64, payloadB64, signatureB64] = splitToken(token);
145
+ const header = decodeObject(headerB64, "header");
146
+ if (header["alg"] !== "HS256") {
147
+ reject(`Unsupported JWT algorithm: ${String(header["alg"])}. Only HS256 is supported.`, "UNSUPPORTED_ALGORITHM");
96
148
  }
149
+ checkSignature(jwtSecret, `${headerB64}.${payloadB64}`, signatureB64);
150
+ const payload = decodeObject(payloadB64, "payload");
151
+ checkTimes(payload);
152
+ checkIssuerAudience(payload, options);
97
153
  return payload;
98
154
  }
155
+ function verifyBearerJwt(config, authorization) {
156
+ if (!config.jwtSecret) {
157
+ throw new types_1.CryptoMiddlewareError("jwtSecret is required for verify-jwt operation", 500, "MISSING_CONFIG");
158
+ }
159
+ const header = authorization ?? "";
160
+ const token = header.startsWith("Bearer ") ? header.slice(7) : "";
161
+ return verifyJwt(config.jwtSecret, token, {
162
+ issuer: config.jwtIssuer,
163
+ audience: config.jwtAudience,
164
+ });
165
+ }
166
+ function verifyRequestSignature(config, headers, body) {
167
+ if (!config.hmacKey) {
168
+ throw new types_1.CryptoMiddlewareError("hmacKey is required for verify-signature operation", 500, "MISSING_CONFIG");
169
+ }
170
+ const signature = headers["x-signature"] ??
171
+ headers["x-hub-signature-256"] ??
172
+ "";
173
+ const rawBody = typeof body === "string" ? body : JSON.stringify(body);
174
+ verifyHmacSignature(config.hmacKey, rawBody, signature);
175
+ }
99
176
  function matchRoute(path, routes) {
100
177
  if (routes.length === 0)
101
178
  return true;
package/dist/express.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Request, Response, NextFunction } from "express";
2
- import { MiddlewareConfig } from "./types";
2
+ import { MiddlewareConfig, PqStreamPluginConfig } from "./types";
3
3
  export declare function createCryptoMiddleware(config: MiddlewareConfig): (req: Request, res: Response, next: NextFunction) => void;
4
+ export declare function createPqStreamMiddleware(config: PqStreamPluginConfig): (req: Request, res: Response, next: NextFunction) => void;
4
5
  //# sourceMappingURL=express.d.ts.map
@@ -1 +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"}
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,EACL,gBAAgB,EAEhB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAwIjB,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,IAK3D,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,MAAM,YAAY,KACjB,IAAI,CAqBR;AAQD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,SAhC5D,OAAO,OACP,QAAQ,QACP,YAAY,KACjB,IAAI,CAiDR"}
package/dist/express.js CHANGED
@@ -1,8 +1,72 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createCryptoMiddleware = createCryptoMiddleware;
4
+ exports.createPqStreamMiddleware = createPqStreamMiddleware;
4
5
  const types_1 = require("./types");
5
6
  const common_1 = require("./common");
7
+ function requireKey(config, operation) {
8
+ if (!config.key) {
9
+ throw new types_1.CryptoMiddlewareError(`key is required for ${operation} operation`, 500, "MISSING_CONFIG");
10
+ }
11
+ return config.key;
12
+ }
13
+ function decryptBody(config, req) {
14
+ const key = requireKey(config, "decrypt-request");
15
+ if (req.body && typeof req.body === "object" && "encrypted" in req.body) {
16
+ req.body = (0, common_1.decryptPayload)(key, req.body.encrypted);
17
+ }
18
+ }
19
+ function encryptJsonResponses(config, res) {
20
+ const key = requireKey(config, "encrypt-response");
21
+ const originalJson = res.json.bind(res);
22
+ res.json = function encryptedJson(body) {
23
+ const sealed = (0, common_1.encryptPayload)(key, body);
24
+ return originalJson({ encrypted: sealed });
25
+ };
26
+ }
27
+ function decryptPqBody(config, req) {
28
+ const xSecret = config.pqKeys?.recipientX25519Secret;
29
+ const kemSecret = config.pqKeys?.recipientMlKemSecret;
30
+ if (!xSecret || !kemSecret) {
31
+ throw new types_1.CryptoMiddlewareError("recipientX25519Secret and recipientMlKemSecret are required for pq-decrypt-request operation", 500, "MISSING_CONFIG");
32
+ }
33
+ if (req.body && typeof req.body === "object" && "encrypted" in req.body) {
34
+ req.body = (0, common_1.decryptPqPayload)(xSecret, kemSecret, req.body.encrypted, config.chunkSize);
35
+ }
36
+ }
37
+ function encryptPqJsonResponses(config, res) {
38
+ const xPublic = config.pqKeys?.recipientX25519Public;
39
+ const kemPublic = config.pqKeys?.recipientMlKemPublic;
40
+ if (!xPublic || !kemPublic) {
41
+ throw new types_1.CryptoMiddlewareError("recipientX25519Public and recipientMlKemPublic are required for pq-encrypt-response operation", 500, "MISSING_CONFIG");
42
+ }
43
+ const originalJson = res.json.bind(res);
44
+ res.json = function encryptedPqJson(body) {
45
+ const sealed = (0, common_1.encryptPqPayload)(xPublic, kemPublic, body, config.chunkSize);
46
+ return originalJson({
47
+ encrypted: sealed,
48
+ algorithm: "X25519-ML-KEM-768-XChaCha20-Poly1305",
49
+ });
50
+ };
51
+ }
52
+ function applyOperations(config, operations, req, res) {
53
+ if (operations.includes("verify-jwt")) {
54
+ req.jwtPayload = (0, common_1.verifyBearerJwt)(config, req.headers.authorization);
55
+ }
56
+ if (operations.includes("verify-signature")) {
57
+ (0, common_1.verifyRequestSignature)(config, req.headers, req.body);
58
+ }
59
+ if (operations.includes("decrypt-request"))
60
+ decryptBody(config, req);
61
+ if (operations.includes("pq-decrypt-request"))
62
+ decryptPqBody(config, req);
63
+ if (operations.includes("encrypt-response")) {
64
+ encryptJsonResponses(config, res);
65
+ }
66
+ if (operations.includes("pq-encrypt-response")) {
67
+ encryptPqJsonResponses(config, res);
68
+ }
69
+ }
6
70
  function createCryptoMiddleware(config) {
7
71
  const operations = config.operations ?? [];
8
72
  const routes = config.routes ?? [];
@@ -12,47 +76,7 @@ function createCryptoMiddleware(config) {
12
76
  return;
13
77
  }
14
78
  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
- }
79
+ applyOperations(config, operations, req, res);
56
80
  next();
57
81
  }
58
82
  catch (err) {
@@ -67,4 +91,21 @@ function createCryptoMiddleware(config) {
67
91
  }
68
92
  };
69
93
  }
94
+ function createPqStreamMiddleware(config) {
95
+ const operations = [];
96
+ if (config.recipientKeys.recipientX25519Secret &&
97
+ config.recipientKeys.recipientMlKemSecret) {
98
+ operations.push("pq-decrypt-request");
99
+ }
100
+ if (config.recipientKeys.recipientX25519Public &&
101
+ config.recipientKeys.recipientMlKemPublic) {
102
+ operations.push("pq-encrypt-response");
103
+ }
104
+ return createCryptoMiddleware({
105
+ pqKeys: config.recipientKeys,
106
+ ...(config.routes !== undefined ? { routes: config.routes } : {}),
107
+ ...(config.chunkSize !== undefined ? { chunkSize: config.chunkSize } : {}),
108
+ operations,
109
+ });
110
+ }
70
111
  //# sourceMappingURL=express.js.map
package/dist/fastify.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import type { FastifyInstance } from "fastify";
2
- import { MiddlewareConfig } from "./types";
2
+ import { MiddlewareConfig, PqStreamPluginConfig } from "./types";
3
3
  declare function cryptoPluginImpl(fastify: FastifyInstance, opts: MiddlewareConfig): Promise<void>;
4
4
  export declare const cryptoPlugin: typeof cryptoPluginImpl;
5
+ declare function pqStreamPluginImpl(fastify: FastifyInstance, opts: PqStreamPluginConfig): Promise<void>;
6
+ export declare const pqStreamPlugin: typeof pqStreamPluginImpl;
5
7
  export {};
6
8
  //# sourceMappingURL=fastify.d.ts.map
@@ -1 +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"}
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,EACL,gBAAgB,EAEhB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAoMjB,iBAAe,gBAAgB,CAC7B,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAGD,eAAO,MAAM,YAAY,yBAGvB,CAAC;AAGH,iBAAe,kBAAkB,CAC/B,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAmBf;AAGD,eAAO,MAAM,cAAc,2BAGzB,CAAC"}
package/dist/fastify.js CHANGED
@@ -3,98 +3,155 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.cryptoPlugin = void 0;
6
+ exports.pqStreamPlugin = exports.cryptoPlugin = void 0;
7
7
  const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
8
8
  const types_1 = require("./types");
9
9
  const common_1 = require("./common");
10
- async function cryptoPluginImpl(fastify, opts) {
11
- const operations = opts.operations ?? [];
12
- const routes = opts.routes ?? [];
10
+ function sendMiddlewareError(reply, err) {
11
+ if (err instanceof types_1.CryptoMiddlewareError) {
12
+ reply.code(err.statusCode).send({
13
+ error: err.message,
14
+ code: err.code,
15
+ });
16
+ return;
17
+ }
18
+ throw err;
19
+ }
20
+ function registerVerification(fastify, opts, operations, routes) {
13
21
  fastify.addHook("onRequest", async (request, reply) => {
14
22
  if (!(0, common_1.matchRoute)(request.url, routes))
15
23
  return;
16
24
  try {
17
25
  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
+ const payload = (0, common_1.verifyBearerJwt)(opts, request.headers.authorization);
26
27
  request.jwtPayload = payload;
27
28
  }
28
29
  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);
30
+ (0, common_1.verifyRequestSignature)(opts, request.headers, request.body);
39
31
  }
40
32
  }
41
33
  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;
34
+ sendMiddlewareError(reply, err);
50
35
  }
51
36
  });
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
- }
37
+ }
38
+ function registerDecryption(fastify, opts, routes) {
39
+ fastify.addHook("preHandler", async (request, reply) => {
40
+ if (!(0, common_1.matchRoute)(request.url, routes))
41
+ return;
42
+ if (!opts.key) {
43
+ reply.code(500).send({
44
+ error: "key is required for decrypt-request operation",
45
+ code: "MISSING_CONFIG",
46
+ });
47
+ return;
48
+ }
49
+ try {
50
+ const body = request.body;
51
+ if (body && typeof body === "object" && "encrypted" in body) {
52
+ request.body = (0, common_1.decryptPayload)(opts.key, body.encrypted);
69
53
  }
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;
54
+ }
55
+ catch (err) {
56
+ sendMiddlewareError(reply, err);
57
+ }
58
+ });
59
+ }
60
+ function registerEncryption(fastify, opts, routes) {
61
+ fastify.addHook("preSerialization", async (request, _reply, payload) => {
62
+ if (!(0, common_1.matchRoute)(request.url, routes))
63
+ return payload;
64
+ if (!opts.key)
65
+ return payload;
66
+ if (payload !== null && typeof payload === "object") {
67
+ const sealed = (0, common_1.encryptPayload)(opts.key, payload);
68
+ return { encrypted: sealed };
69
+ }
70
+ return payload;
71
+ });
72
+ }
73
+ function registerPqDecryption(fastify, opts, routes) {
74
+ fastify.addHook("preHandler", async (request, reply) => {
75
+ if (!(0, common_1.matchRoute)(request.url, routes))
76
+ return;
77
+ const xSecret = opts.pqKeys?.recipientX25519Secret;
78
+ const kemSecret = opts.pqKeys?.recipientMlKemSecret;
79
+ if (!xSecret || !kemSecret) {
80
+ reply.code(500).send({
81
+ error: "recipientX25519Secret and recipientMlKemSecret are required for pq-decrypt-request operation",
82
+ code: "MISSING_CONFIG",
83
+ });
84
+ return;
85
+ }
86
+ try {
87
+ const body = request.body;
88
+ if (body && typeof body === "object" && "encrypted" in body) {
89
+ request.body =
90
+ (0, common_1.decryptPqPayload)(xSecret, kemSecret, body.encrypted, opts.chunkSize);
79
91
  }
80
- });
92
+ }
93
+ catch (err) {
94
+ sendMiddlewareError(reply, err);
95
+ }
96
+ });
97
+ }
98
+ function registerPqEncryption(fastify, opts, routes) {
99
+ fastify.addHook("preSerialization", async (request, _reply, payload) => {
100
+ if (!(0, common_1.matchRoute)(request.url, routes))
101
+ return payload;
102
+ const xPublic = opts.pqKeys?.recipientX25519Public;
103
+ const kemPublic = opts.pqKeys?.recipientMlKemPublic;
104
+ if (!xPublic || !kemPublic)
105
+ return payload;
106
+ if (payload !== null && typeof payload === "object") {
107
+ const sealed = (0, common_1.encryptPqPayload)(xPublic, kemPublic, payload, opts.chunkSize);
108
+ return {
109
+ encrypted: sealed,
110
+ algorithm: "X25519-ML-KEM-768-XChaCha20-Poly1305",
111
+ };
112
+ }
113
+ return payload;
114
+ });
115
+ }
116
+ async function cryptoPluginImpl(fastify, opts) {
117
+ const operations = opts.operations ?? [];
118
+ const routes = opts.routes ?? [];
119
+ registerVerification(fastify, opts, operations, routes);
120
+ if (operations.includes("decrypt-request")) {
121
+ registerDecryption(fastify, opts, routes);
122
+ }
123
+ if (operations.includes("pq-decrypt-request")) {
124
+ registerPqDecryption(fastify, opts, routes);
81
125
  }
82
126
  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
- });
127
+ registerEncryption(fastify, opts, routes);
128
+ }
129
+ if (operations.includes("pq-encrypt-response")) {
130
+ registerPqEncryption(fastify, opts, routes);
94
131
  }
95
132
  }
96
133
  exports.cryptoPlugin = (0, fastify_plugin_1.default)(cryptoPluginImpl, {
97
134
  name: "crypto-middleware",
98
- fastify: "4.x",
135
+ fastify: "4.x || 5.x",
136
+ });
137
+ async function pqStreamPluginImpl(fastify, opts) {
138
+ const routes = opts.routes ?? [];
139
+ const { recipientKeys, chunkSize } = opts;
140
+ const config = {
141
+ pqKeys: recipientKeys,
142
+ ...(chunkSize !== undefined ? { chunkSize } : {}),
143
+ };
144
+ if (recipientKeys.recipientX25519Secret &&
145
+ recipientKeys.recipientMlKemSecret) {
146
+ registerPqDecryption(fastify, config, routes);
147
+ }
148
+ if (recipientKeys.recipientX25519Public &&
149
+ recipientKeys.recipientMlKemPublic) {
150
+ registerPqEncryption(fastify, config, routes);
151
+ }
152
+ }
153
+ exports.pqStreamPlugin = (0, fastify_plugin_1.default)(pqStreamPluginImpl, {
154
+ name: "crypto-middleware-pq-stream",
155
+ fastify: "4.x || 5.x",
99
156
  });
100
157
  //# sourceMappingURL=fastify.js.map
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export type { MiddlewareConfig, JwtPayload } from "./types";
1
+ export type { MiddlewareConfig, JwtPayload, PqKeysConfig, PqStreamPluginConfig, } from "./types";
2
2
  export { CryptoMiddlewareError } from "./types";
3
- export { encryptPayload, decryptPayload, verifyHmacSignature, verifyJwt, matchRoute, } from "./common";
4
- export { createCryptoMiddleware } from "./express";
5
- export { cryptoPlugin } from "./fastify";
3
+ export type { JwtVerifyOptions } from "./common";
4
+ export { encryptPayload, decryptPayload, encryptPqPayload, decryptPqPayload, verifyHmacSignature, verifyJwt, matchRoute, } from "./common";
5
+ export { createCryptoMiddleware, createPqStreamMiddleware } from "./express";
6
+ export { cryptoPlugin, pqStreamPlugin } from "./fastify";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,YAAY,EACV,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,oBAAoB,GACrB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EACL,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,UAAU,GACX,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAG7E,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,16 +1,20 @@
1
1
  "use strict";
2
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;
3
+ exports.pqStreamPlugin = exports.cryptoPlugin = exports.createPqStreamMiddleware = exports.createCryptoMiddleware = exports.matchRoute = exports.verifyJwt = exports.verifyHmacSignature = exports.decryptPqPayload = exports.encryptPqPayload = exports.decryptPayload = exports.encryptPayload = exports.CryptoMiddlewareError = void 0;
4
4
  var types_1 = require("./types");
5
5
  Object.defineProperty(exports, "CryptoMiddlewareError", { enumerable: true, get: function () { return types_1.CryptoMiddlewareError; } });
6
6
  var common_1 = require("./common");
7
7
  Object.defineProperty(exports, "encryptPayload", { enumerable: true, get: function () { return common_1.encryptPayload; } });
8
8
  Object.defineProperty(exports, "decryptPayload", { enumerable: true, get: function () { return common_1.decryptPayload; } });
9
+ Object.defineProperty(exports, "encryptPqPayload", { enumerable: true, get: function () { return common_1.encryptPqPayload; } });
10
+ Object.defineProperty(exports, "decryptPqPayload", { enumerable: true, get: function () { return common_1.decryptPqPayload; } });
9
11
  Object.defineProperty(exports, "verifyHmacSignature", { enumerable: true, get: function () { return common_1.verifyHmacSignature; } });
10
12
  Object.defineProperty(exports, "verifyJwt", { enumerable: true, get: function () { return common_1.verifyJwt; } });
11
13
  Object.defineProperty(exports, "matchRoute", { enumerable: true, get: function () { return common_1.matchRoute; } });
12
14
  var express_1 = require("./express");
13
15
  Object.defineProperty(exports, "createCryptoMiddleware", { enumerable: true, get: function () { return express_1.createCryptoMiddleware; } });
16
+ Object.defineProperty(exports, "createPqStreamMiddleware", { enumerable: true, get: function () { return express_1.createPqStreamMiddleware; } });
14
17
  var fastify_1 = require("./fastify");
15
18
  Object.defineProperty(exports, "cryptoPlugin", { enumerable: true, get: function () { return fastify_1.cryptoPlugin; } });
19
+ Object.defineProperty(exports, "pqStreamPlugin", { enumerable: true, get: function () { return fastify_1.pqStreamPlugin; } });
16
20
  //# sourceMappingURL=index.js.map
package/dist/types.d.ts CHANGED
@@ -1,9 +1,24 @@
1
+ export interface PqKeysConfig {
2
+ recipientX25519Secret?: string | undefined;
3
+ recipientMlKemSecret?: string | undefined;
4
+ recipientX25519Public?: string | undefined;
5
+ recipientMlKemPublic?: string | undefined;
6
+ }
7
+ export interface PqStreamPluginConfig {
8
+ recipientKeys: PqKeysConfig;
9
+ routes?: string[] | undefined;
10
+ chunkSize?: number | undefined;
11
+ }
1
12
  export interface MiddlewareConfig {
2
- key?: string;
3
- routes?: string[];
4
- operations?: Array<"decrypt-request" | "encrypt-response" | "verify-signature" | "verify-jwt">;
13
+ key?: string | undefined;
14
+ routes?: string[] | undefined;
15
+ operations?: Array<"decrypt-request" | "encrypt-response" | "verify-signature" | "verify-jwt" | "pq-decrypt-request" | "pq-encrypt-response">;
5
16
  hmacKey?: string;
6
17
  jwtSecret?: string;
18
+ jwtIssuer?: string;
19
+ jwtAudience?: string;
20
+ pqKeys?: PqKeysConfig | undefined;
21
+ chunkSize?: number | undefined;
7
22
  }
8
23
  export interface JwtPayload {
9
24
  sub?: string;
@@ -1 +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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,YAAY;IAE3B,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE3C,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE1C,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE3C,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAKD,MAAM,WAAW,oBAAoB;IAEnC,aAAa,EAAE,YAAY,CAAC;IAE5B,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAE9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAE/B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzB,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAE9B,UAAU,CAAC,EAAE,KAAK,CACd,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,YAAY,GACZ,oBAAoB,GACpB,qBAAqB,CACxB,CAAC;IAEF,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAElC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;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;IAKxB,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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sebastienrousseau/crypto-middleware",
3
- "version": "0.0.8",
3
+ "version": "0.0.24",
4
4
  "description": "Plug-and-play cryptographic middleware for Express and Fastify -- auto-decrypt requests, verify signatures, and encrypt responses.",
5
5
  "author": "Sebastien Rousseau <sebastienrousseau@users.noreply.github.com>",
6
6
  "license": "MIT OR Apache-2.0",
@@ -16,28 +16,30 @@
16
16
  "engines": {
17
17
  "node": ">=22.0.0"
18
18
  },
19
+ "type": "commonjs",
19
20
  "main": "./dist/index.js",
20
21
  "types": "./dist/index.d.ts",
21
- "sideEffects": false,
22
22
  "exports": {
23
23
  ".": {
24
24
  "types": "./dist/index.d.ts",
25
25
  "require": "./dist/index.js",
26
- "import": "./dist/index.js"
27
- }
26
+ "default": "./dist/index.js"
27
+ },
28
+ "./package.json": "./package.json"
28
29
  },
30
+ "sideEffects": false,
29
31
  "files": [
30
32
  "dist/**/*.js",
31
33
  "dist/**/*.d.ts",
32
34
  "dist/**/*.d.ts.map"
33
35
  ],
34
36
  "dependencies": {
35
- "@sebastienrousseau/crypto-lib": "0.0.8"
37
+ "fastify-plugin": "^6.0.0",
38
+ "@sebastienrousseau/crypto-lib": "0.0.24"
36
39
  },
37
40
  "peerDependencies": {
38
41
  "express": "^5.2.1",
39
- "fastify": "^4.0.0",
40
- "fastify-plugin": "^4.0.0"
42
+ "fastify": "^4.0.0 || ^5.0.0"
41
43
  },
42
44
  "peerDependenciesMeta": {
43
45
  "express": {
@@ -45,25 +47,21 @@
45
47
  },
46
48
  "fastify": {
47
49
  "optional": true
48
- },
49
- "fastify-plugin": {
50
- "optional": true
51
50
  }
52
51
  },
53
52
  "devDependencies": {
54
- "@sebastienrousseau/mocha-config": "^0.0.5",
55
- "@types/chai": "^4.3.7",
53
+ "@sebastienrousseau/mocha-config": "^0.0.7",
54
+ "@types/chai": "^5.2.3",
56
55
  "@types/chai-as-promised": "^8.0.2",
57
56
  "@types/express": "^5.0.6",
58
- "@types/mocha": "^10.0.2",
57
+ "@types/mocha": "^10.0.10",
59
58
  "@types/node": "^26.6.3",
60
59
  "c8": "^12.0.0",
61
- "chai": "^4.5.0",
62
- "chai-as-promised": "^7.1.2",
60
+ "chai": "^6.3.0",
61
+ "chai-as-promised": "^8.0.2",
63
62
  "express": "^5.2.1",
64
63
  "fastify": "^5.12.5",
65
- "fastify-plugin": "^6.0.0",
66
- "mocha": "^10.8.2",
64
+ "mocha": "^12.0.3",
67
65
  "rimraf": "^6.1.3",
68
66
  "ts-node": "^10.9.2",
69
67
  "typedoc": "^0.28.20",
@@ -88,8 +86,8 @@
88
86
  "clean": "rimraf ./coverage ./dist ./docs",
89
87
  "test": "c8 --check-coverage --lines 100 --branches 100 --functions 100 --reporter=lcov --reporter=text mocha --config=.mocharc.cjs",
90
88
  "docs": "typedoc",
91
- "lint": "eslint --ext .ts src __tests__",
92
- "lint:fix": "eslint --cache --fix --ext .ts src __tests__",
89
+ "lint": "eslint src __tests__",
90
+ "lint:fix": "eslint --cache --fix src __tests__",
93
91
  "format": "prettier --write src/**/*.ts",
94
92
  "format:check": "prettier --check \"src/**/*.ts\""
95
93
  }