@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 +16 -7
- package/dist/common.d.ts +10 -2
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js +107 -30
- package/dist/express.d.ts +2 -1
- package/dist/express.d.ts.map +1 -1
- package/dist/express.js +82 -41
- package/dist/fastify.d.ts +3 -1
- package/dist/fastify.d.ts.map +1 -1
- package/dist/fastify.js +126 -69
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/types.d.ts +18 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +17 -19
package/README.md
CHANGED
|
@@ -142,16 +142,23 @@ lets you scope protection to specific endpoints.
|
|
|
142
142
|
|
|
143
143
|
### Configuration
|
|
144
144
|
|
|
145
|
-
| Option
|
|
146
|
-
|
|
|
147
|
-
| `key`
|
|
148
|
-
| `routes`
|
|
149
|
-
| `operations`
|
|
150
|
-
| `hmacKey`
|
|
151
|
-
| `jwtSecret`
|
|
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
|
|
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
|
package/dist/common.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"
|
|
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
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
86
|
+
reject("Malformed JWT: expected 3 parts", "MALFORMED_TOKEN");
|
|
52
87
|
}
|
|
53
|
-
|
|
54
|
-
|
|
88
|
+
return parts;
|
|
89
|
+
}
|
|
90
|
+
function decodeObject(segment, name) {
|
|
91
|
+
let value;
|
|
55
92
|
try {
|
|
56
|
-
|
|
93
|
+
value = JSON.parse(base64urlDecode(segment));
|
|
57
94
|
}
|
|
58
95
|
catch {
|
|
59
|
-
|
|
96
|
+
value = undefined;
|
|
60
97
|
}
|
|
61
|
-
if (
|
|
62
|
-
|
|
98
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
99
|
+
reject(`Malformed JWT ${name}`, "MALFORMED_TOKEN");
|
|
63
100
|
}
|
|
64
|
-
|
|
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
|
|
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
|
-
|
|
114
|
+
reject("Invalid JWT signature", "INVALID_TOKEN");
|
|
77
115
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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 (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
package/dist/express.d.ts.map
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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
|
package/dist/fastify.d.ts.map
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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 {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,YAAY,
|
|
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;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
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.
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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.
|
|
55
|
-
"@types/chai": "^
|
|
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.
|
|
57
|
+
"@types/mocha": "^10.0.10",
|
|
59
58
|
"@types/node": "^26.6.3",
|
|
60
59
|
"c8": "^12.0.0",
|
|
61
|
-
"chai": "^
|
|
62
|
-
"chai-as-promised": "^
|
|
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
|
-
"
|
|
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
|
|
92
|
-
"lint:fix": "eslint --cache --fix
|
|
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
|
}
|