@pulse-compute/jwt 1.0.0-beta.4 → 1.0.0-beta.6
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 +78 -9
- package/as/index.as.ts +7 -2
- package/as/sign.as.ts +189 -0
- package/dist/crypto-verifier.d.ts.map +1 -1
- package/dist/crypto-verifier.js +8 -5
- package/dist/crypto-verifier.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/package-runtime.d.ts +5 -0
- package/dist/internal/package-runtime.d.ts.map +1 -1
- package/dist/internal/package-runtime.js +1 -0
- package/dist/internal/package-runtime.js.map +1 -1
- package/dist/options.d.ts +1 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +16 -8
- package/dist/options.js.map +1 -1
- package/dist/provider.d.ts +1 -0
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +1 -0
- package/dist/provider.js.map +1 -1
- package/dist/sign.d.ts +27 -0
- package/dist/sign.d.ts.map +1 -0
- package/dist/sign.js +219 -0
- package/dist/sign.js.map +1 -0
- package/dist/token.d.ts +1 -0
- package/dist/token.d.ts.map +1 -1
- package/dist/token.js +4 -0
- package/dist/token.js.map +1 -1
- package/package.json +5 -5
- package/pulse.package.json +11 -5
- package/pulsewasm.compiler.cjs +156 -15
- package/pulsewasm.manifest.cjs +7 -5
- package/pulsewasm.native.cjs +6 -3
package/README.md
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- pulse-package-status:start -->
|
|
4
4
|
> **Support tier:** Supported provider/extension surface<br>
|
|
5
|
-
> **Audience:** Applications verifying bounded
|
|
6
|
-
> **Install directly:** Yes, when an application verifies JWTs.<br>
|
|
5
|
+
> **Audience:** Applications verifying JWT credentials and issuing bounded HS256/ES256/RS256 worker tokens through Pulse providers.<br>
|
|
6
|
+
> **Install directly:** Yes, when an application verifies or signs JWTs.<br>
|
|
7
7
|
> **Supported entry points:** `@pulse-compute/jwt`<br>
|
|
8
|
-
> **Stability:** The package root
|
|
8
|
+
> **Stability:** The package root supports provider-neutral verification and bounded HS256/ES256/RS256 signing; provider and compiler integration subpaths are not application APIs.<br>
|
|
9
9
|
> **npm:** [`@pulse-compute/jwt`](https://www.npmjs.com/package/@pulse-compute/jwt)<br>
|
|
10
|
-
> **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.
|
|
10
|
+
> **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.6/packages/jwt/)
|
|
11
11
|
>
|
|
12
|
-
> This release-status block is generated from the synchronized `Pulse 1.0.0-beta.
|
|
12
|
+
> This release-status block is generated from the synchronized `Pulse 1.0.0-beta.6` package policy.
|
|
13
13
|
<!-- pulse-package-status:end -->
|
|
14
14
|
|
|
15
|
-
Bounded, provider-neutral JWT verification for Pulse handlers.
|
|
15
|
+
Bounded, provider-neutral JWT verification and HS256/ES256/RS256 signing for Pulse handlers.
|
|
16
16
|
|
|
17
17
|
This package and `@pulse-compute/crypto` are members of the synchronized
|
|
18
|
-
`1.0.0-beta.
|
|
18
|
+
`1.0.0-beta.6` release catalog.
|
|
19
19
|
|
|
20
20
|
Verification is implemented for HS256 in all four sealed target cells. G3 also
|
|
21
21
|
activates ES256 through the crypto-owned signature seam. H4 aligns Node and
|
|
@@ -41,7 +41,7 @@ const verified = await jwt.verify(
|
|
|
41
41
|
)
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
ES256 accepts only inline public P-256 JWKs or static JWKS values with at most
|
|
44
|
+
ES256 verification accepts only inline public P-256 JWKs or static JWKS values with at most
|
|
45
45
|
16 entries. Coordinates are canonical unpadded base64url encodings of exactly
|
|
46
46
|
32 bytes. Private and certificate members are rejected; `kid` selection is
|
|
47
47
|
deterministic; duplicate, missing, ambiguous, and unknown selections fail
|
|
@@ -53,9 +53,78 @@ claims, captures one wall-clock instant only after authenticity, evaluates
|
|
|
53
53
|
registered claims before an optional runtime schema, and returns a detached,
|
|
54
54
|
deeply frozen result. It does not authorize application or host behavior.
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
`jwt.sign(ctx, claims, { algorithm: 'HS256', key: { type: 'secret', binding: 'WORKER_KEY' }, expiresInSeconds: 45 })`
|
|
57
|
+
returns a compact JWT through a request-owned effect. Select `HMAC-SHA256` in
|
|
58
|
+
the crypto profile. The provider resolves a 32–4096 byte secret and captures
|
|
59
|
+
one trusted clock reading; the package supplies `iat` and `exp`. Lifetimes
|
|
60
|
+
are explicit positive safe integers in seconds, and expiration must fit the
|
|
61
|
+
supported Date range. Applications own lifetime policy. Claims are bounded ordinary JSON; caller-supplied `iat`,
|
|
62
|
+
`exp`, and `nbf` are rejected. See the package guide for exact limits and
|
|
63
|
+
Native authoring requirements. Four-target signing fixtures exercise Node and
|
|
64
|
+
Fastly Native/JavaScript; they are not deployed Fastly evidence.
|
|
65
|
+
|
|
66
|
+
EdDSA, remote key authority, custom crypto providers, and
|
|
57
67
|
automatic fallback remain unavailable. The shared G3 ES256 corpus and
|
|
58
68
|
package-to-crypto composition are recorded in
|
|
59
69
|
`wasm/.test-results/jwt-g3/jwt-g3-evidence.json`; the six-cell target matrix is
|
|
60
70
|
recorded in `wasm/.test-results/boundary-h4/es256-six-cell-matrix.json`. The
|
|
61
71
|
prior four-cell HS256 seal remains historical regression evidence.
|
|
72
|
+
|
|
73
|
+
ES256 issuance selects `ES256` in both signing options and the crypto profile.
|
|
74
|
+
The named secret contains a UTF-8 JSON private P-256 JWK (`kty`, `crv`, `x`,
|
|
75
|
+
`y`, `d`); the private scalar must match the public point. An optional `kid`
|
|
76
|
+
(up to 256 UTF-8 bytes) is copied into the protected header for key selection.
|
|
77
|
+
Private keys never belong in application options or static JWKS artifacts.
|
|
78
|
+
Native signing uses the revised, reproducibly built RustCrypto guest; JavaScript
|
|
79
|
+
uses Web Crypto. Historical verification seals do not validate the revised
|
|
80
|
+
binary. Current signing fixtures cover all four targets without claiming a
|
|
81
|
+
live deployment or a new aggregate release seal.
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
## RS256 issuance and verification
|
|
85
|
+
|
|
86
|
+
Select `RS256` in `pulse.crypto` and in `jwt.sign` options. The named secret
|
|
87
|
+
contains a UTF-8 JSON private RSA JWK with `kty: "RSA"`, `n`, `e`, `d`, `p`,
|
|
88
|
+
`q`, `dp`, `dq`, and `qi`. Its total encoded size is at most 4096 bytes.
|
|
89
|
+
Optional metadata is `alg: "RS256"`, `use: "sig"`, `key_ops: ["sign"]`,
|
|
90
|
+
boolean `ext`, and a `kid` of at most 256 UTF-8 bytes. If signing options and
|
|
91
|
+
the secret both carry `kid`, they must agree. Never put private JWKs into
|
|
92
|
+
application source or verification options.
|
|
93
|
+
|
|
94
|
+
Verification uses `algorithms: ['RS256']` with an inline public JWK or a
|
|
95
|
+
static JWKS of at most 16 entries. Public keys require only `kty`, `n`, and
|
|
96
|
+
`e`; optional `alg`, `use`, `key_ops: ['verify']`, and `kid` follow the same
|
|
97
|
+
policy. Private, certificate, multi-prime (`oth`), and unknown fields are
|
|
98
|
+
rejected. Duplicate `kid` values reject the set; selection is exact by `kid`
|
|
99
|
+
or requires one eligible key. Failure never retries another key.
|
|
100
|
+
|
|
101
|
+
Supported modulus sizes are exactly 2048, 3072, and 4096 bits, with an odd
|
|
102
|
+
public exponent from 3 through 4294967295. JWK integers use minimal unsigned,
|
|
103
|
+
canonical unpadded base64url. Private keys require two distinct, odd factors
|
|
104
|
+
of half the modulus width with their top bit set. Crypto checks `n = p*q`,
|
|
105
|
+
`d < n`, the two reduced exponents, their relation to `e`, and `q*qi mod p`.
|
|
106
|
+
These checks establish consistency; key generation and primality testing
|
|
107
|
+
remain outside this API.
|
|
108
|
+
|
|
109
|
+
RS256 means RSASSA-PKCS1-v1_5 with SHA-256. RSA-PSS is not accepted. Signatures
|
|
110
|
+
are exactly 256, 384, or 512 bytes, and original signing input is bounded to
|
|
111
|
+
12288 bytes. Issued claims retain the 8192-byte bound and application-owned
|
|
112
|
+
positive safe-integer lifetime. The provider owns secret lookup and clock
|
|
113
|
+
capture; authenticity precedes claim validation.
|
|
114
|
+
|
|
115
|
+
Node and Fastly JavaScript use Web Crypto. Both Native providers use the
|
|
116
|
+
pinned BearSSL 0.6 `i31` code in the shared signature guest. Each signer
|
|
117
|
+
verifies its output before returning it. JavaScript uses BigInt to check
|
|
118
|
+
redundant private key fields during import; that validation and the engine's
|
|
119
|
+
key handling have no Pulse constant-time guarantee. Native uses BearSSL's
|
|
120
|
+
constant-time arithmetic design; compiled Wasm timing still depends on the
|
|
121
|
+
engine and CPU. See the Crypto guide for the implementation assumptions.
|
|
122
|
+
|
|
123
|
+
Native RS256 and ES256 share one linked guest. The current fixed-memory
|
|
124
|
+
linker rejects composition with the allocating SHA-256/HMAC guest; use a
|
|
125
|
+
separate Native artifact or an explicitly selected JavaScript target for
|
|
126
|
+
that combination. Fastly Native also retains one verification algorithm per
|
|
127
|
+
artifact. Signing and verification with RS256 together, issuance alone,
|
|
128
|
+
verification alone, and RS256/ES256 issuance composition are tested through
|
|
129
|
+
the normal CLI build path. Injected Fastly hosts are portable evidence, not
|
|
130
|
+
a deployed-service confirmation or an aggregate release seal.
|
package/as/index.as.ts
CHANGED
|
@@ -292,7 +292,7 @@ export function pulse_jwt_fastly_verify(effectIndex: i32, outerHandle: i32): i32
|
|
|
292
292
|
const algorithmPolicy = __pulse_fastly_value(__pulse_jwt_object_field(policy, "algorithms"))
|
|
293
293
|
if (
|
|
294
294
|
algorithm === null ||
|
|
295
|
-
(algorithm != "HS256" && algorithm != "ES256") ||
|
|
295
|
+
(algorithm != "HS256" && algorithm != "ES256" && algorithm != "RS256") ||
|
|
296
296
|
!__pulse_jwt_array_contains(algorithmPolicy, algorithm)
|
|
297
297
|
) {
|
|
298
298
|
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_ALGORITHM_NOT_ALLOWED, 212)
|
|
@@ -333,7 +333,7 @@ export function pulse_jwt_fastly_verify(effectIndex: i32, outerHandle: i32): i32
|
|
|
333
333
|
} else {
|
|
334
334
|
const kid = __pulse_jwt_string_member(protectedHeader, "kid")
|
|
335
335
|
key = __pulse_fastly_jwt_resolve_es256_key(effectIndex, kid)
|
|
336
|
-
if (key === null || key.byteLength != __PULSE_JWT_ES256_PUBLIC_KEY_BYTES) {
|
|
336
|
+
if (key === null || (algorithm == "ES256" ? key.byteLength != __PULSE_JWT_ES256_PUBLIC_KEY_BYTES : key.byteLength < 8 || key.byteLength != 8 + signature.byteLength)) {
|
|
337
337
|
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_KEY_INVALID, 216)
|
|
338
338
|
}
|
|
339
339
|
}
|
|
@@ -386,3 +386,8 @@ export function pulse_jwt_fastly_verify(effectIndex: i32, outerHandle: i32): i32
|
|
|
386
386
|
__pulse_fastly_jwt_record_verified()
|
|
387
387
|
return output
|
|
388
388
|
}
|
|
389
|
+
|
|
390
|
+
export function pulse_jwt_sign(operationRef: i32, invocationRef: i32, resultRef: i32): i32 {
|
|
391
|
+
void operationRef; void invocationRef; void resultRef
|
|
392
|
+
return PULSE_JWT_VERIFY_CRYPTO_COMPOSITION_REQUIRED
|
|
393
|
+
}
|
package/as/sign.as.ts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// Package-owned HS256/ES256 issuance. Provider callbacks own secrets, clock and errors;
|
|
2
|
+
// the selected Crypto guest owns signing. No provider SDK or JavaScript fallback.
|
|
3
|
+
class __PulseJwtSignBudget { entries: i32 = 0; code: i32 = 0 }
|
|
4
|
+
|
|
5
|
+
function __pulse_jwt_sign_validate(handle: i32, depth: i32, budget: __PulseJwtSignBudget): bool {
|
|
6
|
+
if (++budget.entries > 1024 || depth > 32) { budget.code = __PULSE_JWT_ERROR_LIMIT_EXCEEDED; return false }
|
|
7
|
+
const value = __pulse_fastly_value(handle)
|
|
8
|
+
if (value.kind == PULSE_VALUE_NULL || value.kind == PULSE_VALUE_BOOLEAN) return true
|
|
9
|
+
if (value.kind == PULSE_VALUE_NUMBER && isFinite(value.number)) return true
|
|
10
|
+
if (value.kind == PULSE_VALUE_STRING) {
|
|
11
|
+
if (value.text.length > 8192) { budget.code = __PULSE_JWT_ERROR_LIMIT_EXCEEDED; return false }
|
|
12
|
+
__pulse_fastly_remember_secret(value.text)
|
|
13
|
+
return true
|
|
14
|
+
}
|
|
15
|
+
if (value.kind == PULSE_VALUE_ARRAY || value.kind == PULSE_VALUE_OBJECT) {
|
|
16
|
+
for (let i = 0; i < value.values.length; i++) {
|
|
17
|
+
if (value.kind == PULSE_VALUE_OBJECT && unchecked(value.keys[i]).length > 8192) {
|
|
18
|
+
budget.code = __PULSE_JWT_ERROR_LIMIT_EXCEEDED; return false
|
|
19
|
+
}
|
|
20
|
+
if (!__pulse_jwt_sign_validate(unchecked(value.values[i]), depth + 1, budget)) return false
|
|
21
|
+
}
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
24
|
+
budget.code = __PULSE_JWT_ERROR_CLAIMS_INVALID
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function __pulse_jwt_base64url_encode(bytes: Uint8Array): string {
|
|
29
|
+
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'
|
|
30
|
+
let output = ''
|
|
31
|
+
let accumulator: u32 = 0
|
|
32
|
+
let bits = 0
|
|
33
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
34
|
+
accumulator = (accumulator << 8) | unchecked(bytes[i]); bits += 8
|
|
35
|
+
while (bits >= 6) { bits -= 6; output += alphabet.charAt((accumulator >> bits) & 63) }
|
|
36
|
+
}
|
|
37
|
+
if (bits > 0) output += alphabet.charAt((accumulator << (6 - bits)) & 63)
|
|
38
|
+
return output
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function __pulse_jwt_sign_private_key(encoded: Uint8Array, policy: __PulseFastlyValue): Uint8Array | null {
|
|
42
|
+
const text = __pulse_jwt_decode_text(encoded)
|
|
43
|
+
const roundtrip = Uint8Array.wrap(String.UTF8.encode(text, false))
|
|
44
|
+
let valid = roundtrip.length == encoded.length
|
|
45
|
+
for (let i = 0; valid && i < encoded.length; i++) if (roundtrip[i] != encoded[i]) valid = false
|
|
46
|
+
__pulse_jwt_wipe(roundtrip)
|
|
47
|
+
if (!valid) return null
|
|
48
|
+
const parser = new __PulseJsonParser(text, true)
|
|
49
|
+
const handle = parser.parse()
|
|
50
|
+
if (parser.failed || handle <= 0) return null
|
|
51
|
+
const jwk = __pulse_fastly_value(handle)
|
|
52
|
+
if (jwk.kind != PULSE_VALUE_OBJECT) return null
|
|
53
|
+
const rsa = __pulse_jwt_string_member(policy, 'algorithm') == 'RS256'
|
|
54
|
+
const allowed = rsa ? ['kty', 'n', 'e', 'd', 'p', 'q', 'dp', 'dq', 'qi', 'alg', 'use', 'key_ops', 'kid', 'ext'] : ['kty', 'crv', 'x', 'y', 'd', 'alg', 'use', 'key_ops', 'kid', 'ext']
|
|
55
|
+
for (let i = 0; i < jwk.keys.length; i++) if (allowed.indexOf(jwk.keys[i]) < 0) return null
|
|
56
|
+
if (rsa ? __pulse_jwt_string_member(jwk, 'kty') != 'RSA' : (__pulse_jwt_string_member(jwk, 'kty') != 'EC' || __pulse_jwt_string_member(jwk, 'crv') != 'P-256')) return null
|
|
57
|
+
if (__pulse_jwt_has_field(jwk, 'alg') && __pulse_jwt_string_member(jwk, 'alg') != (rsa ? 'RS256' : 'ES256')) return null
|
|
58
|
+
if (__pulse_jwt_has_field(jwk, 'use') && __pulse_jwt_string_member(jwk, 'use') != 'sig') return null
|
|
59
|
+
if (__pulse_jwt_has_field(jwk, 'ext') && __pulse_fastly_value(__pulse_jwt_object_field(jwk, 'ext')).kind != PULSE_VALUE_BOOLEAN) return null
|
|
60
|
+
if (__pulse_jwt_has_field(jwk, 'key_ops')) {
|
|
61
|
+
const ops = __pulse_fastly_value(__pulse_jwt_object_field(jwk, 'key_ops'))
|
|
62
|
+
if (ops.kind != PULSE_VALUE_ARRAY || ops.values.length != 1 || !__pulse_jwt_array_contains(ops, 'sign')) return null
|
|
63
|
+
}
|
|
64
|
+
if (__pulse_jwt_has_field(jwk, 'kid')) {
|
|
65
|
+
const kid = __pulse_jwt_string_member(jwk, 'kid')
|
|
66
|
+
if (kid === null || kid.length == 0 || kid.indexOf(String.fromCharCode(0)) >= 0 || String.UTF8.byteLength(kid) > 256) return null
|
|
67
|
+
if (__pulse_jwt_has_field(policy, 'kid') && __pulse_jwt_string_member(policy, 'kid') != kid) return null
|
|
68
|
+
}
|
|
69
|
+
if (rsa) return __pulse_jwt_rsa_private_bytes(jwk)
|
|
70
|
+
const names = ['x', 'y', 'd']
|
|
71
|
+
const output = new Uint8Array(96)
|
|
72
|
+
for (let i = 0; i < 3; i++) {
|
|
73
|
+
const value = __pulse_jwt_string_member(jwk, names[i])
|
|
74
|
+
if (value === null || value.length != 43) { __pulse_jwt_wipe(output); return null }
|
|
75
|
+
__pulse_fastly_remember_secret(value)
|
|
76
|
+
const decoded = __pulse_jwt_base64url_decode(value)
|
|
77
|
+
if (decoded === null) { __pulse_jwt_wipe(output); return null }
|
|
78
|
+
if (decoded.length != 32) { __pulse_jwt_wipe(decoded); __pulse_jwt_wipe(output); return null }
|
|
79
|
+
memory.copy(output.dataStart + i * 32, decoded.dataStart, 32)
|
|
80
|
+
__pulse_jwt_wipe(decoded)
|
|
81
|
+
}
|
|
82
|
+
return output
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function pulse_jwt_fastly_sign(effectIndex: i32, outerHandle: i32): i32 {
|
|
86
|
+
const outer = __pulse_fastly_value(outerHandle)
|
|
87
|
+
const policy = __pulse_fastly_value(__pulse_jwt_object_field(outer, 'payload'))
|
|
88
|
+
const invocation = __pulse_fastly_value(__pulse_jwt_object_field(outer, 'invocation'))
|
|
89
|
+
const claimsHandle = __pulse_jwt_object_field(invocation, 'claims')
|
|
90
|
+
const claims = __pulse_fastly_value(claimsHandle)
|
|
91
|
+
const lifetime = __pulse_jwt_numeric_claim(policy, 'expiresInSeconds')
|
|
92
|
+
const algorithm = __pulse_jwt_string_member(policy, 'algorithm')
|
|
93
|
+
const kid = __pulse_jwt_string_member(policy, 'kid')
|
|
94
|
+
if (__pulse_jwt_has_field(policy, 'kid') && (kid === null || kid.length == 0 || kid.indexOf(String.fromCharCode(0)) >= 0 || String.UTF8.byteLength(kid) > 256)) {
|
|
95
|
+
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_KEY_INVALID, 249)
|
|
96
|
+
}
|
|
97
|
+
if ((algorithm != 'HS256' && algorithm != 'ES256' && algorithm != 'RS256') || !isFinite(lifetime)
|
|
98
|
+
|| Math.floor(lifetime) != lifetime || lifetime < 1 || lifetime > 9007199254740991.0) {
|
|
99
|
+
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_OPERATION_FAILED, 240)
|
|
100
|
+
}
|
|
101
|
+
if (claims.kind != PULSE_VALUE_OBJECT || __pulse_jwt_has_field(claims, 'iat')
|
|
102
|
+
|| __pulse_jwt_has_field(claims, 'exp') || __pulse_jwt_has_field(claims, 'nbf')) {
|
|
103
|
+
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_CLAIMS_INVALID, 241)
|
|
104
|
+
}
|
|
105
|
+
const budget = new __PulseJwtSignBudget()
|
|
106
|
+
if (!__pulse_jwt_sign_validate(claimsHandle, 0, budget)) return __pulse_jwt_fail(effectIndex, budget.code, 242)
|
|
107
|
+
if (String.UTF8.byteLength(__pulse_fastly_json(claimsHandle, 0)) > 8192) {
|
|
108
|
+
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_LIMIT_EXCEEDED, 243)
|
|
109
|
+
}
|
|
110
|
+
let key = __pulse_fastly_jwt_resolve_secret(effectIndex)
|
|
111
|
+
if (key.length < 32 || key.length > 4096) {
|
|
112
|
+
__pulse_jwt_wipe(key)
|
|
113
|
+
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_KEY_INVALID, 244)
|
|
114
|
+
}
|
|
115
|
+
if (algorithm != 'HS256') {
|
|
116
|
+
const decoded = __pulse_jwt_sign_private_key(key, policy)
|
|
117
|
+
__pulse_jwt_wipe(key)
|
|
118
|
+
if (decoded === null) return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_KEY_INVALID, 249)
|
|
119
|
+
key = decoded
|
|
120
|
+
}
|
|
121
|
+
const captured = __pulse_fastly_jwt_capture_clock(effectIndex)
|
|
122
|
+
const now = Math.floor(captured)
|
|
123
|
+
if (!isFinite(captured) || captured < 0 || captured > 8640000000000.0) {
|
|
124
|
+
__pulse_jwt_wipe(key)
|
|
125
|
+
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_CLOCK_INVALID, 245)
|
|
126
|
+
}
|
|
127
|
+
if (now > 8640000000000.0 - lifetime) {
|
|
128
|
+
__pulse_jwt_wipe(key)
|
|
129
|
+
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_OPERATION_FAILED, 248)
|
|
130
|
+
}
|
|
131
|
+
const issued = host_value_object()
|
|
132
|
+
for (let i = 0; i < claims.keys.length; i++) {
|
|
133
|
+
host_value_object_set(issued, __pulse_fastly_string_value(unchecked(claims.keys[i])), unchecked(claims.values[i]))
|
|
134
|
+
}
|
|
135
|
+
host_value_object_set(issued, __pulse_fastly_string_value('iat'), host_value_number(now))
|
|
136
|
+
host_value_object_set(issued, __pulse_fastly_string_value('exp'), host_value_number(now + lifetime))
|
|
137
|
+
const text = __pulse_fastly_json(issued, 0)
|
|
138
|
+
if (String.UTF8.byteLength(text) > 8192) {
|
|
139
|
+
__pulse_jwt_wipe(key)
|
|
140
|
+
return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_LIMIT_EXCEEDED, 246)
|
|
141
|
+
}
|
|
142
|
+
__pulse_fastly_remember_secret(text)
|
|
143
|
+
const header = host_value_object()
|
|
144
|
+
host_value_object_set(header, __pulse_fastly_string_value('alg'), __pulse_fastly_string_value(algorithm!))
|
|
145
|
+
host_value_object_set(header, __pulse_fastly_string_value('typ'), __pulse_fastly_string_value('JWT'))
|
|
146
|
+
if (kid !== null) host_value_object_set(header, __pulse_fastly_string_value('kid'), __pulse_fastly_string_value(kid))
|
|
147
|
+
const input = __pulse_jwt_base64url_encode(Uint8Array.wrap(String.UTF8.encode(__pulse_fastly_json(header, 0), false))) + '.' + __pulse_jwt_base64url_encode(Uint8Array.wrap(String.UTF8.encode(text, false)))
|
|
148
|
+
const data = Uint8Array.wrap(String.UTF8.encode(input, false))
|
|
149
|
+
const tag = new Uint8Array(algorithm == 'RS256' ? i32(load<u32>(key.dataStart)) : algorithm == 'ES256' ? 64 : 32)
|
|
150
|
+
const status = __pulse_fastly_jwt_crypto_sign(algorithm!, key, data, tag)
|
|
151
|
+
__pulse_jwt_wipe(key); __pulse_jwt_wipe(data)
|
|
152
|
+
if (status == -1) { __pulse_jwt_wipe(tag); return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_KEY_INVALID, 249) }
|
|
153
|
+
if (status != 1) { __pulse_jwt_wipe(tag); return __pulse_jwt_fail(effectIndex, __PULSE_JWT_ERROR_OPERATION_FAILED, 247) }
|
|
154
|
+
const signature = __pulse_jwt_base64url_encode(tag)
|
|
155
|
+
__pulse_jwt_wipe(tag)
|
|
156
|
+
const token = input + '.' + signature
|
|
157
|
+
__pulse_fastly_remember_secret(signature); __pulse_fastly_remember_secret(token)
|
|
158
|
+
return __pulse_fastly_string_value(token)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
function __pulse_jwt_rsa_integer(jwk: __PulseFastlyValue, name: string, maximum: i32): Uint8Array | null {
|
|
163
|
+
const value = __pulse_jwt_string_member(jwk, name)
|
|
164
|
+
if (value === null || value.length > (maximum * 4 + 2) / 3) return null
|
|
165
|
+
__pulse_fastly_remember_secret(value)
|
|
166
|
+
const decoded = __pulse_jwt_base64url_decode(value)
|
|
167
|
+
if (decoded === null) return null
|
|
168
|
+
if (decoded.length == 0 || decoded.length > maximum || decoded[0] == 0) { __pulse_jwt_wipe(decoded); return null }
|
|
169
|
+
return decoded
|
|
170
|
+
}
|
|
171
|
+
function __pulse_jwt_rsa_private_bytes(jwk: __PulseFastlyValue): Uint8Array | null {
|
|
172
|
+
const n = __pulse_jwt_rsa_integer(jwk, 'n', 512)
|
|
173
|
+
if (n === null) return null
|
|
174
|
+
const k = n.length
|
|
175
|
+
if ((k != 256 && k != 384 && k != 512) || n[0] < 128 || (n[k-1] & 1) == 0) { __pulse_jwt_wipe(n); return null }
|
|
176
|
+
const output = new Uint8Array(8 + k * 9 / 2)
|
|
177
|
+
store<u32>(output.dataStart, k)
|
|
178
|
+
memory.copy(output.dataStart + 4, n.dataStart, k); __pulse_jwt_wipe(n)
|
|
179
|
+
const names = ['e', 'd', 'p', 'q', 'dp', 'dq', 'qi']
|
|
180
|
+
let offset = 4 + k
|
|
181
|
+
for (let i = 0; i < names.length; i++) {
|
|
182
|
+
const width = i == 0 ? 4 : i == 1 ? k : k / 2
|
|
183
|
+
const bytes = __pulse_jwt_rsa_integer(jwk, names[i], width)
|
|
184
|
+
if (bytes === null) { __pulse_jwt_wipe(output); return null }
|
|
185
|
+
memory.copy(output.dataStart + offset + width - bytes.length, bytes.dataStart, bytes.length)
|
|
186
|
+
offset += width; __pulse_jwt_wipe(bytes)
|
|
187
|
+
}
|
|
188
|
+
return output
|
|
189
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto-verifier.d.ts","sourceRoot":"","sources":["../src/crypto-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"crypto-verifier.d.ts","sourceRoot":"","sources":["../src/crypto-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,wBAAwB,EAE7B,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAIL,KAAK,SAAS,EAEf,MAAM,cAAc,CAAC;AACtB,OAAO,EAA4B,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAiB7E,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,kCAAkC,CAAC;AAE1C,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,CAAC;AAEtD,MAAM,WAAW,qBAAsB,SAAQ,eAAe;CAAG;AAEjE,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,gBAAgB,KACtB,wBAAwB,GAAG,WAAW,CAAC,wBAAwB,CAAC,CAAC;AAEtE,MAAM,MAAM,wBAAwB,GAAG,CACrC,OAAO,EAAE,sBAAsB,KAC5B,wBAAwB,GAAG,WAAW,CAAC,wBAAwB,CAAC,CAAC;AAEtE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;QACrB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;KACrC,CAAC,CAAC;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC;QAC5B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;KAC3C,CAAC,CAAC;CACJ;AA8HD,wBAAsB,mBAAmB,CAAC,MAAM,GAAG,SAAS,EAC1D,KAAK,EAAE,sBAAsB,EAC7B,IAAI,EAAE,qBAAqB,EAC3B,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CA8GlC"}
|
package/dist/crypto-verifier.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CRYPTO_VERIFICATION_STATUSES, normalizeEs256JoseVerifyRequest, } from '@pulse-compute/crypto';
|
|
1
|
+
import { CRYPTO_VERIFICATION_STATUSES, normalizeEs256JoseVerifyRequest, normalizeRs256JoseVerifyRequest, } from '@pulse-compute/crypto';
|
|
2
2
|
import { isJwtError, jwtError } from './errors.js';
|
|
3
|
-
import { normalizeJwtVerifyOptions,
|
|
3
|
+
import { normalizeJwtVerifyOptions, selectSignatureVerificationJwk, } from './options.js';
|
|
4
4
|
import { normalizeJwtVerification } from './result.js';
|
|
5
5
|
import { compactJwtParts, compactJwtSignatureInput, parseVerifiedClaims, preflightCompactJwt, protectedAlgorithm, protectedHeaderString, } from './token.js';
|
|
6
6
|
import { captureJwtCurrentDate } from './internal/clock.js';
|
|
@@ -161,11 +161,14 @@ export async function verifyJwtWithCrypto(input, host, crypto) {
|
|
|
161
161
|
keyBytes.fill(0);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
-
else if (selectedAlgorithm === 'ES256') {
|
|
164
|
+
else if (selectedAlgorithm === 'ES256' || selectedAlgorithm === 'RS256') {
|
|
165
165
|
const verifySignature = cryptoSignatureVerify(crypto);
|
|
166
|
-
const selectedJwk =
|
|
166
|
+
const selectedJwk = selectSignatureVerificationJwk(options.key, kid, selectedAlgorithm);
|
|
167
167
|
const compact = compactJwtParts(token);
|
|
168
|
-
const normalized =
|
|
168
|
+
const normalized = selectedAlgorithm === 'RS256' ? normalizeRs256JoseVerifyRequest({
|
|
169
|
+
key: { n: selectedJwk.n, e: selectedJwk.e },
|
|
170
|
+
data: compact.signingInput, signature: compact.signatureSegment,
|
|
171
|
+
}) : normalizeEs256JoseVerifyRequest({
|
|
169
172
|
key: {
|
|
170
173
|
x: selectedJwk.x,
|
|
171
174
|
y: selectedJwk.y,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto-verifier.js","sourceRoot":"","sources":["../src/crypto-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,GAKhC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EACL,yBAAyB,EACzB,
|
|
1
|
+
{"version":3,"file":"crypto-verifier.js","sourceRoot":"","sources":["../src/crypto-verifier.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { bearer } from './bearer.js';
|
|
|
3
3
|
import { JwtError, JWT_ERROR_CODES } from './errors.js';
|
|
4
4
|
import { type JwtClaims, type JwtVerifyOptions } from './options.js';
|
|
5
5
|
import { type JwtVerification } from './result.js';
|
|
6
|
+
import { type JwtSignOptions } from './sign.js';
|
|
7
|
+
export type { JwtSignOptions } from './sign.js';
|
|
6
8
|
export { bearer, JwtError, JWT_ERROR_CODES };
|
|
7
9
|
export type { JwtErrorCode, JwtErrorDetailValue, } from './errors.js';
|
|
8
10
|
export type { JwtAlgorithm, JwtClaims, JwtJsonPrimitive, JwtJsonValue, JwtPublicJwk, JwtVerificationKey, JwtVerifyOptions, } from './options.js';
|
|
@@ -11,9 +13,11 @@ export declare function verify<Claims>(ctx: PulseContext, token: string | undefi
|
|
|
11
13
|
readonly claimsSchema: string;
|
|
12
14
|
}): PulseParallelEffect<JwtVerification<Claims>>;
|
|
13
15
|
export declare function verify(ctx: PulseContext, token: string | undefined, options: JwtVerifyOptions): PulseParallelEffect<JwtVerification<JwtClaims>>;
|
|
16
|
+
export declare function sign(ctx: PulseContext, claims: JwtClaims, options: JwtSignOptions): PulseParallelEffect<string>;
|
|
14
17
|
export declare const jwt: Readonly<{
|
|
15
18
|
bearer: typeof bearer;
|
|
16
19
|
verify: typeof verify;
|
|
20
|
+
sign: typeof sign;
|
|
17
21
|
}>;
|
|
18
22
|
export default jwt;
|
|
19
23
|
//# 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":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAA0E,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACxH,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;AAC7C,YAAY,EACV,YAAY,EACZ,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,wBAAgB,MAAM,CAAC,MAAM,EAC3B,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,EAAE,gBAAgB,GAAG;IAAE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC5D,mBAAmB,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;AAChD,wBAAgB,MAAM,CACpB,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,EAAE,gBAAgB,GACxB,mBAAmB,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;AAmBnD,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAM/G;AAED,eAAO,MAAM,GAAG;;;;EAId,CAAC;AAEH,eAAe,GAAG,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { normalizeJwtVerifyOptions, } from './options.js';
|
|
|
4
4
|
import { normalizeJwtVerification, } from './result.js';
|
|
5
5
|
import { preflightCompactJwt } from './token.js';
|
|
6
6
|
import { pulseJwtRuntime } from './internal/package-runtime.js';
|
|
7
|
+
import { normalizeJwtSignClaims, normalizeJwtSignOptions, normalizeJwtSignature } from './sign.js';
|
|
7
8
|
export { bearer, JwtError, JWT_ERROR_CODES };
|
|
8
9
|
export function verify(ctx, token, options) {
|
|
9
10
|
preflightCompactJwt(token);
|
|
@@ -13,9 +14,17 @@ export function verify(ctx, token, options) {
|
|
|
13
14
|
options: normalized,
|
|
14
15
|
}, (value) => normalizeJwtVerification(value));
|
|
15
16
|
}
|
|
17
|
+
export function sign(ctx, claims, options) {
|
|
18
|
+
const normalized = normalizeJwtSignOptions(options);
|
|
19
|
+
return pulseJwtRuntime.effect(ctx, 'sign', {
|
|
20
|
+
claims: normalizeJwtSignClaims(claims),
|
|
21
|
+
options: normalized,
|
|
22
|
+
}, value => normalizeJwtSignature(value, normalized));
|
|
23
|
+
}
|
|
16
24
|
export const jwt = Object.freeze({
|
|
17
25
|
bearer,
|
|
18
26
|
verify,
|
|
27
|
+
sign,
|
|
19
28
|
});
|
|
20
29
|
export default jwt;
|
|
21
30
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EACL,yBAAyB,GAG1B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,GAEzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EACL,yBAAyB,GAG1B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,wBAAwB,GAEzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,qBAAqB,EAAuB,MAAM,WAAW,CAAC;AAGxH,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;AA8B7C,MAAM,UAAU,MAAM,CACpB,GAAiB,EACjB,KAAyB,EACzB,OAAyB;IAEzB,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,UAAU,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACtD,OAAO,eAAe,CAAC,MAAM,CAC3B,GAAG,EACH,QAAQ,EACR;QACE,KAAK,EAAE,KAAe;QACtB,OAAO,EAAE,UAAU;KACpB,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAC3C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAiB,EAAE,MAAiB,EAAE,OAAuB;IAChF,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACpD,OAAO,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE;QACzC,MAAM,EAAE,sBAAsB,CAAC,MAAM,CAAC;QACtC,OAAO,EAAE,UAAU;KACpB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/B,MAAM;IACN,MAAM;IACN,IAAI;CACL,CAAC,CAAC;AAEH,eAAe,GAAG,CAAC"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import packageRuntime from '@pulse-compute/runtime/package';
|
|
2
2
|
export declare const pulseJwtRuntime: packageRuntime.PulsePackageRuntime<{
|
|
3
|
+
readonly sign: {
|
|
4
|
+
readonly kind: "jwt.sign";
|
|
5
|
+
readonly capability: "jwt.sign";
|
|
6
|
+
readonly result: "string";
|
|
7
|
+
};
|
|
3
8
|
readonly verify: {
|
|
4
9
|
readonly kind: "jwt.verify";
|
|
5
10
|
readonly capability: "jwt.verify";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-runtime.d.ts","sourceRoot":"","sources":["../../src/internal/package-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,gCAAgC,CAAC;AAE5D,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"package-runtime.d.ts","sourceRoot":"","sources":["../../src/internal/package-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,gCAAgC,CAAC;AAE5D,eAAO,MAAM,eAAe;;;;;;;;;;;EAYjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-runtime.js","sourceRoot":"","sources":["../../src/internal/package-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,gCAAgC,CAAC;AAE5D,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAC,oBAAoB,CAAC;IACjE,OAAO,EAAE,oBAAoB;IAC7B,UAAU,EAAE,WAAW;IACvB,YAAY,EAAE,KAAK;IACnB,UAAU,EAAE;QACV,MAAM,EAAE;YACN,IAAI,EAAE,YAAY;YAClB,UAAU,EAAE,YAAY;YACxB,MAAM,EAAE,kBAAkB;SAC3B;KACF;CACO,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"package-runtime.js","sourceRoot":"","sources":["../../src/internal/package-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,gCAAgC,CAAC;AAE5D,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAC,oBAAoB,CAAC;IACjE,OAAO,EAAE,oBAAoB;IAC7B,UAAU,EAAE,WAAW;IACvB,YAAY,EAAE,KAAK;IACnB,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE;QACpE,MAAM,EAAE;YACN,IAAI,EAAE,YAAY;YAClB,UAAU,EAAE,YAAY;YACxB,MAAM,EAAE,kBAAkB;SAC3B;KACF;CACO,CAAC,CAAC"}
|
package/dist/options.d.ts
CHANGED
|
@@ -110,4 +110,5 @@ export declare const JWT_ES256_KEY_NORMALIZATION_CONTRACT: Readonly<{
|
|
|
110
110
|
export declare function normalizeJwtVerifyOptions(value: JwtVerifyOptions): NormalizedJwtVerifyOptions;
|
|
111
111
|
export declare function isJwkCompatibleWithAlgorithm(jwk: JwtPublicJwk, algorithm: JwtAlgorithm): boolean;
|
|
112
112
|
export declare function selectEs256VerificationJwk(key: JwtVerificationKey, kid: string | undefined): JwtPublicJwk;
|
|
113
|
+
export declare function selectSignatureVerificationJwk(key: JwtVerificationKey, kid: string | undefined, algorithm: 'ES256' | 'RS256'): JwtPublicJwk;
|
|
113
114
|
//# sourceMappingURL=options.d.ts.map
|
package/dist/options.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
|
package/dist/options.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeRsaPublicKey } from '@pulse-compute/crypto';
|
|
1
2
|
import { normalizeP256PublicKeyCoordinates } from '@pulse-compute/crypto';
|
|
2
3
|
import { jwtError } from './errors.js';
|
|
3
4
|
import { jwtDataRecord, jwtDenseArrayValues, } from './internal/data.js';
|
|
@@ -173,9 +174,8 @@ function normalizePublicJwk(value) {
|
|
|
173
174
|
throw jwtError('PULSE_JWT_KEY_INVALID', { category: 'key' });
|
|
174
175
|
const declaredType = record.get('kty');
|
|
175
176
|
if ([...record.keys()].some((key) => PRIVATE_JWK_MEMBERS.includes(key))
|
|
176
|
-
|| [...record.keys()].some((key) => (declaredType === '
|
|
177
|
-
? !ES256_JWK_MEMBERS.has(key)
|
|
178
|
-
: !JWK_MEMBERS.has(key)))) {
|
|
177
|
+
|| [...record.keys()].some((key) => (declaredType === 'RSA' ? !new Set(['kty', 'n', 'e', 'alg', 'use', 'key_ops', 'kid']).has(key)
|
|
178
|
+
: declaredType === 'EC' ? !ES256_JWK_MEMBERS.has(key) : !JWK_MEMBERS.has(key)))) {
|
|
179
179
|
throw jwtError('PULSE_JWT_KEY_INVALID', { category: 'key' });
|
|
180
180
|
}
|
|
181
181
|
const kty = nonEmptyString(record.get('kty'), 'key');
|
|
@@ -206,8 +206,13 @@ function normalizePublicJwk(value) {
|
|
|
206
206
|
throw jwtError('PULSE_JWT_KEY_INVALID', { category: 'key' });
|
|
207
207
|
}
|
|
208
208
|
if (kty === 'RSA') {
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
if (typeof output.kid === 'string' && new TextEncoder().encode(output.kid).length > 256)
|
|
210
|
+
throw jwtError('PULSE_JWT_KEY_INVALID', { category: 'key-kid' });
|
|
211
|
+
const n = nonEmptyString(output.n, 'key'), e = nonEmptyString(output.e, 'key');
|
|
212
|
+
const normalized = normalizeRsaPublicKey({ n, e });
|
|
213
|
+
if (!normalized.ok || output.alg !== undefined && output.alg !== 'RS256')
|
|
214
|
+
throw jwtError('PULSE_JWT_KEY_INVALID', { category: 'key-rsa' });
|
|
215
|
+
normalized.key.bytes.fill(0);
|
|
211
216
|
}
|
|
212
217
|
else if (kty === 'EC') {
|
|
213
218
|
if (output.crv !== 'P-256')
|
|
@@ -341,13 +346,16 @@ export function isJwkCompatibleWithAlgorithm(jwk, algorithm) {
|
|
|
341
346
|
return compatibleAlgorithm(jwk, algorithm);
|
|
342
347
|
}
|
|
343
348
|
export function selectEs256VerificationJwk(key, kid) {
|
|
349
|
+
return selectSignatureVerificationJwk(key, kid, 'ES256');
|
|
350
|
+
}
|
|
351
|
+
export function selectSignatureVerificationJwk(key, kid, algorithm) {
|
|
344
352
|
if (key.type === 'secret') {
|
|
345
353
|
throw jwtError('PULSE_JWT_KEY_INVALID', {
|
|
346
354
|
category: 'algorithm-key-mismatch',
|
|
347
355
|
});
|
|
348
356
|
}
|
|
349
357
|
if (key.type === 'jwk') {
|
|
350
|
-
if (!compatibleAlgorithm(key.key,
|
|
358
|
+
if (!compatibleAlgorithm(key.key, algorithm)) {
|
|
351
359
|
throw jwtError('PULSE_JWT_KEY_INVALID', {
|
|
352
360
|
category: 'algorithm-key-mismatch',
|
|
353
361
|
});
|
|
@@ -364,14 +372,14 @@ export function selectEs256VerificationJwk(key, kid) {
|
|
|
364
372
|
category: selected.length === 0 ? 'unknown-kid' : 'duplicate-kid',
|
|
365
373
|
});
|
|
366
374
|
}
|
|
367
|
-
if (!compatibleAlgorithm(selected[0],
|
|
375
|
+
if (!compatibleAlgorithm(selected[0], algorithm)) {
|
|
368
376
|
throw jwtError('PULSE_JWT_KEY_INVALID', {
|
|
369
377
|
category: 'algorithm-key-mismatch',
|
|
370
378
|
});
|
|
371
379
|
}
|
|
372
380
|
return selected[0];
|
|
373
381
|
}
|
|
374
|
-
const eligible = key.keys.filter((entry) => (compatibleAlgorithm(entry,
|
|
382
|
+
const eligible = key.keys.filter((entry) => (compatibleAlgorithm(entry, algorithm)));
|
|
375
383
|
if (eligible.length !== 1) {
|
|
376
384
|
throw jwtError('PULSE_JWT_KEY_INVALID', {
|
|
377
385
|
category: eligible.length === 0 ? 'missing-kid' : 'ambiguous-key',
|