unjwt 0.4.0 → 0.5.1
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 +445 -190
- package/dist/index.d.mts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.mjs +5 -5
- package/dist/jwe.d.mts +3 -3
- package/dist/jwe.d.ts +3 -3
- package/dist/jwe.mjs +4 -3
- package/dist/jwk.d.mts +2 -2
- package/dist/jwk.d.ts +2 -2
- package/dist/jwk.mjs +2 -2
- package/dist/jws.d.mts +3 -3
- package/dist/jws.d.ts +3 -3
- package/dist/jws.mjs +4 -4
- package/dist/shared/unjwt.1gbuWbc6.mjs +1507 -0
- package/dist/shared/unjwt.B0XDPf8a.d.ts +189 -0
- package/dist/shared/unjwt.B4fFiy1c.d.mts +52 -0
- package/dist/shared/unjwt.BG_R52ey.d.mts +100 -0
- package/dist/shared/unjwt.BISJ5yt1.d.ts +52 -0
- package/dist/shared/unjwt.BxqF-n1S.mjs +167 -0
- package/dist/shared/unjwt.C9Xhi7hE.mjs +101 -0
- package/dist/shared/unjwt.CVKbKOFy.d.ts +100 -0
- package/dist/shared/unjwt.Cd9nTEWg.d.mts +52 -0
- package/dist/shared/unjwt.Ce72NmIz.mjs +453 -0
- package/dist/shared/unjwt.CxhGjEAX.d.mts +202 -0
- package/dist/shared/unjwt.CxhGjEAX.d.ts +202 -0
- package/dist/shared/unjwt.D1J1DelP.d.mts +198 -0
- package/dist/shared/unjwt.DHdDAH0L.mjs +83 -0
- package/dist/shared/unjwt.DQIYSlHj.d.mts +189 -0
- package/dist/shared/unjwt.DqmNvXMd.d.ts +52 -0
- package/dist/shared/unjwt.WvWb2zNM.d.ts +198 -0
- package/dist/utils.d.mts +2 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.mjs +1 -0
- package/package.json +8 -4
- package/dist/shared/unjwt.4uzJv0cA.d.mts +0 -110
- package/dist/shared/unjwt.A7HKFx3n.d.mts +0 -52
- package/dist/shared/unjwt.BdjvpIUY.d.mts +0 -79
- package/dist/shared/unjwt.BmjmfFWo.d.ts +0 -79
- package/dist/shared/unjwt.C9ELsKeK.mjs +0 -120
- package/dist/shared/unjwt.CVUxLNoy.d.ts +0 -52
- package/dist/shared/unjwt.ChP7VhqI.d.ts +0 -110
- package/dist/shared/unjwt.DD0p18Gd.mjs +0 -81
- package/dist/shared/unjwt.DGsIvgyn.d.ts +0 -106
- package/dist/shared/unjwt.DPTwlVpK.mjs +0 -28
- package/dist/shared/unjwt.Dr-mxtq9.d.mts +0 -106
- package/dist/shared/unjwt.KOd0vXyx.mjs +0 -90
- package/dist/shared/unjwt._GivNhs2.mjs +0 -213
- package/dist/shared/unjwt.zb2wBNCJ.d.mts +0 -82
- package/dist/shared/unjwt.zb2wBNCJ.d.ts +0 -82
package/README.md
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
# unjwt
|
|
2
2
|
|
|
3
|
-
<!-- automd:badges color=
|
|
3
|
+
<!-- automd:badges bundlephobia style="flat" color="FFDC3B" -->
|
|
4
4
|
|
|
5
|
-
[](https://npmjs.com/package/unjwt)
|
|
6
|
+
[](https://npm.chart.dev/unjwt)
|
|
7
|
+
[](https://bundlephobia.com/package/unjwt)
|
|
7
8
|
|
|
8
9
|
<!-- /automd -->
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
A collection of low-level JWT ([RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519)) utilities using the Web Crypto API. Supports:
|
|
11
12
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- JWK (JSON Web Key)
|
|
13
|
+
- **JWS (JSON Web Signature, [RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515))**: sign and verify tokens using HMAC, RSA (RSASSA-PKCS1-v1_5 & RSA-PSS), and ECDSA algorithms.
|
|
14
|
+
- **JWE (JSON Web Encryption, [RFC 7516](https://datatracker.ietf.org/doc/html/rfc7516))**: encrypt and decrypt data using various key management algorithms (AES Key Wrap, AES-GCM Key Wrap, RSA-OAEP, PBES2, ECDH-ES) and content encryption algorithms (AES-GCM, AES-CBC HMAC-SHA2).
|
|
15
|
+
- **JWK (JSON Web Key, [RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517))**: generate, import, export, wrap, and unwrap keys in JWK format or as `CryptoKey` objects.
|
|
16
|
+
|
|
17
|
+
> [!WARNING]
|
|
18
|
+
> Please do note that some algorithms are not fully working out-of-the-box yet, such as:
|
|
19
|
+
>
|
|
20
|
+
> - ECDH-ES algorithms with AES Key Wrap (e.g., ECDH-ES+A128KW)
|
|
21
|
+
> - RSA algorithms in combination with some bigger CBC encodings (for example RSA-OAEP-256 with A256CBC-HS512)
|
|
22
|
+
>
|
|
23
|
+
> For these algorithms, you should be able to provide your own keys. Although I do plan to study and simplify this.
|
|
15
24
|
|
|
16
25
|
## Usage
|
|
17
26
|
|
|
@@ -28,308 +37,553 @@ Import:
|
|
|
28
37
|
|
|
29
38
|
```js
|
|
30
39
|
import { jws, jwe, jwk } from "unjwt";
|
|
31
|
-
|
|
40
|
+
// JWS functions
|
|
32
41
|
import { sign, verify } from "unjwt/jws";
|
|
33
|
-
|
|
42
|
+
// JWE functions
|
|
43
|
+
import { encrypt, decrypt } from "unjwt/jwe";
|
|
44
|
+
// JWK functions
|
|
45
|
+
import {
|
|
46
|
+
generateKey,
|
|
47
|
+
deriveKeyFromPassword,
|
|
48
|
+
importKey,
|
|
49
|
+
exportKey,
|
|
50
|
+
wrapKey,
|
|
51
|
+
unwrapKey,
|
|
52
|
+
} from "unjwt/jwk";
|
|
53
|
+
// Utility functions
|
|
54
|
+
import { base64UrlEncode, base64UrlDecode, randomBytes } from "unjwt/utils";
|
|
34
55
|
```
|
|
35
56
|
|
|
36
57
|
**CDN** (Deno, Bun and Browsers)
|
|
37
58
|
|
|
38
59
|
```js
|
|
39
60
|
import { jws, jwe, jwk } from "https://esm.sh/unjwt";
|
|
40
|
-
|
|
61
|
+
// JWS functions
|
|
41
62
|
import { sign, verify } from "https://esm.sh/unjwt/jws";
|
|
42
|
-
|
|
63
|
+
// JWE functions
|
|
64
|
+
import { encrypt, decrypt } from "https://esm.sh/unjwt/jwe";
|
|
65
|
+
// JWK functions
|
|
66
|
+
import {
|
|
67
|
+
generateKey,
|
|
68
|
+
deriveKeyFromPassword,
|
|
69
|
+
importKey,
|
|
70
|
+
exportKey,
|
|
71
|
+
wrapKey,
|
|
72
|
+
unwrapKey,
|
|
73
|
+
} from "https://esm.sh/unjwt/jwk";
|
|
74
|
+
// Utility functions
|
|
75
|
+
import {
|
|
76
|
+
base64UrlEncode,
|
|
77
|
+
base64UrlDecode,
|
|
78
|
+
randomBytes,
|
|
79
|
+
} from "https://esm.sh/unjwt/utils";
|
|
43
80
|
```
|
|
44
81
|
|
|
45
|
-
###
|
|
82
|
+
### JWS (JSON Web Signature, [RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515))
|
|
46
83
|
|
|
47
|
-
|
|
84
|
+
Functions to sign and verify data according to the JWS specification.
|
|
48
85
|
|
|
49
|
-
#### `
|
|
86
|
+
#### `sign(payload, key, options)`
|
|
50
87
|
|
|
51
|
-
|
|
88
|
+
Creates a JWS token.
|
|
52
89
|
|
|
53
|
-
- `
|
|
54
|
-
- `
|
|
55
|
-
- `options
|
|
56
|
-
- `
|
|
57
|
-
- `
|
|
58
|
-
- `protectedHeader`: An object containing JWE header parameters to include.
|
|
59
|
-
- `alg`: Key Wrapping Algorithm (default: `PBES2-HS256+A128KW`). Supported: `PBES2-HS256+A128KW`, `PBES2-HS384+A192KW`, `PBES2-HS512+A256KW`.
|
|
60
|
-
- `enc`: Content Encryption Algorithm (default: `A256GCM`). Supported: `A128GCM`, `A192GCM`, `A256GCM`, `A128CBC-HS256`, `A192CBC-HS384`, `A256CBC-HS512`.
|
|
61
|
-
- Other standard JWE or custom header parameters can be added here.
|
|
90
|
+
- `payload`: The data to sign (`string`, `Uint8Array`, or a JSON-serializable `object`).
|
|
91
|
+
- `key`: The signing key (`CryptoKey`, `JWK`, or `Uint8Array` for symmetric keys).
|
|
92
|
+
- `options`:
|
|
93
|
+
- `alg`: (Required) The JWS algorithm (e.g., `"HS256"`, `"RS256"`, `"ES256"`, `"PS256"`).
|
|
94
|
+
- `protectedHeader`: An object for additional JWS Protected Header parameters (e.g., `kid`, `typ`, `cty`, `crit`, `b64`). If `payload` is an object and `typ` is not set, it defaults to `"JWT"`. The `b64` parameter ([RFC7797 section-3](https://datatracker.ietf.org/doc/html/rfc7797#section-3)) controls payload encoding (defaults to `true`, meaning Base64URL encoded).
|
|
62
95
|
|
|
63
|
-
Returns a Promise resolving to the
|
|
96
|
+
Returns a `Promise<string>` resolving to the JWS token in Compact Serialization format.
|
|
64
97
|
|
|
65
|
-
**Example:**
|
|
98
|
+
**Example (HS256 with string secret):**
|
|
66
99
|
|
|
67
100
|
```ts
|
|
68
|
-
import {
|
|
101
|
+
import { sign } from "unjwt/jws";
|
|
69
102
|
|
|
70
|
-
const
|
|
71
|
-
const
|
|
103
|
+
const payload = { message: "My important data" }; // Object payload
|
|
104
|
+
const secret = "supersecretkey"; // String secret, will be imported (length depends on choosen alg)
|
|
72
105
|
|
|
73
|
-
const token = await
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
106
|
+
const token = await sign(payload, secret, { alg: "HS256" });
|
|
107
|
+
|
|
108
|
+
console.log(token);
|
|
109
|
+
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Example (RS256 with CryptoKey):**
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { sign } from "unjwt/jws";
|
|
116
|
+
import { generateKey } from "unjwt/jwk";
|
|
117
|
+
|
|
118
|
+
const payload = { userId: 123, permissions: ["read"] };
|
|
119
|
+
const { privateKey } = await generateKey("RS256"); // Generates a CryptoKeyPair
|
|
120
|
+
|
|
121
|
+
const token = await sign(payload, privateKey, { alg: "RS256" });
|
|
79
122
|
|
|
80
123
|
console.log(token);
|
|
81
|
-
//
|
|
124
|
+
// eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
82
125
|
```
|
|
83
126
|
|
|
84
|
-
#### `
|
|
127
|
+
#### `verify(jws, key, options?)`
|
|
85
128
|
|
|
86
|
-
|
|
129
|
+
Verifies a JWS token.
|
|
87
130
|
|
|
88
|
-
- `
|
|
89
|
-
- `
|
|
131
|
+
- `jws`: The JWS token string.
|
|
132
|
+
- `key`: The verification key (`CryptoKey`, `JWK`, `Uint8Array`, or a `KeyLookupFunction`).
|
|
133
|
+
A `KeyLookupFunction` has the signature `(header: JWSProtectedHeader) => Promise<CryptoKey | JWK | Uint8Array> | CryptoKey | JWK | Uint8Array`.
|
|
90
134
|
- `options` (optional):
|
|
91
|
-
- `
|
|
135
|
+
- `algorithms`: An array of allowed JWS `alg` values. If not provided, the `alg` from the JWS header is used.
|
|
136
|
+
- `critical`: An array of JWS header parameter names that the application understands and processes.
|
|
92
137
|
|
|
93
|
-
Returns a Promise
|
|
138
|
+
Returns a `Promise<JWSVerifyResult<T>>` which is an object `{ payload: T, protectedHeader: JWSProtectedHeader }`.
|
|
139
|
+
The `payload` type `T` can be `JWTClaims` (object), `string`, or `Uint8Array` depending on the JWS content and headers.
|
|
94
140
|
|
|
95
|
-
**Example:**
|
|
141
|
+
**Example (HS256):**
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { verify } from "unjwt/jws";
|
|
145
|
+
|
|
146
|
+
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // From HS256 sign example
|
|
147
|
+
const secret = "supersecretkey";
|
|
148
|
+
|
|
149
|
+
const { payload, protectedHeader } = await verify(token, secret);
|
|
150
|
+
console.log(payload); // { message: "My important data" }
|
|
151
|
+
console.log(protectedHeader); // { alg: "HS256", typ: "JWT" }
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Example (RS256 with key lookup):**
|
|
96
155
|
|
|
97
156
|
```ts
|
|
98
|
-
import {
|
|
157
|
+
import { verify } from "unjwt/jws";
|
|
158
|
+
import { generateKey } from "unjwt/jwk";
|
|
159
|
+
|
|
160
|
+
const token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."; // From RS256 sign example
|
|
99
161
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const password = "strongpassword";
|
|
162
|
+
// Example: using a key lookup function
|
|
163
|
+
const { publicKey: rsaPublicKey } = await generateKey("RS256"); // For example purposes, assume publicKey is stored/fetched during lookup
|
|
103
164
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
165
|
+
const keyLookup = async (header) => {
|
|
166
|
+
if (header.alg === "RS256" /* && header.kid === 'expected-kid' */) {
|
|
167
|
+
return rsaPublicKey;
|
|
168
|
+
}
|
|
169
|
+
throw new Error("Unsupported algorithm or key not found");
|
|
170
|
+
};
|
|
107
171
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
console.log(decryptedBytes); // Uint8Array [ 77, 121, 32, ... ]
|
|
172
|
+
const { payload } = await verify(token, keyLookup, { algorithms: ["RS256"] });
|
|
173
|
+
console.log(payload); // { userId: 123, permissions: ["read"] }
|
|
111
174
|
```
|
|
112
175
|
|
|
113
|
-
###
|
|
176
|
+
### JWE (JSON Web Encryption, [RFC 7516](https://datatracker.ietf.org/doc/html/rfc7516))
|
|
114
177
|
|
|
115
|
-
|
|
178
|
+
Functions to encrypt and decrypt data according to the JWE specification.
|
|
116
179
|
|
|
117
|
-
#### `
|
|
180
|
+
#### `encrypt(payload, key, options)`
|
|
118
181
|
|
|
119
|
-
|
|
182
|
+
Encrypts data to produce a JWE token.
|
|
120
183
|
|
|
121
|
-
- `payload`: The data to
|
|
122
|
-
- `
|
|
123
|
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
- `
|
|
127
|
-
- `
|
|
128
|
-
|
|
129
|
-
|
|
184
|
+
- `payload`: The data to encrypt (`string`, `Uint8Array`, or a JSON-serializable `object`).
|
|
185
|
+
- `key`: The Key Encryption Key (KEK) or password (`CryptoKey`, `JWK`, `string`, or `Uint8Array`).
|
|
186
|
+
- `options`:
|
|
187
|
+
- `alg`: (Required) The JWE Key Management algorithm (e.g., `"A128KW"`, `"RSA-OAEP-256"`, `"PBES2-HS256+A128KW"`, `"ECDH-ES+A128KW"`), defaults depends on the key provided.
|
|
188
|
+
- `enc`: (Required) The JWE Content Encryption algorithm (e.g., `"A128GCM"`, `"A256CBC-HS512"`), defaults depends on the key provided.
|
|
189
|
+
- `protectedHeader`: An object for JWE Protected Header parameters (e.g., `kid`, `typ`, `cty`, `crit`, `apu`, `apv`, `p2s`, `p2c`). If `payload` is an object and `typ` is not set, it defaults to `"JWT"`.
|
|
190
|
+
- `cek`: (Optional) Provide your own Content Encryption Key (`CryptoKey` or `Uint8Array`).
|
|
191
|
+
- `contentEncryptionIV`: (Optional) Provide your own Initialization Vector for content encryption (`Uint8Array`).
|
|
192
|
+
- Other algorithm-specific options like `p2s`, `p2c` (for PBES2), `keyManagementIV`, `ecdhPartyUInfo`, `ecdhPartyVInfo`.
|
|
130
193
|
|
|
131
|
-
Returns a Promise resolving to the
|
|
194
|
+
Returns a `Promise<string>` resolving to the JWE token in Compact Serialization format.
|
|
132
195
|
|
|
133
|
-
**Example (
|
|
196
|
+
**Example (PBES2 password-based encryption):**
|
|
134
197
|
|
|
135
198
|
```ts
|
|
136
|
-
import {
|
|
199
|
+
import { encrypt } from "unjwt/jwe";
|
|
137
200
|
|
|
138
|
-
const
|
|
139
|
-
const
|
|
201
|
+
const plaintext = "Secret message for password protection";
|
|
202
|
+
const password = "myVeryStrongPassword123!";
|
|
140
203
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
console.log(token);
|
|
148
|
-
// eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...
|
|
204
|
+
// Fallback to PBES2-HS256+A128KW and A128GCM if no `alg` and `end` are provided
|
|
205
|
+
const jweToken = await encrypt(plaintext, password);
|
|
206
|
+
console.log(jweToken);
|
|
207
|
+
// JWE token string...
|
|
149
208
|
```
|
|
150
209
|
|
|
151
|
-
**Example (
|
|
210
|
+
**Example (A128KW with A128GCM):**
|
|
152
211
|
|
|
153
212
|
```ts
|
|
154
|
-
import {
|
|
213
|
+
import { encrypt } from "unjwt/jwe";
|
|
155
214
|
import { generateKey } from "unjwt/jwk";
|
|
156
215
|
|
|
157
|
-
const payload =
|
|
158
|
-
|
|
159
|
-
const secretJwk = await generateKey("oct", 256, { alg: "HS256" });
|
|
216
|
+
const payload = { data: "sensitive information" };
|
|
217
|
+
const kek = await generateKey("A128KW"); // AES Key Wrap key
|
|
160
218
|
|
|
161
|
-
const
|
|
219
|
+
const jweToken = await encrypt(payload, kek, {
|
|
220
|
+
alg: "A128KW",
|
|
221
|
+
enc: "A128GCM",
|
|
222
|
+
protectedHeader: { kid: "aes-key-1" },
|
|
223
|
+
});
|
|
162
224
|
|
|
163
|
-
console.log(
|
|
164
|
-
//
|
|
225
|
+
console.log(jweToken);
|
|
226
|
+
// eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiYWVzLWtleS0xIn0...
|
|
165
227
|
```
|
|
166
228
|
|
|
167
|
-
#### `
|
|
229
|
+
#### `decrypt(jwe, key, options?)`
|
|
168
230
|
|
|
169
|
-
|
|
231
|
+
Decrypts a JWE token.
|
|
170
232
|
|
|
171
|
-
- `
|
|
172
|
-
- `
|
|
173
|
-
|
|
174
|
-
- A `Uint8Array` containing the raw key bytes.
|
|
175
|
-
- A symmetric JSON Web Key (`JWK`) object (with `kty: "oct"`).
|
|
233
|
+
- `jwe`: The JWE token string.
|
|
234
|
+
- `key`: The Key Decryption Key (KDK) or password (`CryptoKey`, `JWK`, `string`, `Uint8Array`, or a `JWEKeyLookupFunction`).
|
|
235
|
+
A `JWEKeyLookupFunction` has the signature `(header: JWEHeaderParameters) => Promise<CryptoKey | JWK | string | Uint8Array> | CryptoKey | JWK | string | Uint8Array`.
|
|
176
236
|
- `options` (optional):
|
|
177
|
-
- `
|
|
237
|
+
- `algorithms`: Array of allowed JWE Key Management `alg` values.
|
|
238
|
+
- `encryptionAlgorithms`: Array of allowed JWE Content Encryption `enc` values.
|
|
239
|
+
- `critical`: Array of JWE header parameter names that the application understands.
|
|
240
|
+
- `unwrappedKeyAlgorithm`: (For `unwrapKey` internally) Algorithm details for the CEK after unwrapping.
|
|
241
|
+
- `keyUsage`: (For `unwrapKey` internally) Intended usages for the unwrapped CEK.
|
|
178
242
|
|
|
179
|
-
Returns a Promise
|
|
243
|
+
Returns a `Promise<JWEDecryptResult<T>>` which is an object `{ payload: T, protectedHeader: JWEHeaderParameters, cek: Uint8Array, aad: Uint8Array }`.
|
|
244
|
+
The `payload` type `T` can be `JWTClaims` (object) or `string`.
|
|
180
245
|
|
|
181
|
-
**Example (
|
|
246
|
+
**Example (PBES2 password-based decryption):**
|
|
182
247
|
|
|
183
248
|
```ts
|
|
184
|
-
import {
|
|
249
|
+
import { decrypt } from "unjwt/jwe";
|
|
250
|
+
// const jweToken = ...; // From PBES2 encrypt example
|
|
251
|
+
// const password = "myVeryStrongPassword123!";
|
|
185
252
|
|
|
186
|
-
const
|
|
187
|
-
|
|
253
|
+
const { payload } = await decrypt(jweToken, password);
|
|
254
|
+
```
|
|
188
255
|
|
|
189
|
-
|
|
190
|
-
const verifiedString = await verify(token, secret);
|
|
191
|
-
console.log(verifiedString); // {"message":"My important data"}
|
|
256
|
+
**Example (A128KW with A128GCM):**
|
|
192
257
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
258
|
+
```ts
|
|
259
|
+
import { decrypt } from "unjwt/jwe";
|
|
260
|
+
// const jweToken = "eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiYWVzLWtleS0xIn0...";
|
|
261
|
+
// const kek = ...; // The same AES Key Wrap key used for encryption
|
|
262
|
+
|
|
263
|
+
async function decryptData(jweToken: string, kek: CryptoKey) {
|
|
264
|
+
try {
|
|
265
|
+
const { payload, protectedHeader, cek } = await decrypt(jweToken, kek, {
|
|
266
|
+
algorithms: ["A128KW"],
|
|
267
|
+
encryptionAlgorithms: ["A128GCM"],
|
|
268
|
+
});
|
|
269
|
+
console.log("Decrypted Plaintext:", payload);
|
|
270
|
+
console.log("Protected Header:", protectedHeader);
|
|
271
|
+
// console.log("CEK (Content Encryption Key):", cek);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
console.error("Decryption failed:", error);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
196
276
|
```
|
|
197
277
|
|
|
198
|
-
|
|
278
|
+
### JWK (JSON Web Key, [RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517))
|
|
279
|
+
|
|
280
|
+
Utilities for working with JSON Web Keys.
|
|
281
|
+
|
|
282
|
+
#### `generateKey(alg, options?)`
|
|
283
|
+
|
|
284
|
+
Generates a cryptographic key.
|
|
285
|
+
|
|
286
|
+
- `alg`: The JWA algorithm identifier for the key to be generated (e.g., `"HS256"`, `"RS256"`, `"ES256"`, `"A128KW"`, `"A128GCM"`, `"A128CBC-HS256"`).
|
|
287
|
+
- `options` (optional):
|
|
288
|
+
- `toJWK`: If `true`, returns the key(s) in JWK format. Otherwise, returns `CryptoKey`(s) or `Uint8Array` (for composite keys like AES-CBC-HS\*). Default `false`.
|
|
289
|
+
- `extractable`: Boolean, whether the generated `CryptoKey` can be exported. Default `true`.
|
|
290
|
+
- `keyUsage`: Array of `KeyUsage` strings. Defaults are algorithm-specific.
|
|
291
|
+
- `modulusLength`: For RSA keys (e.g., `2048`, `4096`). Default `2048`.
|
|
292
|
+
- `publicExponent`: For RSA keys. Default `new Uint8Array([0x01, 0x00, 0x01])`.
|
|
293
|
+
|
|
294
|
+
Returns a `Promise` resolving to `CryptoKey`, `CryptoKeyPair`, `Uint8Array` (for composite keys), `JWK`, or `{ privateKey: JWK, publicKey: JWK }` depending on `alg` and `options.toJWK`.
|
|
295
|
+
|
|
296
|
+
**Examples:**
|
|
199
297
|
|
|
200
298
|
```ts
|
|
201
|
-
import { verify } from "unjwt/jws";
|
|
202
299
|
import { generateKey } from "unjwt/jwk";
|
|
203
300
|
|
|
204
|
-
|
|
205
|
-
const
|
|
301
|
+
// Generate an HS256 CryptoKey
|
|
302
|
+
const hmacKey = await generateKey("HS256");
|
|
303
|
+
console.log(hmacKey); // CryptoKey
|
|
206
304
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
305
|
+
// Generate an RS256 CryptoKeyPair
|
|
306
|
+
const rsaKeyPair = await generateKey("RS256", { modulusLength: 2048 });
|
|
307
|
+
console.log(rsaKeyPair.publicKey); // CryptoKey
|
|
308
|
+
console.log(rsaKeyPair.privateKey); // CryptoKey
|
|
210
309
|
|
|
211
|
-
|
|
310
|
+
// Generate an ES384 key pair as JWKs
|
|
311
|
+
const ecJwks = await generateKey("ES384", { toJWK: true });
|
|
312
|
+
console.log(ecJwks.publicKey); // JWK
|
|
313
|
+
console.log(ecJwks.privateKey); // JWK
|
|
212
314
|
|
|
213
|
-
|
|
315
|
+
// Generate a composite key for A128CBC-HS256 as Uint8Array
|
|
316
|
+
const aesCbcHsKeyBytes = await generateKey("A128CBC-HS256");
|
|
317
|
+
console.log(aesCbcHsKeyBytes); // Uint8Array (32 bytes: 16 for AES, 16 for HMAC)
|
|
214
318
|
|
|
215
|
-
|
|
319
|
+
// Generate an A256GCM key as a JWK
|
|
320
|
+
const aesGcmJwk = await generateKey("A256GCM", { toJWK: true });
|
|
321
|
+
console.log(aesGcmJwk); // JWK
|
|
322
|
+
```
|
|
216
323
|
|
|
217
|
-
|
|
324
|
+
#### `deriveKeyFromPassword(password, alg, options)`
|
|
218
325
|
|
|
219
|
-
|
|
220
|
-
- `length`(for `"oct"`): Key length in bits (e.g., `128`, `192`, `256`, `512`). Choose a length appropriate for the intended algorithm (e.g., >= 256 for HS256, >= 384 for HS384, >= 512 for HS512).
|
|
221
|
-
- `jwk` (optional, for `"oct"`): Any valid JWK param such as a JWA algorithm identifier (e.g., `HS256`, `A128KW`) to include in the generated JWK.
|
|
326
|
+
Derives a key from a password using PBKDF2 for PBES2 algorithms.
|
|
222
327
|
|
|
223
|
-
|
|
328
|
+
- `password`: The password (`string` or `Uint8Array`).
|
|
329
|
+
- `alg`: The PBES2 algorithm (e.g., `"PBES2-HS256+A128KW"`).
|
|
330
|
+
- `options`:
|
|
331
|
+
- `salt`: The salt (`Uint8Array`, at least 8 octets).
|
|
332
|
+
- `iterations`: The iteration count (positive integer).
|
|
333
|
+
- `toJWK`: If `true`, returns a `JWK_oct`. Otherwise, `CryptoKey`. Default `false`.
|
|
334
|
+
- `extractable`: Boolean for `CryptoKey`. Default `false` unless `toJWK` is true.
|
|
335
|
+
- `keyUsage`: For `CryptoKey`. Default `["wrapKey", "unwrapKey"]`.
|
|
336
|
+
|
|
337
|
+
Returns a `Promise` resolving to `CryptoKey` or `JWK_oct`.
|
|
224
338
|
|
|
225
339
|
**Example:**
|
|
226
340
|
|
|
227
341
|
```ts
|
|
228
|
-
import {
|
|
342
|
+
import { deriveKeyFromPassword } from "unjwt/jwk";
|
|
343
|
+
import { randomBytes, textEncoder } from "unjwt/utils";
|
|
229
344
|
|
|
230
|
-
|
|
231
|
-
const
|
|
345
|
+
const password = "mySecretPassword";
|
|
346
|
+
const salt = randomBytes(16);
|
|
347
|
+
const iterations = 4096;
|
|
232
348
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
349
|
+
const derivedKey = await deriveKeyFromPassword(password, "PBES2-HS384+A192KW", {
|
|
350
|
+
salt,
|
|
351
|
+
iterations,
|
|
352
|
+
});
|
|
353
|
+
console.log(derivedKey); // CryptoKey for AES-KW (192-bit)
|
|
354
|
+
|
|
355
|
+
const derivedJwk = await deriveKeyFromPassword(password, "PBES2-HS512+A256KW", {
|
|
356
|
+
salt,
|
|
357
|
+
iterations,
|
|
358
|
+
toJWK: true,
|
|
359
|
+
});
|
|
360
|
+
console.log(derivedJwk); // JWK_oct { kty: "oct", k: "...", alg: "A256KW" }
|
|
240
361
|
```
|
|
241
362
|
|
|
242
|
-
#### `
|
|
363
|
+
#### `importKey(keyMaterial, alg?)`
|
|
243
364
|
|
|
244
|
-
|
|
365
|
+
Imports a key from various formats. This is a flexible wrapper.
|
|
245
366
|
|
|
246
|
-
- `
|
|
367
|
+
- `keyMaterial`: The key to import. Can be:
|
|
368
|
+
- `CryptoKey`: Returned directly.
|
|
369
|
+
- `Uint8Array`: Returned directly (treated as raw symmetric key bytes).
|
|
370
|
+
- `string`: Encoded to `Uint8Array` and returned.
|
|
371
|
+
- `JWK_oct` (symmetric JWK with `k` property): The `k` value is Base64URL decoded and returned as `Uint8Array`.
|
|
372
|
+
- Other `JWK` types (asymmetric): Imported into a `CryptoKey`.
|
|
373
|
+
- `alg` (optional): The JWA algorithm string. **Required** when importing asymmetric JWKs (e.g., RSA, EC) to provide context for `crypto.subtle.importKey`.
|
|
247
374
|
|
|
248
|
-
Returns a Promise resolving to
|
|
375
|
+
Returns a `Promise` resolving to `CryptoKey` or `Uint8Array`.
|
|
249
376
|
|
|
250
|
-
**
|
|
377
|
+
**Examples:**
|
|
251
378
|
|
|
252
379
|
```ts
|
|
253
|
-
import { importKey
|
|
380
|
+
import { importKey } from "unjwt/jwk";
|
|
381
|
+
import { textEncoder, base64UrlDecode } from "unjwt/utils";
|
|
254
382
|
|
|
255
|
-
//
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
383
|
+
// Import raw symmetric key bytes
|
|
384
|
+
const rawBytes = textEncoder.encode("a-32-byte-long-secret-key-123"); // 32 bytes for AES-256 or HS256
|
|
385
|
+
const symmetricKeyBytes = await importKey(rawBytes);
|
|
386
|
+
console.log(symmetricKeyBytes); // Uint8Array
|
|
387
|
+
|
|
388
|
+
// Import a symmetric JWK (kty: "oct")
|
|
389
|
+
const octJwk = {
|
|
390
|
+
kty: "oct",
|
|
391
|
+
k: "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr0", // Example key
|
|
392
|
+
};
|
|
393
|
+
const importedOctBytes = await importKey(octJwk); // Returns Uint8Array
|
|
394
|
+
console.log(importedOctBytes); // Uint8Array (decoded from k)
|
|
395
|
+
|
|
396
|
+
// Import an RSA Public Key JWK
|
|
397
|
+
const rsaPublicJwk = {
|
|
398
|
+
kty: "RSA",
|
|
399
|
+
n: "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3ok92YEnjsADC4Ue87zwRzH2J-TCwlcQrY3E9gGZJZL2g_2_5QjLhL0gR0xYj04_N4M",
|
|
400
|
+
e: "AQAB",
|
|
401
|
+
alg: "RS256",
|
|
402
|
+
kid: "rsa-pub-1",
|
|
403
|
+
};
|
|
404
|
+
const rsaPublicKey = await importKey(rsaPublicJwk, "RS256"); // 'alg' is crucial here
|
|
405
|
+
console.log(rsaPublicKey); // CryptoKey
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
#### `exportKey(key, jwk?)`
|
|
409
|
+
|
|
410
|
+
Exports a `CryptoKey` to JWK format.
|
|
411
|
+
|
|
412
|
+
- `key`: The `CryptoKey` to export (must be `extractable`).
|
|
413
|
+
- `jwk` (optional): A partial `JWK` object to merge with the exported properties (e.g., to add `kid`, `use`, or override `alg`).
|
|
414
|
+
|
|
415
|
+
Returns a `Promise<JWK>`.
|
|
416
|
+
|
|
417
|
+
**Example:**
|
|
265
418
|
|
|
266
|
-
|
|
267
|
-
|
|
419
|
+
```ts
|
|
420
|
+
import { generateKey, exportKey } from "unjwt/jwk";
|
|
421
|
+
|
|
422
|
+
const { publicKey } = await generateKey("ES256"); // Generates an extractable CryptoKey
|
|
268
423
|
|
|
424
|
+
const jwk = await exportKey(publicKey, { kid: "ec-key-001", use: "sig" });
|
|
269
425
|
console.log(jwk);
|
|
270
426
|
// {
|
|
271
|
-
// kty: '
|
|
272
|
-
//
|
|
273
|
-
//
|
|
274
|
-
//
|
|
275
|
-
// ext: true
|
|
427
|
+
// kty: 'EC',
|
|
428
|
+
// crv: 'P-256',
|
|
429
|
+
// x: '...',
|
|
430
|
+
// y: '...',
|
|
431
|
+
// ext: true,
|
|
432
|
+
// key_ops: [ 'verify' ], // or as per generation
|
|
433
|
+
// kid: 'ec-key-001',
|
|
434
|
+
// use: 'sig'
|
|
276
435
|
// }
|
|
277
436
|
```
|
|
278
437
|
|
|
279
|
-
#### `
|
|
438
|
+
#### `wrapKey(alg, keyToWrap, wrappingKey, options?)`
|
|
280
439
|
|
|
281
|
-
|
|
440
|
+
Wraps a Content Encryption Key (CEK).
|
|
282
441
|
|
|
283
|
-
- `
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
- `algorithm`: The Web Crypto `AlgorithmIdentifier` object specifying the algorithm the key will be used for (e.g., `{ name: "HMAC", hash: "SHA-256" }`, `{ name: "AES-GCM", length: 256 }`).
|
|
288
|
-
- `extractable`: A boolean indicating whether the generated `CryptoKey` can be exported later (using `exportKey` or `crypto.subtle.exportKey`).
|
|
289
|
-
- `keyUsages`: An array of strings indicating the allowed operations for the key (e.g., `["sign", "verify"]`, `["encrypt", "decrypt"]`, `["wrapKey", "unwrapKey"]`).
|
|
442
|
+
- `alg`: The JWA key management algorithm (e.g., `"A128KW"`, `"RSA-OAEP"`).
|
|
443
|
+
- `keyToWrap`: The CEK to wrap (`CryptoKey` or `Uint8Array`).
|
|
444
|
+
- `wrappingKey`: The Key Encryption Key (KEK) (`CryptoKey`, `JWK`, or password `string`/`Uint8Array` for PBES2).
|
|
445
|
+
- `options` (optional): Algorithm-specific options (e.g., `p2s`, `p2c` for PBES2; `iv` for AES-GCMKW).
|
|
290
446
|
|
|
291
|
-
Returns a Promise
|
|
447
|
+
Returns a `Promise<WrapKeyResult>` containing `encryptedKey` and other parameters like `iv`, `tag`, `epk`, `p2s`, `p2c` as needed by the algorithm.
|
|
292
448
|
|
|
293
|
-
**Example (
|
|
449
|
+
**Example (AES Key Wrap):**
|
|
294
450
|
|
|
295
451
|
```ts
|
|
296
|
-
import {
|
|
452
|
+
import { wrapKey, generateKey } from "unjwt/jwk";
|
|
453
|
+
import { randomBytes } from "unjwt/utils";
|
|
297
454
|
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
k: "AyMee--70a4a4xED9qS4sN0KxBas6KTMx7_Q9Gf6nvM", // Example base64url key
|
|
301
|
-
alg: "HS256", // Optional hint, but algorithm param below is definitive
|
|
302
|
-
};
|
|
455
|
+
const cekToWrap = randomBytes(32); // e.g., a 256-bit AES key as Uint8Array
|
|
456
|
+
const kek = await generateKey("A128KW"); // 128-bit AES Key Wrap key
|
|
303
457
|
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
{ name: "HMAC", hash: "SHA-256" }, // Algorithm for the CryptoKey
|
|
307
|
-
false, // Make this key non-extractable
|
|
308
|
-
["verify"], // Allow only verification usage
|
|
309
|
-
);
|
|
310
|
-
|
|
311
|
-
console.log(cryptoKey);
|
|
312
|
-
// CryptoKey { type: 'secret', extractable: false, algorithm: { ... }, usages: [ 'verify' ] }
|
|
458
|
+
const { encryptedKey } = await wrapKey("A128KW", cekToWrap, kek);
|
|
459
|
+
console.log("Wrapped CEK:", encryptedKey); // Uint8Array
|
|
313
460
|
```
|
|
314
461
|
|
|
315
|
-
|
|
462
|
+
#### `unwrapKey(alg, wrappedKey, unwrappingKey, options?)`
|
|
463
|
+
|
|
464
|
+
Unwraps a Content Encryption Key (CEK).
|
|
465
|
+
|
|
466
|
+
- `alg`: The JWA key management algorithm.
|
|
467
|
+
- `wrappedKey`: The encrypted CEK (`Uint8Array`).
|
|
468
|
+
- `unwrappingKey`: The Key Decryption Key (KDK).
|
|
469
|
+
- `options` (optional):
|
|
470
|
+
- `returnAs`: If `false`, returns `Uint8Array`. If `true` (default) or undefined, returns `CryptoKey`.
|
|
471
|
+
- `unwrappedKeyAlgorithm`: `AlgorithmIdentifier` for the imported CEK if `returnAs` is `true`.
|
|
472
|
+
- `keyUsage`: `KeyUsage[]` for the imported CEK if `returnAs` is `true`.
|
|
473
|
+
- `extractable`: Boolean for the imported CEK.
|
|
474
|
+
- Other algorithm-specific options (e.g., `p2s`, `p2c`, `iv`, `tag`, `epk`).
|
|
475
|
+
|
|
476
|
+
Returns a `Promise` resolving to the unwrapped CEK as `CryptoKey` or `Uint8Array`.
|
|
477
|
+
|
|
478
|
+
**Example (AES Key Unwrap):**
|
|
316
479
|
|
|
317
480
|
```ts
|
|
318
|
-
import {
|
|
481
|
+
import { unwrapKey, generateKey } from "unjwt/jwk";
|
|
482
|
+
// const encryptedKey = ...; // From wrapKey example
|
|
483
|
+
// const kdk = ...; // Same KEK used for wrapping
|
|
484
|
+
|
|
485
|
+
async function unwrapMyKey(encryptedKey: Uint8Array, kdk: CryptoKey) {
|
|
486
|
+
const unwrappedCekBytes = await unwrapKey("A128KW", encryptedKey, kdk, {
|
|
487
|
+
returnAs: false, // Get raw bytes
|
|
488
|
+
});
|
|
489
|
+
console.log("Unwrapped CEK (bytes):", unwrappedCekBytes); // Uint8Array
|
|
490
|
+
|
|
491
|
+
const unwrappedCekCryptoKey = await unwrapKey("A128KW", encryptedKey, kdk, {
|
|
492
|
+
returnAs: true, // Get CryptoKey
|
|
493
|
+
unwrappedKeyAlgorithm: { name: "AES-GCM", length: 256 }, // Specify CEK's intended alg
|
|
494
|
+
keyUsage: ["encrypt", "decrypt"],
|
|
495
|
+
});
|
|
496
|
+
console.log("Unwrapped CEK (CryptoKey):", unwrappedCekCryptoKey); // CryptoKey
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
#### `importJWKFromPEM(pem, pemType, alg, importOptions?, jwkExtras?)`
|
|
501
|
+
|
|
502
|
+
Imports a key from a PEM-encoded string and converts it to a JWK.
|
|
503
|
+
|
|
504
|
+
- `pem`: The PEM-encoded string (including `-----BEGIN ...-----` and `-----END ...-----` markers).
|
|
505
|
+
- `pemType`: The type of PEM encoding:
|
|
506
|
+
- `"pkcs8"`: For private keys in PKCS#8 format.
|
|
507
|
+
- `"spki"`: For public keys in SPKI format.
|
|
508
|
+
- `"x509"`: For X.509 certificates (extracts the public key).
|
|
509
|
+
- `alg`: The JWA algorithm identifier (e.g., `"RS256"`, `"ES256"`). This is crucial for `crypto.subtle.importKey` to understand the key's intended algorithm and for setting the `'alg'` field in the resulting JWK.
|
|
510
|
+
- `importOptions` (optional): Options for the underlying `crypto.subtle.importKey` call:
|
|
511
|
+
- `extractable`: Boolean, whether the imported `CryptoKey` should be extractable. Defaults to `true`.
|
|
512
|
+
- `keyUsage`: Array of `KeyUsage` strings for the imported `CryptoKey`.
|
|
513
|
+
- `jwkExtras` (optional): An object containing additional properties to merge into the resulting JWK (e.g., `"kid"`, `"use"`).
|
|
319
514
|
|
|
320
|
-
|
|
515
|
+
Returns a `Promise<JWK>` resolving to the imported key as a JWK.
|
|
321
516
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
517
|
+
**Example:**
|
|
518
|
+
|
|
519
|
+
```ts
|
|
520
|
+
import { importJWKFromPEM } from "unjwt/jwk";
|
|
521
|
+
|
|
522
|
+
const rsaPublicJwk = await importJWKFromPEM(
|
|
523
|
+
provess.env.RSA_PEM_SPKI, // PEM string
|
|
524
|
+
"spki",
|
|
525
|
+
"RS256",
|
|
526
|
+
{ extractable: false },
|
|
527
|
+
{ kid: "my-rsa-key" }, // Additional properties to add to the JWK
|
|
327
528
|
);
|
|
529
|
+
console.log(rsaPublicJwk);
|
|
530
|
+
// {
|
|
531
|
+
// kty: 'RSA',
|
|
532
|
+
// alg: 'RS256',
|
|
533
|
+
// kid: 'my-rsa-key',
|
|
534
|
+
// n: '...',
|
|
535
|
+
// e: 'AQAB',
|
|
536
|
+
// ext: false,
|
|
537
|
+
// key_ops: [ 'verify' ]
|
|
538
|
+
// }
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
#### exportJWKToPEM(jwk, pemFormat, algForCryptoKeyImport?)
|
|
542
|
+
|
|
543
|
+
Exports a JWK to a PEM-encoded string.
|
|
544
|
+
|
|
545
|
+
- jwk: The JWK to export.
|
|
546
|
+
- pemFormat: The desired PEM format:
|
|
547
|
+
- "pkcs8": For private keys in PKCS#8 format.
|
|
548
|
+
- "spki": For public keys in SPKI format.
|
|
549
|
+
- algForCryptoKeyImport (optional): If the JWK does not have an 'alg' property, this algorithm hint is required to correctly convert it to a CryptoKey first. This is only needed if the JWK lacks an alg property.
|
|
550
|
+
|
|
551
|
+
Returns a `Promise<string>` resolving to the PEM-encoded key string.
|
|
328
552
|
|
|
329
|
-
|
|
330
|
-
|
|
553
|
+
Example:
|
|
554
|
+
|
|
555
|
+
```ts
|
|
556
|
+
import { exportJWKToPEM } from "unjwt/jwk";
|
|
557
|
+
import { rsaJWK } from "./keys"; // Assuming you have JWKs in keys.ts
|
|
558
|
+
|
|
559
|
+
const rsaPrivatePem = await exportJWKToPEM(rsaJWK.private, "pkcs8");
|
|
560
|
+
console.log(rsaPrivatePem);
|
|
561
|
+
// -----BEGIN PRIVATE KEY-----
|
|
562
|
+
// MII...
|
|
563
|
+
// -----END PRIVATE KEY-----
|
|
564
|
+
|
|
565
|
+
const rsaPublicSpki = await exportJWKToPEM(
|
|
566
|
+
rsaJWK.public,
|
|
567
|
+
"spki",
|
|
568
|
+
"RS256", // this is required if `rsaJWK.public.alg` is undefined
|
|
569
|
+
);
|
|
570
|
+
console.log(rsaPublicSpki);
|
|
571
|
+
// -----BEGIN PUBLIC KEY-----
|
|
572
|
+
// MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQE...
|
|
573
|
+
// -----END PUBLIC KEY-----
|
|
331
574
|
```
|
|
332
575
|
|
|
576
|
+
### Utility Functions
|
|
577
|
+
|
|
578
|
+
`unjwt/utils` exports several helpful functions:
|
|
579
|
+
|
|
580
|
+
- `base64UrlEncode(data: Uint8Array | string): string`
|
|
581
|
+
- `base64UrlDecode(str?: string, toString?: boolean): Uint8Array | string` (Decodes to string by default, or `Uint8Array` if `toString` is `false`)
|
|
582
|
+
- `randomBytes(length: number): Uint8Array`
|
|
583
|
+
- `textEncoder: TextEncoder`
|
|
584
|
+
- `textDecoder: TextDecoder`
|
|
585
|
+
- Type guards: `isJWK(key)`, `isCryptoKey(key)`, `isCryptoKeyPair(keyPair)`
|
|
586
|
+
|
|
333
587
|
## Development
|
|
334
588
|
|
|
335
589
|
<details>
|
|
@@ -347,6 +601,7 @@ console.log(cryptoKey);
|
|
|
347
601
|
## Credits
|
|
348
602
|
|
|
349
603
|
Originally developed by [Johann Schopplich](https://github.com/johannschopplich/unjwt).
|
|
604
|
+
Heavily inspired by [Filip Skokan's work](https://github.com/panva/jose).
|
|
350
605
|
|
|
351
606
|
## License
|
|
352
607
|
|