@gr4vy/sdk 1.10.18 → 2.0.0
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/jsr.json +1 -1
- package/lib/config.d.ts +3 -3
- package/lib/config.js +3 -3
- package/lib/config.js.map +1 -1
- package/lib/helpers.d.ts +22 -5
- package/lib/helpers.d.ts.map +1 -1
- package/lib/helpers.js +111 -22
- package/lib/helpers.js.map +1 -1
- package/package.json +1 -4
- package/src/lib/config.ts +3 -3
- package/src/lib/helpers.ts +135 -25
package/jsr.json
CHANGED
package/lib/config.d.ts
CHANGED
|
@@ -44,8 +44,8 @@ export declare function serverURLFromOptions(options: SDKOptions): URL | null;
|
|
|
44
44
|
export declare const SDK_METADATA: {
|
|
45
45
|
readonly language: "typescript";
|
|
46
46
|
readonly openapiDocVersion: "1.0.0";
|
|
47
|
-
readonly sdkVersion: "
|
|
48
|
-
readonly genVersion: "2.
|
|
49
|
-
readonly userAgent: "speakeasy-sdk/typescript
|
|
47
|
+
readonly sdkVersion: "2.0.0";
|
|
48
|
+
readonly genVersion: "2.858.2";
|
|
49
|
+
readonly userAgent: "speakeasy-sdk/typescript 2.0.0 2.858.2 1.0.0 @gr4vy/sdk";
|
|
50
50
|
};
|
|
51
51
|
//# sourceMappingURL=config.d.ts.map
|
package/lib/config.js
CHANGED
|
@@ -37,8 +37,8 @@ function serverURLFromOptions(options) {
|
|
|
37
37
|
exports.SDK_METADATA = {
|
|
38
38
|
language: "typescript",
|
|
39
39
|
openapiDocVersion: "1.0.0",
|
|
40
|
-
sdkVersion: "
|
|
41
|
-
genVersion: "2.
|
|
42
|
-
userAgent: "speakeasy-sdk/typescript
|
|
40
|
+
sdkVersion: "2.0.0",
|
|
41
|
+
genVersion: "2.858.2",
|
|
42
|
+
userAgent: "speakeasy-sdk/typescript 2.0.0 2.858.2 1.0.0 @gr4vy/sdk",
|
|
43
43
|
};
|
|
44
44
|
//# sourceMappingURL=config.js.map
|
package/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/lib/config.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAkDH,oDAsBC;AAnED,qCAA8C;AAEjC,QAAA,aAAa,GAAG,SAAS,CAAC;AAC1B,QAAA,gBAAgB,GAAG,YAAY,CAAC;AAC7C;;GAEG;AACU,QAAA,UAAU,GAAG;IACxB,CAAC,qBAAa,CAAC,EAAE,oCAAoC;IACrD,CAAC,wBAAgB,CAAC,EAAE,4BAA4B;CACxC,CAAC;AAmCX,SAAgB,oBAAoB,CAAC,OAAmB;IACtD,IAAI,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAElC,MAAM,YAAY,GAA2B;QAC3C,SAAS,EAAE;YACT,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,SAAS;SAC9B;QACD,YAAY,EAAE;YACZ,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,SAAS;SAC9B;KACF,CAAC;IAEF,IAAI,MAAM,GAAW,EAAE,CAAC;IAExB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,qBAAa,CAAC;QAC/C,SAAS,GAAG,kBAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,CAAC,GAAG,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAEY,QAAA,YAAY,GAAG;IAC1B,QAAQ,EAAE,YAAY;IACtB,iBAAiB,EAAE,OAAO;IAC1B,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/lib/config.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAkDH,oDAsBC;AAnED,qCAA8C;AAEjC,QAAA,aAAa,GAAG,SAAS,CAAC;AAC1B,QAAA,gBAAgB,GAAG,YAAY,CAAC;AAC7C;;GAEG;AACU,QAAA,UAAU,GAAG;IACxB,CAAC,qBAAa,CAAC,EAAE,oCAAoC;IACrD,CAAC,wBAAgB,CAAC,EAAE,4BAA4B;CACxC,CAAC;AAmCX,SAAgB,oBAAoB,CAAC,OAAmB;IACtD,IAAI,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAElC,MAAM,YAAY,GAA2B;QAC3C,SAAS,EAAE;YACT,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,SAAS;SAC9B;QACD,YAAY,EAAE;YACZ,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,SAAS;SAC9B;KACF,CAAC;IAEF,IAAI,MAAM,GAAW,EAAE,CAAC;IAExB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,qBAAa,CAAC;QAC/C,SAAS,GAAG,kBAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,CAAC,GAAG,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAEY,QAAA,YAAY,GAAG;IAC1B,QAAQ,EAAE,YAAY;IACtB,iBAAiB,EAAE,OAAO;IAC1B,UAAU,EAAE,OAAO;IACnB,UAAU,EAAE,SAAS;IACrB,SAAS,EAAE,yDAAyD;CAC5D,CAAC"}
|
package/lib/helpers.d.ts
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Best-effort runtime identification used for SDK metadata/user-agent strings.
|
|
3
|
+
*
|
|
4
|
+
* The function prefers browser-style detection via `navigator.userAgent` and
|
|
5
|
+
* falls back to Node.js `process.version` when available.
|
|
6
|
+
*
|
|
7
|
+
* @returns A runtime identifier string, or `"<unknown-runtime>"` when not detectable.
|
|
3
8
|
*/
|
|
4
9
|
export declare function getRuntime(): string;
|
|
5
10
|
/**
|
|
6
|
-
*
|
|
11
|
+
* Derives JWT `kid` from a private key using an RFC 7638 JWK thumbprint.
|
|
12
|
+
*
|
|
13
|
+
* Expected key format:
|
|
14
|
+
* - PKCS#8 PEM-encoded private key
|
|
15
|
+
* - EC P-521 curve (matches ES512 signing)
|
|
16
|
+
*
|
|
17
|
+
* Steps:
|
|
18
|
+
* 1. Decode PEM to PKCS#8 DER bytes.
|
|
19
|
+
* 2. Import key through Web Crypto.
|
|
20
|
+
* 3. Export as JWK and validate required fields.
|
|
21
|
+
* 4. Hash the canonical RFC 7638 thumbprint input with SHA-256.
|
|
22
|
+
* 5. Return base64url encoded digest.
|
|
23
|
+
*
|
|
24
|
+
* @param privateKey PEM-encoded PKCS#8 EC private key.
|
|
25
|
+
* @returns The base64url-encoded JWK thumbprint used as JWT `kid`.
|
|
26
|
+
* @throws If key parsing/import/export/validation/digest fails.
|
|
7
27
|
*/
|
|
8
28
|
export declare function getKeyId(privateKey: string): Promise<string>;
|
|
9
|
-
export declare function stripUndefined<T extends {}>(obj: T): {
|
|
10
|
-
[K in keyof T]?: Exclude<T[K], undefined>;
|
|
11
|
-
};
|
|
12
29
|
//# sourceMappingURL=helpers.d.ts.map
|
package/lib/helpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/lib/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/lib/helpers.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,wBAAgB,UAAU,WAsBzB;AAyDD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkElE"}
|
package/lib/helpers.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.getRuntime = getRuntime;
|
|
7
4
|
exports.getKeyId = getKeyId;
|
|
8
|
-
|
|
9
|
-
const keyto_1 = __importDefault(require("@trust/keyto"));
|
|
10
|
-
const jwk_thumbprint_1 = require("jwk-thumbprint");
|
|
5
|
+
const base64_1 = require("./base64");
|
|
11
6
|
/**
|
|
12
|
-
*
|
|
7
|
+
* Best-effort runtime identification used for SDK metadata/user-agent strings.
|
|
8
|
+
*
|
|
9
|
+
* The function prefers browser-style detection via `navigator.userAgent` and
|
|
10
|
+
* falls back to Node.js `process.version` when available.
|
|
11
|
+
*
|
|
12
|
+
* @returns A runtime identifier string, or `"<unknown-runtime>"` when not detectable.
|
|
13
13
|
*/
|
|
14
14
|
function getRuntime() {
|
|
15
15
|
if (typeof navigator !== "undefined" &&
|
|
@@ -28,26 +28,115 @@ function getRuntime() {
|
|
|
28
28
|
}
|
|
29
29
|
return "<unknown-runtime>";
|
|
30
30
|
}
|
|
31
|
+
let cachedWebCrypto;
|
|
31
32
|
/**
|
|
32
|
-
*
|
|
33
|
+
* Resolves a Web Crypto implementation across supported runtimes.
|
|
34
|
+
*
|
|
35
|
+
* Resolution order:
|
|
36
|
+
* 1. `globalThis.crypto` when already exposed by the runtime.
|
|
37
|
+
* 2. Node.js fallback via `node:crypto`.webcrypto (important for some Node 18 setups).
|
|
38
|
+
*
|
|
39
|
+
* @returns A Web Crypto compatible `Crypto` object with `subtle` APIs.
|
|
40
|
+
* @throws If no Web Crypto implementation is available.
|
|
33
41
|
*/
|
|
34
|
-
async function
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
async function resolveWebCrypto() {
|
|
43
|
+
// Browsers, Bun, Deno, and many Node setups expose crypto globally.
|
|
44
|
+
if (globalThis.crypto?.subtle != null) {
|
|
45
|
+
return globalThis.crypto;
|
|
46
|
+
}
|
|
47
|
+
// Reuse the resolved Node fallback to avoid repeated dynamic imports.
|
|
48
|
+
if (cachedWebCrypto != null) {
|
|
49
|
+
return cachedWebCrypto;
|
|
39
50
|
}
|
|
40
|
-
|
|
51
|
+
const gt = globalThis;
|
|
52
|
+
const isNodeRuntime = typeof gt === "object" &&
|
|
53
|
+
gt != null &&
|
|
54
|
+
"process" in gt &&
|
|
55
|
+
typeof gt.process === "object" &&
|
|
56
|
+
gt.process != null &&
|
|
57
|
+
"versions" in gt.process &&
|
|
58
|
+
typeof gt.process.versions === "object" &&
|
|
59
|
+
gt.process.versions != null &&
|
|
60
|
+
"node" in gt.process.versions;
|
|
61
|
+
// Avoid attempting to resolve `node:crypto` in non-Node runtimes.
|
|
62
|
+
if (isNodeRuntime) {
|
|
63
|
+
try {
|
|
64
|
+
// Keep the specifier non-literal to avoid eager bundler resolution.
|
|
65
|
+
const nodeCryptoSpecifier = `node${":"}crypto`;
|
|
66
|
+
const nodeCrypto = await import(nodeCryptoSpecifier);
|
|
67
|
+
if (nodeCrypto.webcrypto?.subtle != null) {
|
|
68
|
+
cachedWebCrypto = nodeCrypto.webcrypto;
|
|
69
|
+
return cachedWebCrypto;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Intentionally ignored. We'll throw a descriptive error below.
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
throw new Error("Web Crypto API is unavailable. Expected globalThis.crypto.subtle or Node's crypto.webcrypto.");
|
|
41
77
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Derives JWT `kid` from a private key using an RFC 7638 JWK thumbprint.
|
|
80
|
+
*
|
|
81
|
+
* Expected key format:
|
|
82
|
+
* - PKCS#8 PEM-encoded private key
|
|
83
|
+
* - EC P-521 curve (matches ES512 signing)
|
|
84
|
+
*
|
|
85
|
+
* Steps:
|
|
86
|
+
* 1. Decode PEM to PKCS#8 DER bytes.
|
|
87
|
+
* 2. Import key through Web Crypto.
|
|
88
|
+
* 3. Export as JWK and validate required fields.
|
|
89
|
+
* 4. Hash the canonical RFC 7638 thumbprint input with SHA-256.
|
|
90
|
+
* 5. Return base64url encoded digest.
|
|
91
|
+
*
|
|
92
|
+
* @param privateKey PEM-encoded PKCS#8 EC private key.
|
|
93
|
+
* @returns The base64url-encoded JWK thumbprint used as JWT `kid`.
|
|
94
|
+
* @throws If key parsing/import/export/validation/digest fails.
|
|
95
|
+
*/
|
|
96
|
+
async function getKeyId(privateKey) {
|
|
97
|
+
try {
|
|
98
|
+
const runtimeCrypto = await resolveWebCrypto();
|
|
99
|
+
// Parse PEM to DER binary
|
|
100
|
+
const pemBody = privateKey
|
|
101
|
+
.replace(/-----BEGIN PRIVATE KEY-----/, "")
|
|
102
|
+
.replace(/-----END PRIVATE KEY-----/, "")
|
|
103
|
+
.replace(/\s/g, "");
|
|
104
|
+
const der = (0, base64_1.bytesFromBase64)(pemBody);
|
|
105
|
+
// Import as extractable CryptoKey (ES512 = P-521)
|
|
106
|
+
const key = await runtimeCrypto.subtle.importKey("pkcs8", der, { name: "ECDSA", namedCurve: "P-521" }, true, ["sign"]);
|
|
107
|
+
// Export as JWK and validate fields required to build an RFC 7638 thumbprint.
|
|
108
|
+
const jwk = await runtimeCrypto.subtle.exportKey("jwk", key);
|
|
109
|
+
const requiredFields = ["kty", "crv", "x", "y"];
|
|
110
|
+
const invalidFields = requiredFields.filter((field) => {
|
|
111
|
+
const value = jwk[field];
|
|
112
|
+
return typeof value !== "string" || value.length === 0;
|
|
113
|
+
});
|
|
114
|
+
if (invalidFields.length > 0) {
|
|
115
|
+
throw new Error(`Exported JWK is missing required string field(s): ${invalidFields.join(", ")}`);
|
|
116
|
+
}
|
|
117
|
+
if (jwk.kty !== "EC" || jwk.crv !== "P-521") {
|
|
118
|
+
throw new Error("Imported key is not an EC P-521 private key");
|
|
49
119
|
}
|
|
120
|
+
// RFC 7638 canonical member set for EC keys: crv, kty, x, y.
|
|
121
|
+
const input = JSON.stringify({
|
|
122
|
+
crv: jwk.crv,
|
|
123
|
+
kty: jwk.kty,
|
|
124
|
+
x: jwk.x,
|
|
125
|
+
y: jwk.y,
|
|
126
|
+
});
|
|
127
|
+
const hash = await runtimeCrypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
|
|
128
|
+
// Base64url encode
|
|
129
|
+
return btoa(String.fromCharCode(...new Uint8Array(hash)))
|
|
130
|
+
.replace(/\+/g, "-")
|
|
131
|
+
.replace(/\//g, "_")
|
|
132
|
+
.replace(/=+$/, "");
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
const reason = error instanceof Error && error.message
|
|
136
|
+
? ` Reason: ${error.message}`
|
|
137
|
+
: "";
|
|
138
|
+
throw new Error("Failed to derive JWT key ID from private key. Expected a PKCS#8 PEM-encoded EC private key on curve P-521 (ES512)." +
|
|
139
|
+
reason);
|
|
50
140
|
}
|
|
51
|
-
return newObj;
|
|
52
141
|
}
|
|
53
142
|
//# sourceMappingURL=helpers.js.map
|
package/lib/helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/lib/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/lib/helpers.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gr4vy/sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"author": "Gr4vy",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@eslint/js": "^9.26.0",
|
|
21
21
|
"@types/jsonwebtoken": "^9.0.10",
|
|
22
|
-
"@types/trust__keyto": "^1.0.4",
|
|
23
22
|
"@types/uuid": "^11.0.0",
|
|
24
23
|
"eslint": "^9.26.0",
|
|
25
24
|
"globals": "^15.14.0",
|
|
@@ -29,9 +28,7 @@
|
|
|
29
28
|
"vitest": "^4.0.3"
|
|
30
29
|
},
|
|
31
30
|
"dependencies": {
|
|
32
|
-
"@trust/keyto": "^1.0.1",
|
|
33
31
|
"jsonwebtoken": "^9.0.3",
|
|
34
|
-
"jwk-thumbprint": "^0.1.4",
|
|
35
32
|
"snakecase-keys": "^6.0.0",
|
|
36
33
|
"uuid": "^11.1.0",
|
|
37
34
|
"zod": "^3.25.0 || ^4.0.0"
|
package/src/lib/config.ts
CHANGED
|
@@ -77,7 +77,7 @@ export function serverURLFromOptions(options: SDKOptions): URL | null {
|
|
|
77
77
|
export const SDK_METADATA = {
|
|
78
78
|
language: "typescript",
|
|
79
79
|
openapiDocVersion: "1.0.0",
|
|
80
|
-
sdkVersion: "
|
|
81
|
-
genVersion: "2.
|
|
82
|
-
userAgent: "speakeasy-sdk/typescript
|
|
80
|
+
sdkVersion: "2.0.0",
|
|
81
|
+
genVersion: "2.858.2",
|
|
82
|
+
userAgent: "speakeasy-sdk/typescript 2.0.0 2.858.2 1.0.0 @gr4vy/sdk",
|
|
83
83
|
} as const;
|
package/src/lib/helpers.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { jwkThumbprintByEncoding } from "jwk-thumbprint";
|
|
1
|
+
import { bytesFromBase64 } from "./base64";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
|
-
*
|
|
4
|
+
* Best-effort runtime identification used for SDK metadata/user-agent strings.
|
|
5
|
+
*
|
|
6
|
+
* The function prefers browser-style detection via `navigator.userAgent` and
|
|
7
|
+
* falls back to Node.js `process.version` when available.
|
|
8
|
+
*
|
|
9
|
+
* @returns A runtime identifier string, or `"<unknown-runtime>"` when not detectable.
|
|
6
10
|
*/
|
|
7
11
|
export function getRuntime() {
|
|
8
12
|
if (
|
|
@@ -28,37 +32,143 @@ export function getRuntime() {
|
|
|
28
32
|
return "<unknown-runtime>";
|
|
29
33
|
}
|
|
30
34
|
|
|
35
|
+
let cachedWebCrypto: Crypto | undefined;
|
|
36
|
+
|
|
31
37
|
/**
|
|
32
|
-
*
|
|
38
|
+
* Resolves a Web Crypto implementation across supported runtimes.
|
|
39
|
+
*
|
|
40
|
+
* Resolution order:
|
|
41
|
+
* 1. `globalThis.crypto` when already exposed by the runtime.
|
|
42
|
+
* 2. Node.js fallback via `node:crypto`.webcrypto (important for some Node 18 setups).
|
|
43
|
+
*
|
|
44
|
+
* @returns A Web Crypto compatible `Crypto` object with `subtle` APIs.
|
|
45
|
+
* @throws If no Web Crypto implementation is available.
|
|
33
46
|
*/
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
async function resolveWebCrypto(): Promise<Crypto> {
|
|
48
|
+
// Browsers, Bun, Deno, and many Node setups expose crypto globally.
|
|
49
|
+
if (globalThis.crypto?.subtle != null) {
|
|
50
|
+
return globalThis.crypto;
|
|
51
|
+
}
|
|
36
52
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
// Reuse the resolved Node fallback to avoid repeated dynamic imports.
|
|
54
|
+
if (cachedWebCrypto != null) {
|
|
55
|
+
return cachedWebCrypto;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const gt: unknown = globalThis;
|
|
59
|
+
const isNodeRuntime =
|
|
60
|
+
typeof gt === "object" &&
|
|
61
|
+
gt != null &&
|
|
62
|
+
"process" in gt &&
|
|
63
|
+
typeof gt.process === "object" &&
|
|
64
|
+
gt.process != null &&
|
|
65
|
+
"versions" in gt.process &&
|
|
66
|
+
typeof gt.process.versions === "object" &&
|
|
67
|
+
gt.process.versions != null &&
|
|
68
|
+
"node" in gt.process.versions;
|
|
69
|
+
|
|
70
|
+
// Avoid attempting to resolve `node:crypto` in non-Node runtimes.
|
|
71
|
+
if (isNodeRuntime) {
|
|
72
|
+
try {
|
|
73
|
+
// Keep the specifier non-literal to avoid eager bundler resolution.
|
|
74
|
+
const nodeCryptoSpecifier = `node${":"}crypto`;
|
|
75
|
+
const nodeCrypto = await import(nodeCryptoSpecifier);
|
|
76
|
+
if (nodeCrypto.webcrypto?.subtle != null) {
|
|
77
|
+
cachedWebCrypto = nodeCrypto.webcrypto as unknown as Crypto;
|
|
78
|
+
return cachedWebCrypto;
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
// Intentionally ignored. We'll throw a descriptive error below.
|
|
82
|
+
}
|
|
44
83
|
}
|
|
45
84
|
|
|
46
|
-
|
|
85
|
+
throw new Error(
|
|
86
|
+
"Web Crypto API is unavailable. Expected globalThis.crypto.subtle or Node's crypto.webcrypto."
|
|
87
|
+
);
|
|
47
88
|
}
|
|
48
89
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Derives JWT `kid` from a private key using an RFC 7638 JWK thumbprint.
|
|
92
|
+
*
|
|
93
|
+
* Expected key format:
|
|
94
|
+
* - PKCS#8 PEM-encoded private key
|
|
95
|
+
* - EC P-521 curve (matches ES512 signing)
|
|
96
|
+
*
|
|
97
|
+
* Steps:
|
|
98
|
+
* 1. Decode PEM to PKCS#8 DER bytes.
|
|
99
|
+
* 2. Import key through Web Crypto.
|
|
100
|
+
* 3. Export as JWK and validate required fields.
|
|
101
|
+
* 4. Hash the canonical RFC 7638 thumbprint input with SHA-256.
|
|
102
|
+
* 5. Return base64url encoded digest.
|
|
103
|
+
*
|
|
104
|
+
* @param privateKey PEM-encoded PKCS#8 EC private key.
|
|
105
|
+
* @returns The base64url-encoded JWK thumbprint used as JWT `kid`.
|
|
106
|
+
* @throws If key parsing/import/export/validation/digest fails.
|
|
107
|
+
*/
|
|
108
|
+
export async function getKeyId(privateKey: string): Promise<string> {
|
|
109
|
+
try {
|
|
110
|
+
const runtimeCrypto = await resolveWebCrypto();
|
|
111
|
+
|
|
112
|
+
// Parse PEM to DER binary
|
|
113
|
+
const pemBody = privateKey
|
|
114
|
+
.replace(/-----BEGIN PRIVATE KEY-----/, "")
|
|
115
|
+
.replace(/-----END PRIVATE KEY-----/, "")
|
|
116
|
+
.replace(/\s/g, "");
|
|
117
|
+
const der = bytesFromBase64(pemBody);
|
|
54
118
|
|
|
55
|
-
|
|
56
|
-
const
|
|
119
|
+
// Import as extractable CryptoKey (ES512 = P-521)
|
|
120
|
+
const key = await runtimeCrypto.subtle.importKey(
|
|
121
|
+
"pkcs8",
|
|
122
|
+
der,
|
|
123
|
+
{ name: "ECDSA", namedCurve: "P-521" },
|
|
124
|
+
true,
|
|
125
|
+
["sign"]
|
|
126
|
+
);
|
|
57
127
|
|
|
58
|
-
|
|
59
|
-
|
|
128
|
+
// Export as JWK and validate fields required to build an RFC 7638 thumbprint.
|
|
129
|
+
const jwk = await runtimeCrypto.subtle.exportKey("jwk", key);
|
|
130
|
+
const requiredFields = ["kty", "crv", "x", "y"] as const;
|
|
131
|
+
const invalidFields = requiredFields.filter((field) => {
|
|
132
|
+
const value = jwk[field];
|
|
133
|
+
return typeof value !== "string" || value.length === 0;
|
|
134
|
+
});
|
|
135
|
+
if (invalidFields.length > 0) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`Exported JWK is missing required string field(s): ${invalidFields.join(
|
|
138
|
+
", "
|
|
139
|
+
)}`
|
|
140
|
+
);
|
|
60
141
|
}
|
|
61
|
-
}
|
|
62
142
|
|
|
63
|
-
|
|
143
|
+
if (jwk.kty !== "EC" || jwk.crv !== "P-521") {
|
|
144
|
+
throw new Error("Imported key is not an EC P-521 private key");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// RFC 7638 canonical member set for EC keys: crv, kty, x, y.
|
|
148
|
+
const input = JSON.stringify({
|
|
149
|
+
crv: jwk.crv,
|
|
150
|
+
kty: jwk.kty,
|
|
151
|
+
x: jwk.x,
|
|
152
|
+
y: jwk.y,
|
|
153
|
+
});
|
|
154
|
+
const hash = await runtimeCrypto.subtle.digest(
|
|
155
|
+
"SHA-256",
|
|
156
|
+
new TextEncoder().encode(input)
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Base64url encode
|
|
160
|
+
return btoa(String.fromCharCode(...new Uint8Array(hash)))
|
|
161
|
+
.replace(/\+/g, "-")
|
|
162
|
+
.replace(/\//g, "_")
|
|
163
|
+
.replace(/=+$/, "");
|
|
164
|
+
} catch (error) {
|
|
165
|
+
const reason =
|
|
166
|
+
error instanceof Error && error.message
|
|
167
|
+
? ` Reason: ${error.message}`
|
|
168
|
+
: "";
|
|
169
|
+
throw new Error(
|
|
170
|
+
"Failed to derive JWT key ID from private key. Expected a PKCS#8 PEM-encoded EC private key on curve P-521 (ES512)." +
|
|
171
|
+
reason
|
|
172
|
+
);
|
|
173
|
+
}
|
|
64
174
|
}
|