@aura-stack/jose 0.2.0 → 0.3.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/dist/{chunk-K5BQTFSO.js → chunk-CXN54JNY.js} +1 -1
- package/dist/{chunk-ZHDED44B.js → chunk-EX3NULRX.js} +1 -1
- package/dist/chunk-SES6WQL3.js +57 -0
- package/dist/{chunk-VPFE27PW.js → chunk-URDLFFH3.js} +1 -1
- package/dist/deriveKey.cjs +30 -6
- package/dist/deriveKey.d.ts +2 -2
- package/dist/deriveKey.js +2 -2
- package/dist/encrypt.cjs +30 -6
- package/dist/encrypt.d.ts +2 -2
- package/dist/encrypt.js +2 -2
- package/dist/index.cjs +45 -13
- package/dist/index.d.ts +2 -153
- package/dist/index.js +14 -7
- package/dist/secret.cjs +32 -4
- package/dist/secret.d.ts +2 -17
- package/dist/secret.js +5 -1
- package/dist/sign.cjs +30 -6
- package/dist/sign.d.ts +173 -2
- package/dist/sign.js +2 -2
- package/package.json +3 -1
- package/dist/chunk-GXM4P5MQ.js +0 -31
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isObject
|
|
3
|
+
} from "./chunk-ZHFHDRQH.js";
|
|
4
|
+
import {
|
|
5
|
+
InvalidSecretError
|
|
6
|
+
} from "./chunk-BMXFAB6Q.js";
|
|
7
|
+
|
|
8
|
+
// src/secret.ts
|
|
9
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
10
|
+
var getEntropy = (secret) => {
|
|
11
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
12
|
+
for (const char of secret) {
|
|
13
|
+
if (!charFreq.has(char)) {
|
|
14
|
+
charFreq.set(char, 0);
|
|
15
|
+
}
|
|
16
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
17
|
+
}
|
|
18
|
+
let entropy = 0;
|
|
19
|
+
const length = secret.length;
|
|
20
|
+
for (const freq of charFreq.values()) {
|
|
21
|
+
const p = freq / length;
|
|
22
|
+
entropy -= p * Math.log2(p);
|
|
23
|
+
}
|
|
24
|
+
return entropy;
|
|
25
|
+
};
|
|
26
|
+
var createSecret = (secret, length = 32) => {
|
|
27
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
28
|
+
if (typeof secret === "string") {
|
|
29
|
+
const byteLength = new TextEncoder().encode(secret).byteLength;
|
|
30
|
+
if (byteLength < length) {
|
|
31
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
32
|
+
}
|
|
33
|
+
const entropy = getEntropy(secret);
|
|
34
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
35
|
+
throw new InvalidSecretError(
|
|
36
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return new Uint8Array(Buffer.from(secret, "utf-8"));
|
|
40
|
+
}
|
|
41
|
+
return secret;
|
|
42
|
+
};
|
|
43
|
+
var getSecrets = (secret) => {
|
|
44
|
+
const jwsSecret = isObject(secret) && "jws" in secret ? secret.jws : secret;
|
|
45
|
+
const jweSecret = isObject(secret) && "jwe" in secret ? secret.jwe : secret;
|
|
46
|
+
return {
|
|
47
|
+
jwsSecret,
|
|
48
|
+
jweSecret
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
MIN_SECRET_ENTROPY_BITS,
|
|
54
|
+
getEntropy,
|
|
55
|
+
createSecret,
|
|
56
|
+
getSecrets
|
|
57
|
+
};
|
package/dist/deriveKey.cjs
CHANGED
|
@@ -24,7 +24,7 @@ __export(deriveKey_exports, {
|
|
|
24
24
|
deriveKey: () => deriveKey
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(deriveKey_exports);
|
|
27
|
-
var
|
|
27
|
+
var import_crypto = require("crypto");
|
|
28
28
|
|
|
29
29
|
// src/errors.ts
|
|
30
30
|
var AuraJoseError = class extends Error {
|
|
@@ -42,11 +42,35 @@ var InvalidSecretError = class extends AuraJoseError {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
// src/secret.ts
|
|
45
|
-
var
|
|
46
|
-
|
|
45
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
46
|
+
var getEntropy = (secret) => {
|
|
47
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
48
|
+
for (const char of secret) {
|
|
49
|
+
if (!charFreq.has(char)) {
|
|
50
|
+
charFreq.set(char, 0);
|
|
51
|
+
}
|
|
52
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
53
|
+
}
|
|
54
|
+
let entropy = 0;
|
|
55
|
+
const length = secret.length;
|
|
56
|
+
for (const freq of charFreq.values()) {
|
|
57
|
+
const p = freq / length;
|
|
58
|
+
entropy -= p * Math.log2(p);
|
|
59
|
+
}
|
|
60
|
+
return entropy;
|
|
61
|
+
};
|
|
62
|
+
var createSecret = (secret, length = 32) => {
|
|
63
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
47
64
|
if (typeof secret === "string") {
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
const byteLength = new TextEncoder().encode(secret).byteLength;
|
|
66
|
+
if (byteLength < length) {
|
|
67
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
68
|
+
}
|
|
69
|
+
const entropy = getEntropy(secret);
|
|
70
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
71
|
+
throw new InvalidSecretError(
|
|
72
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
73
|
+
);
|
|
50
74
|
}
|
|
51
75
|
return new Uint8Array(Buffer.from(secret, "utf-8"));
|
|
52
76
|
}
|
|
@@ -56,7 +80,7 @@ var createSecret = (secret) => {
|
|
|
56
80
|
// src/deriveKey.ts
|
|
57
81
|
var deriveKey = (secret, salt, info, length = 32) => {
|
|
58
82
|
try {
|
|
59
|
-
const key = (0,
|
|
83
|
+
const key = (0, import_crypto.hkdfSync)("SHA256", secret, salt, info, length);
|
|
60
84
|
const derivedKey = Buffer.from(key);
|
|
61
85
|
return {
|
|
62
86
|
key,
|
package/dist/deriveKey.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
export { createDeriveKey, deriveKey } from './
|
|
1
|
+
import 'crypto';
|
|
2
|
+
export { m as createDeriveKey, l as deriveKey } from './sign.js';
|
|
3
3
|
import 'jose';
|
package/dist/deriveKey.js
CHANGED
package/dist/encrypt.cjs
CHANGED
|
@@ -35,7 +35,7 @@ __export(encrypt_exports, {
|
|
|
35
35
|
encryptJWE: () => encryptJWE
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(encrypt_exports);
|
|
38
|
-
var
|
|
38
|
+
var import_crypto = __toESM(require("crypto"), 1);
|
|
39
39
|
var import_jose = require("jose");
|
|
40
40
|
|
|
41
41
|
// src/errors.ts
|
|
@@ -71,11 +71,35 @@ var isFalsy = (value) => {
|
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
// src/secret.ts
|
|
74
|
-
var
|
|
75
|
-
|
|
74
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
75
|
+
var getEntropy = (secret) => {
|
|
76
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
77
|
+
for (const char of secret) {
|
|
78
|
+
if (!charFreq.has(char)) {
|
|
79
|
+
charFreq.set(char, 0);
|
|
80
|
+
}
|
|
81
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
82
|
+
}
|
|
83
|
+
let entropy = 0;
|
|
84
|
+
const length = secret.length;
|
|
85
|
+
for (const freq of charFreq.values()) {
|
|
86
|
+
const p = freq / length;
|
|
87
|
+
entropy -= p * Math.log2(p);
|
|
88
|
+
}
|
|
89
|
+
return entropy;
|
|
90
|
+
};
|
|
91
|
+
var createSecret = (secret, length = 32) => {
|
|
92
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
76
93
|
if (typeof secret === "string") {
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
const byteLength = new TextEncoder().encode(secret).byteLength;
|
|
95
|
+
if (byteLength < length) {
|
|
96
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
97
|
+
}
|
|
98
|
+
const entropy = getEntropy(secret);
|
|
99
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
100
|
+
throw new InvalidSecretError(
|
|
101
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
102
|
+
);
|
|
79
103
|
}
|
|
80
104
|
return new Uint8Array(Buffer.from(secret, "utf-8"));
|
|
81
105
|
}
|
|
@@ -89,7 +113,7 @@ var encryptJWE = async (payload, secret, options) => {
|
|
|
89
113
|
throw new InvalidPayloadError("The payload must be a non-empty string");
|
|
90
114
|
}
|
|
91
115
|
const secretKey = createSecret(secret);
|
|
92
|
-
const jti =
|
|
116
|
+
const jti = import_crypto.default.randomBytes(32).toString("base64url");
|
|
93
117
|
return new import_jose.EncryptJWT({ payload }).setProtectedHeader({ alg: "dir", enc: "A256GCM", typ: "JWT", cty: "JWT" }).setIssuedAt().setNotBefore(options?.nbf ?? "0s").setExpirationTime(options?.exp ?? "15d").setJti(jti).encrypt(secretKey);
|
|
94
118
|
} catch (error) {
|
|
95
119
|
if (isAuraJoseError(error)) {
|
package/dist/encrypt.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { JWTDecryptOptions } from 'jose';
|
|
2
|
-
export { EncryptOptions, EncryptedPayload, createJWE, decryptJWE, encryptJWE } from './
|
|
3
|
-
import '
|
|
2
|
+
export { a as EncryptOptions, E as EncryptedPayload, c as createJWE, d as decryptJWE, e as encryptJWE } from './sign.js';
|
|
3
|
+
import 'crypto';
|
package/dist/encrypt.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -30,22 +30,26 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
MIN_SECRET_ENTROPY_BITS: () => MIN_SECRET_ENTROPY_BITS,
|
|
33
34
|
createDeriveKey: () => createDeriveKey,
|
|
34
35
|
createJWE: () => createJWE,
|
|
35
36
|
createJWS: () => createJWS,
|
|
36
37
|
createJWT: () => createJWT,
|
|
38
|
+
createSecret: () => createSecret,
|
|
37
39
|
decodeJWT: () => decodeJWT,
|
|
38
40
|
decryptJWE: () => decryptJWE,
|
|
39
41
|
deriveKey: () => deriveKey,
|
|
40
42
|
encodeJWT: () => encodeJWT,
|
|
41
43
|
encryptJWE: () => encryptJWE,
|
|
44
|
+
getEntropy: () => getEntropy,
|
|
45
|
+
getSecrets: () => getSecrets,
|
|
42
46
|
signJWS: () => signJWS,
|
|
43
47
|
verifyJWS: () => verifyJWS
|
|
44
48
|
});
|
|
45
49
|
module.exports = __toCommonJS(index_exports);
|
|
46
50
|
|
|
47
51
|
// src/sign.ts
|
|
48
|
-
var
|
|
52
|
+
var import_crypto = __toESM(require("crypto"), 1);
|
|
49
53
|
var import_jose = require("jose");
|
|
50
54
|
|
|
51
55
|
// src/errors.ts
|
|
@@ -99,11 +103,35 @@ var isInvalidPayload = (payload) => {
|
|
|
99
103
|
};
|
|
100
104
|
|
|
101
105
|
// src/secret.ts
|
|
102
|
-
var
|
|
103
|
-
|
|
106
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
107
|
+
var getEntropy = (secret) => {
|
|
108
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
109
|
+
for (const char of secret) {
|
|
110
|
+
if (!charFreq.has(char)) {
|
|
111
|
+
charFreq.set(char, 0);
|
|
112
|
+
}
|
|
113
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
114
|
+
}
|
|
115
|
+
let entropy = 0;
|
|
116
|
+
const length = secret.length;
|
|
117
|
+
for (const freq of charFreq.values()) {
|
|
118
|
+
const p = freq / length;
|
|
119
|
+
entropy -= p * Math.log2(p);
|
|
120
|
+
}
|
|
121
|
+
return entropy;
|
|
122
|
+
};
|
|
123
|
+
var createSecret = (secret, length = 32) => {
|
|
124
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
104
125
|
if (typeof secret === "string") {
|
|
105
|
-
|
|
106
|
-
|
|
126
|
+
const byteLength = new TextEncoder().encode(secret).byteLength;
|
|
127
|
+
if (byteLength < length) {
|
|
128
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
129
|
+
}
|
|
130
|
+
const entropy = getEntropy(secret);
|
|
131
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
132
|
+
throw new InvalidSecretError(
|
|
133
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
134
|
+
);
|
|
107
135
|
}
|
|
108
136
|
return new Uint8Array(Buffer.from(secret, "utf-8"));
|
|
109
137
|
}
|
|
@@ -125,7 +153,7 @@ var signJWS = async (payload, secret) => {
|
|
|
125
153
|
throw new InvalidPayloadError("The payload must be a non-empty object");
|
|
126
154
|
}
|
|
127
155
|
const secretKey = createSecret(secret);
|
|
128
|
-
const jti =
|
|
156
|
+
const jti = import_crypto.default.randomBytes(32).toString("base64url");
|
|
129
157
|
return new import_jose.SignJWT(payload).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuedAt().setNotBefore(payload.nbf ?? "0s").setExpirationTime(payload.exp ?? "15d").setJti(jti).sign(secretKey);
|
|
130
158
|
} catch (error) {
|
|
131
159
|
if (isAuraJoseError(error)) {
|
|
@@ -157,7 +185,7 @@ var createJWS = (secret) => {
|
|
|
157
185
|
};
|
|
158
186
|
|
|
159
187
|
// src/encrypt.ts
|
|
160
|
-
var
|
|
188
|
+
var import_crypto2 = __toESM(require("crypto"), 1);
|
|
161
189
|
var import_jose2 = require("jose");
|
|
162
190
|
var encryptJWE = async (payload, secret, options) => {
|
|
163
191
|
try {
|
|
@@ -165,7 +193,7 @@ var encryptJWE = async (payload, secret, options) => {
|
|
|
165
193
|
throw new InvalidPayloadError("The payload must be a non-empty string");
|
|
166
194
|
}
|
|
167
195
|
const secretKey = createSecret(secret);
|
|
168
|
-
const jti =
|
|
196
|
+
const jti = import_crypto2.default.randomBytes(32).toString("base64url");
|
|
169
197
|
return new import_jose2.EncryptJWT({ payload }).setProtectedHeader({ alg: "dir", enc: "A256GCM", typ: "JWT", cty: "JWT" }).setIssuedAt().setNotBefore(options?.nbf ?? "0s").setExpirationTime(options?.exp ?? "15d").setJti(jti).encrypt(secretKey);
|
|
170
198
|
} catch (error) {
|
|
171
199
|
if (isAuraJoseError(error)) {
|
|
@@ -197,10 +225,10 @@ var createJWE = (secret) => {
|
|
|
197
225
|
};
|
|
198
226
|
|
|
199
227
|
// src/deriveKey.ts
|
|
200
|
-
var
|
|
228
|
+
var import_crypto3 = require("crypto");
|
|
201
229
|
var deriveKey = (secret, salt, info, length = 32) => {
|
|
202
230
|
try {
|
|
203
|
-
const key = (0,
|
|
231
|
+
const key = (0, import_crypto3.hkdfSync)("SHA256", secret, salt, info, length);
|
|
204
232
|
const derivedKey = Buffer.from(key);
|
|
205
233
|
return {
|
|
206
234
|
key,
|
|
@@ -230,13 +258,13 @@ var encodeJWT = async (token, secret) => {
|
|
|
230
258
|
throw new JWTEncodingError("JWT encoding failed", { cause: error });
|
|
231
259
|
}
|
|
232
260
|
};
|
|
233
|
-
var decodeJWT = async (token, secret) => {
|
|
261
|
+
var decodeJWT = async (token, secret, options) => {
|
|
234
262
|
try {
|
|
235
263
|
const { jweSecret, jwsSecret } = getSecrets(secret);
|
|
236
264
|
const { verifyJWS: verifyJWS2 } = createJWS(jwsSecret);
|
|
237
265
|
const { decryptJWE: decryptJWE2 } = createJWE(jweSecret);
|
|
238
|
-
const decrypted = await decryptJWE2(token);
|
|
239
|
-
return await verifyJWS2(decrypted);
|
|
266
|
+
const decrypted = await decryptJWE2(token, options?.jwt);
|
|
267
|
+
return await verifyJWS2(decrypted, options?.jws);
|
|
240
268
|
} catch (error) {
|
|
241
269
|
if (isAuraJoseError(error)) {
|
|
242
270
|
throw error;
|
|
@@ -252,15 +280,19 @@ var createJWT = (secret) => {
|
|
|
252
280
|
};
|
|
253
281
|
// Annotate the CommonJS export names for ESM import in node:
|
|
254
282
|
0 && (module.exports = {
|
|
283
|
+
MIN_SECRET_ENTROPY_BITS,
|
|
255
284
|
createDeriveKey,
|
|
256
285
|
createJWE,
|
|
257
286
|
createJWS,
|
|
258
287
|
createJWT,
|
|
288
|
+
createSecret,
|
|
259
289
|
decodeJWT,
|
|
260
290
|
decryptJWE,
|
|
261
291
|
deriveKey,
|
|
262
292
|
encodeJWT,
|
|
263
293
|
encryptJWE,
|
|
294
|
+
getEntropy,
|
|
295
|
+
getSecrets,
|
|
264
296
|
signJWS,
|
|
265
297
|
verifyJWS
|
|
266
298
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,154 +1,3 @@
|
|
|
1
|
-
import { KeyObject, BinaryLike } from 'node:crypto';
|
|
2
|
-
import { JWTPayload, JWTVerifyOptions, JWTDecryptOptions } from 'jose';
|
|
3
1
|
export { JWTDecryptOptions, JWTVerifyOptions } from 'jose';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Sign a standard JWT token with the following claims:
|
|
7
|
-
* - alg: algorithm used to sign the JWT
|
|
8
|
-
* - typ: type of the token
|
|
9
|
-
* - iat: time at which the JWT was issued
|
|
10
|
-
* - nbf: not before time of the JWT
|
|
11
|
-
* - exp: expiration time of the JWT
|
|
12
|
-
* - jti: unique identifier to avoid collisions
|
|
13
|
-
*
|
|
14
|
-
* @param payload - Payload data information to sign the JWT
|
|
15
|
-
* @param secret - Secret key to sign the JWT (CryptoKey, KeyObject, string or Uint8Array)
|
|
16
|
-
* @returns Signed JWT string
|
|
17
|
-
*/
|
|
18
|
-
declare const signJWS: (payload: JWTPayload, secret: SecretInput) => Promise<string>;
|
|
19
|
-
/**
|
|
20
|
-
* Verify the integrity of a JWT token and return the payload if valid, rejecting
|
|
21
|
-
* tokens that use the "none" algorithm to prevent unsecured tokens.
|
|
22
|
-
*
|
|
23
|
-
* @see https://datatracker.ietf.org/doc/html/rfc7519#section-6 Unsecured JWTs
|
|
24
|
-
* @param token - JWT string to verify
|
|
25
|
-
* @param secret - CryptoKey or KeyObject used to verify the JWT
|
|
26
|
-
* @returns verify and return the payload of the JWT
|
|
27
|
-
*/
|
|
28
|
-
declare const verifyJWS: (token: string, secret: SecretInput, options?: JWTVerifyOptions) => Promise<JWTPayload>;
|
|
29
|
-
/**
|
|
30
|
-
* Create a JWS (JSON Web Signature) signer and verifier. It implements the `signJWS`
|
|
31
|
-
* and `verifyJWS` functions of the module.
|
|
32
|
-
*
|
|
33
|
-
* @param secret - Secret key used for signing and verifying the JWS
|
|
34
|
-
* @returns signJWS and verifyJWS functions
|
|
35
|
-
*/
|
|
36
|
-
declare const createJWS: (secret: SecretInput) => {
|
|
37
|
-
signJWS: (payload: JWTPayload) => Promise<string>;
|
|
38
|
-
verifyJWS: (payload: string, options?: JWTVerifyOptions) => Promise<JWTPayload>;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
interface EncryptedPayload {
|
|
42
|
-
payload: string;
|
|
43
|
-
}
|
|
44
|
-
interface EncryptOptions {
|
|
45
|
-
nbf?: string | number | Date;
|
|
46
|
-
exp?: string | number | Date;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Encrypt a standard JWT token with the following claims:
|
|
50
|
-
* - alg: algorithm used to encrypt the JWT
|
|
51
|
-
* - enc: encryption method used
|
|
52
|
-
* - typ: type of the token
|
|
53
|
-
* - cty: content type of the token
|
|
54
|
-
*
|
|
55
|
-
* @param payload - Payload data information to encrypt the JWT
|
|
56
|
-
* @param secret - Secret key to encrypt the JWT (CryptoKey, KeyObject, string or Uint8Array)
|
|
57
|
-
* @returns Encrypted JWT string
|
|
58
|
-
*/
|
|
59
|
-
declare const encryptJWE: (payload: string, secret: SecretInput, options?: EncryptOptions) => Promise<string>;
|
|
60
|
-
/**
|
|
61
|
-
* Decrypt a JWE token and return the payload if valid.
|
|
62
|
-
*
|
|
63
|
-
* @param token - Encrypted JWT string to decrypt
|
|
64
|
-
* @param secret - Secret key to decrypt the JWT (CryptoKey, KeyObject, string or Uint8Array)
|
|
65
|
-
* @returns Decrypted JWT payload string
|
|
66
|
-
*/
|
|
67
|
-
declare const decryptJWE: (token: string, secret: SecretInput, options?: JWTDecryptOptions) => Promise<string>;
|
|
68
|
-
/**
|
|
69
|
-
* Creates a `JWE (JSON Web Encryption)` encrypter and decrypter. It implements the `encryptJWE`
|
|
70
|
-
* and `decryptJWE` functions of the module.
|
|
71
|
-
*
|
|
72
|
-
* @param secret - Secret key used for encrypting and decrypting the JWE
|
|
73
|
-
* @returns encryptJWE and decryptJWE functions
|
|
74
|
-
*/
|
|
75
|
-
declare const createJWE: (secret: SecretInput) => {
|
|
76
|
-
encryptJWE: (payload: string, options?: EncryptOptions) => Promise<string>;
|
|
77
|
-
decryptJWE: (payload: string, options?: JWTDecryptOptions) => Promise<string>;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @module @aura-stack/jose
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
type SecretInput = KeyObject | Uint8Array | string;
|
|
85
|
-
type DerivedKeyInput = {
|
|
86
|
-
jws: SecretInput;
|
|
87
|
-
jwe: SecretInput;
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Encode a JWT signed and encrypted token. The token first signed using JWS
|
|
91
|
-
* and then encrypted using JWE to ensure both integrity and confidentiality.
|
|
92
|
-
* It implements the `signJWS` and `encryptJWE` functions of the module.
|
|
93
|
-
*
|
|
94
|
-
* Based on the RFC 7519 standard
|
|
95
|
-
* - Official RFC: https://datatracker.ietf.org/doc/html/rfc7519
|
|
96
|
-
* - Nested JWTs should be signed and then encrypted: https://datatracker.ietf.org/doc/html/rfc7519#section-5.2
|
|
97
|
-
* - Ensuring the integrity and confidentiality of the claims: https://datatracker.ietf.org/doc/html/rfc7519#section-11.2
|
|
98
|
-
*
|
|
99
|
-
* @param token - Payload data to encode in the JWT
|
|
100
|
-
* @param secret - Secret key used for both signing and encrypting the JWT
|
|
101
|
-
* @returns Promise resolving to the signed and encrypted JWT string
|
|
102
|
-
*/
|
|
103
|
-
declare const encodeJWT: (token: JWTPayload, secret: SecretInput | DerivedKeyInput) => Promise<string>;
|
|
104
|
-
/**
|
|
105
|
-
* Decode a JWT signed and encrypted token. The token is first decrypted using JWE
|
|
106
|
-
* and then verified using JWS to ensure both confidentiality and integrity. It
|
|
107
|
-
* implements the `decryptJWE` and `verifyJWS` functions of the module.
|
|
108
|
-
*
|
|
109
|
-
* Based on the RFC 7519 standard
|
|
110
|
-
* - Official RFC: https://datatracker.ietf.org/doc/html/rfc7519
|
|
111
|
-
* - Validating a JWT: https://datatracker.ietf.org/doc/html/rfc7519#section-7.2
|
|
112
|
-
* @param token
|
|
113
|
-
* @param secret
|
|
114
|
-
* @returns
|
|
115
|
-
*/
|
|
116
|
-
declare const decodeJWT: (token: string, secret: SecretInput | DerivedKeyInput) => Promise<JWTPayload>;
|
|
117
|
-
/**
|
|
118
|
-
* Create a JWT handler with encode and decode methods to `signJWS/encryptJWE` and `verifyJWS/decryptJWE`
|
|
119
|
-
* JWT tokens. The JWTs are signed and verified using JWS and encrypted and decrypted using JWE. It
|
|
120
|
-
* implements the `signJWS`, `verifyJWS`, `encryptJWE` and `decryptJWE` functions of the module.
|
|
121
|
-
*
|
|
122
|
-
* @param secret - Secret key used for signing, verifying, encrypting and decrypting the JWT
|
|
123
|
-
* @returns JWT handler object with `signJWS/encryptJWE` and `verifyJWS/decryptJWE` methods
|
|
124
|
-
*/
|
|
125
|
-
declare const createJWT: (secret: SecretInput | DerivedKeyInput) => {
|
|
126
|
-
encodeJWT: (payload: JWTPayload) => Promise<string>;
|
|
127
|
-
decodeJWT: (token: string) => Promise<JWTPayload>;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Generate a derived key using HKDF (HMAC-based Extract-and-Expand Key Derivation Function)
|
|
132
|
-
*
|
|
133
|
-
* @param secret Value used as the input keying material
|
|
134
|
-
* @param salt Cryptographic salt
|
|
135
|
-
* @param info Context and application specific information
|
|
136
|
-
* @param length Size of the derived key in bytes (default is 32 bytes)
|
|
137
|
-
* @returns Derived key as Uint8Array and base64 encoded string
|
|
138
|
-
*/
|
|
139
|
-
declare const deriveKey: (secret: SecretInput, salt: BinaryLike, info: string, length?: number) => {
|
|
140
|
-
key: ArrayBuffer;
|
|
141
|
-
derivedKey: Buffer<ArrayBuffer>;
|
|
142
|
-
};
|
|
143
|
-
/**
|
|
144
|
-
* Create a derived key from a given secret.
|
|
145
|
-
*
|
|
146
|
-
* @param secret - The secret as a string or Uint8Array
|
|
147
|
-
* @returns The secret in Uint8Array format
|
|
148
|
-
*/
|
|
149
|
-
declare const createDeriveKey: (secret: SecretInput, salt?: BinaryLike, info?: string, length?: number) => {
|
|
150
|
-
key: ArrayBuffer;
|
|
151
|
-
derivedKey: Buffer<ArrayBuffer>;
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
export { type DerivedKeyInput, type EncryptOptions, type EncryptedPayload, type SecretInput, createDeriveKey, createJWE, createJWS, createJWT, decodeJWT, decryptJWE, deriveKey, encodeJWT, encryptJWE, signJWS, verifyJWS };
|
|
2
|
+
import 'crypto';
|
|
3
|
+
export { h as DecodedJWTPayloadOptions, D as DerivedKeyInput, a as EncryptOptions, E as EncryptedPayload, M as MIN_SECRET_ENTROPY_BITS, S as SecretInput, m as createDeriveKey, c as createJWE, createJWS, k as createJWT, b as createSecret, j as decodeJWT, d as decryptJWE, l as deriveKey, i as encodeJWT, e as encryptJWE, g as getEntropy, f as getSecrets, signJWS, verifyJWS } from './sign.js';
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createDeriveKey,
|
|
3
3
|
deriveKey
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CXN54JNY.js";
|
|
5
5
|
import {
|
|
6
6
|
createJWE,
|
|
7
7
|
decryptJWE,
|
|
8
8
|
encryptJWE
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-URDLFFH3.js";
|
|
10
10
|
import {
|
|
11
11
|
createJWS,
|
|
12
12
|
signJWS,
|
|
13
13
|
verifyJWS
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-EX3NULRX.js";
|
|
15
15
|
import {
|
|
16
|
+
MIN_SECRET_ENTROPY_BITS,
|
|
17
|
+
createSecret,
|
|
18
|
+
getEntropy,
|
|
16
19
|
getSecrets
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-SES6WQL3.js";
|
|
18
21
|
import {
|
|
19
22
|
isAuraJoseError
|
|
20
23
|
} from "./chunk-ZHFHDRQH.js";
|
|
@@ -38,13 +41,13 @@ var encodeJWT = async (token, secret) => {
|
|
|
38
41
|
throw new JWTEncodingError("JWT encoding failed", { cause: error });
|
|
39
42
|
}
|
|
40
43
|
};
|
|
41
|
-
var decodeJWT = async (token, secret) => {
|
|
44
|
+
var decodeJWT = async (token, secret, options) => {
|
|
42
45
|
try {
|
|
43
46
|
const { jweSecret, jwsSecret } = getSecrets(secret);
|
|
44
47
|
const { verifyJWS: verifyJWS2 } = createJWS(jwsSecret);
|
|
45
48
|
const { decryptJWE: decryptJWE2 } = createJWE(jweSecret);
|
|
46
|
-
const decrypted = await decryptJWE2(token);
|
|
47
|
-
return await verifyJWS2(decrypted);
|
|
49
|
+
const decrypted = await decryptJWE2(token, options?.jwt);
|
|
50
|
+
return await verifyJWS2(decrypted, options?.jws);
|
|
48
51
|
} catch (error) {
|
|
49
52
|
if (isAuraJoseError(error)) {
|
|
50
53
|
throw error;
|
|
@@ -59,15 +62,19 @@ var createJWT = (secret) => {
|
|
|
59
62
|
};
|
|
60
63
|
};
|
|
61
64
|
export {
|
|
65
|
+
MIN_SECRET_ENTROPY_BITS,
|
|
62
66
|
createDeriveKey,
|
|
63
67
|
createJWE,
|
|
64
68
|
createJWS,
|
|
65
69
|
createJWT,
|
|
70
|
+
createSecret,
|
|
66
71
|
decodeJWT,
|
|
67
72
|
decryptJWE,
|
|
68
73
|
deriveKey,
|
|
69
74
|
encodeJWT,
|
|
70
75
|
encryptJWE,
|
|
76
|
+
getEntropy,
|
|
77
|
+
getSecrets,
|
|
71
78
|
signJWS,
|
|
72
79
|
verifyJWS
|
|
73
80
|
};
|
package/dist/secret.cjs
CHANGED
|
@@ -20,7 +20,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/secret.ts
|
|
21
21
|
var secret_exports = {};
|
|
22
22
|
__export(secret_exports, {
|
|
23
|
+
MIN_SECRET_ENTROPY_BITS: () => MIN_SECRET_ENTROPY_BITS,
|
|
23
24
|
createSecret: () => createSecret,
|
|
25
|
+
getEntropy: () => getEntropy,
|
|
24
26
|
getSecrets: () => getSecrets
|
|
25
27
|
});
|
|
26
28
|
module.exports = __toCommonJS(secret_exports);
|
|
@@ -46,11 +48,35 @@ var isObject = (value) => {
|
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
// src/secret.ts
|
|
49
|
-
var
|
|
50
|
-
|
|
51
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
52
|
+
var getEntropy = (secret) => {
|
|
53
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
54
|
+
for (const char of secret) {
|
|
55
|
+
if (!charFreq.has(char)) {
|
|
56
|
+
charFreq.set(char, 0);
|
|
57
|
+
}
|
|
58
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
59
|
+
}
|
|
60
|
+
let entropy = 0;
|
|
61
|
+
const length = secret.length;
|
|
62
|
+
for (const freq of charFreq.values()) {
|
|
63
|
+
const p = freq / length;
|
|
64
|
+
entropy -= p * Math.log2(p);
|
|
65
|
+
}
|
|
66
|
+
return entropy;
|
|
67
|
+
};
|
|
68
|
+
var createSecret = (secret, length = 32) => {
|
|
69
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
51
70
|
if (typeof secret === "string") {
|
|
52
|
-
|
|
53
|
-
|
|
71
|
+
const byteLength = new TextEncoder().encode(secret).byteLength;
|
|
72
|
+
if (byteLength < length) {
|
|
73
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
74
|
+
}
|
|
75
|
+
const entropy = getEntropy(secret);
|
|
76
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
77
|
+
throw new InvalidSecretError(
|
|
78
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
79
|
+
);
|
|
54
80
|
}
|
|
55
81
|
return new Uint8Array(Buffer.from(secret, "utf-8"));
|
|
56
82
|
}
|
|
@@ -66,6 +92,8 @@ var getSecrets = (secret) => {
|
|
|
66
92
|
};
|
|
67
93
|
// Annotate the CommonJS export names for ESM import in node:
|
|
68
94
|
0 && (module.exports = {
|
|
95
|
+
MIN_SECRET_ENTROPY_BITS,
|
|
69
96
|
createSecret,
|
|
97
|
+
getEntropy,
|
|
70
98
|
getSecrets
|
|
71
99
|
});
|
package/dist/secret.d.ts
CHANGED
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import 'node:crypto';
|
|
1
|
+
import 'crypto';
|
|
2
|
+
export { M as MIN_SECRET_ENTROPY_BITS, b as createSecret, g as getEntropy, f as getSecrets } from './sign.js';
|
|
4
3
|
import 'jose';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Create a secret in Uint8Array format
|
|
8
|
-
*
|
|
9
|
-
* @param secret - The secret as a string or Uint8Array
|
|
10
|
-
* @returns The secret in Uint8Array format
|
|
11
|
-
*/
|
|
12
|
-
declare const createSecret: (secret: SecretInput) => crypto.KeyObject | Uint8Array<ArrayBufferLike>;
|
|
13
|
-
declare const getSecrets: (secret: SecretInput | DerivedKeyInput) => {
|
|
14
|
-
jwsSecret: SecretInput;
|
|
15
|
-
jweSecret: SecretInput;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export { createSecret, getSecrets };
|
package/dist/secret.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
MIN_SECRET_ENTROPY_BITS,
|
|
2
3
|
createSecret,
|
|
4
|
+
getEntropy,
|
|
3
5
|
getSecrets
|
|
4
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SES6WQL3.js";
|
|
5
7
|
import "./chunk-ZHFHDRQH.js";
|
|
6
8
|
import "./chunk-BMXFAB6Q.js";
|
|
7
9
|
export {
|
|
10
|
+
MIN_SECRET_ENTROPY_BITS,
|
|
8
11
|
createSecret,
|
|
12
|
+
getEntropy,
|
|
9
13
|
getSecrets
|
|
10
14
|
};
|
package/dist/sign.cjs
CHANGED
|
@@ -35,7 +35,7 @@ __export(sign_exports, {
|
|
|
35
35
|
verifyJWS: () => verifyJWS
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(sign_exports);
|
|
38
|
-
var
|
|
38
|
+
var import_crypto = __toESM(require("crypto"), 1);
|
|
39
39
|
var import_jose = require("jose");
|
|
40
40
|
|
|
41
41
|
// src/errors.ts
|
|
@@ -77,11 +77,35 @@ var isInvalidPayload = (payload) => {
|
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
// src/secret.ts
|
|
80
|
-
var
|
|
81
|
-
|
|
80
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
81
|
+
var getEntropy = (secret) => {
|
|
82
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
83
|
+
for (const char of secret) {
|
|
84
|
+
if (!charFreq.has(char)) {
|
|
85
|
+
charFreq.set(char, 0);
|
|
86
|
+
}
|
|
87
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
88
|
+
}
|
|
89
|
+
let entropy = 0;
|
|
90
|
+
const length = secret.length;
|
|
91
|
+
for (const freq of charFreq.values()) {
|
|
92
|
+
const p = freq / length;
|
|
93
|
+
entropy -= p * Math.log2(p);
|
|
94
|
+
}
|
|
95
|
+
return entropy;
|
|
96
|
+
};
|
|
97
|
+
var createSecret = (secret, length = 32) => {
|
|
98
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
82
99
|
if (typeof secret === "string") {
|
|
83
|
-
|
|
84
|
-
|
|
100
|
+
const byteLength = new TextEncoder().encode(secret).byteLength;
|
|
101
|
+
if (byteLength < length) {
|
|
102
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
103
|
+
}
|
|
104
|
+
const entropy = getEntropy(secret);
|
|
105
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
106
|
+
throw new InvalidSecretError(
|
|
107
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
108
|
+
);
|
|
85
109
|
}
|
|
86
110
|
return new Uint8Array(Buffer.from(secret, "utf-8"));
|
|
87
111
|
}
|
|
@@ -95,7 +119,7 @@ var signJWS = async (payload, secret) => {
|
|
|
95
119
|
throw new InvalidPayloadError("The payload must be a non-empty object");
|
|
96
120
|
}
|
|
97
121
|
const secretKey = createSecret(secret);
|
|
98
|
-
const jti =
|
|
122
|
+
const jti = import_crypto.default.randomBytes(32).toString("base64url");
|
|
99
123
|
return new import_jose.SignJWT(payload).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuedAt().setNotBefore(payload.nbf ?? "0s").setExpirationTime(payload.exp ?? "15d").setJti(jti).sign(secretKey);
|
|
100
124
|
} catch (error) {
|
|
101
125
|
if (isAuraJoseError(error)) {
|
package/dist/sign.d.ts
CHANGED
|
@@ -1,3 +1,174 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
import { KeyObject, BinaryLike } from 'crypto';
|
|
3
|
+
import { JWTPayload, JWTVerifyOptions, JWTDecryptOptions } from 'jose';
|
|
1
4
|
export { JWTVerifyOptions } from 'jose';
|
|
2
|
-
|
|
3
|
-
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Sign a standard JWT token with the following claims:
|
|
8
|
+
* - alg: algorithm used to sign the JWT
|
|
9
|
+
* - typ: type of the token
|
|
10
|
+
* - iat: time at which the JWT was issued
|
|
11
|
+
* - nbf: not before time of the JWT
|
|
12
|
+
* - exp: expiration time of the JWT
|
|
13
|
+
* - jti: unique identifier to avoid collisions
|
|
14
|
+
*
|
|
15
|
+
* @param payload - Payload data information to sign the JWT
|
|
16
|
+
* @param secret - Secret key to sign the JWT (CryptoKey, KeyObject, string or Uint8Array)
|
|
17
|
+
* @returns Signed JWT string
|
|
18
|
+
*/
|
|
19
|
+
declare const signJWS: (payload: JWTPayload, secret: SecretInput) => Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Verify the integrity of a JWT token and return the payload if valid, rejecting
|
|
22
|
+
* tokens that use the "none" algorithm to prevent unsecured tokens.
|
|
23
|
+
*
|
|
24
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7519#section-6 Unsecured JWTs
|
|
25
|
+
* @param token - JWT string to verify
|
|
26
|
+
* @param secret - CryptoKey or KeyObject used to verify the JWT
|
|
27
|
+
* @param options - Additional JWT verification options
|
|
28
|
+
* @returns verify and return the payload of the JWT
|
|
29
|
+
*/
|
|
30
|
+
declare const verifyJWS: (token: string, secret: SecretInput, options?: JWTVerifyOptions) => Promise<JWTPayload>;
|
|
31
|
+
/**
|
|
32
|
+
* Create a JWS (JSON Web Signature) signer and verifier. It implements the `signJWS`
|
|
33
|
+
* and `verifyJWS` functions of the module.
|
|
34
|
+
*
|
|
35
|
+
* @param secret - Secret key used for signing and verifying the JWS
|
|
36
|
+
* @returns signJWS and verifyJWS functions
|
|
37
|
+
*/
|
|
38
|
+
declare const createJWS: (secret: SecretInput) => {
|
|
39
|
+
signJWS: (payload: JWTPayload) => Promise<string>;
|
|
40
|
+
verifyJWS: (payload: string, options?: JWTVerifyOptions) => Promise<JWTPayload>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
interface EncryptedPayload {
|
|
44
|
+
payload: string;
|
|
45
|
+
}
|
|
46
|
+
interface EncryptOptions {
|
|
47
|
+
nbf?: string | number | Date;
|
|
48
|
+
exp?: string | number | Date;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Encrypt a standard JWT token with the following claims:
|
|
52
|
+
* - alg: algorithm used to encrypt the JWT
|
|
53
|
+
* - enc: encryption method used
|
|
54
|
+
* - typ: type of the token
|
|
55
|
+
* - cty: content type of the token
|
|
56
|
+
*
|
|
57
|
+
* @param payload - Payload data information to encrypt the JWT
|
|
58
|
+
* @param secret - Secret key to encrypt the JWT (CryptoKey, KeyObject, string or Uint8Array)
|
|
59
|
+
* @returns Encrypted JWT string
|
|
60
|
+
*/
|
|
61
|
+
declare const encryptJWE: (payload: string, secret: SecretInput, options?: EncryptOptions) => Promise<string>;
|
|
62
|
+
/**
|
|
63
|
+
* Decrypt a JWE token and return the payload if valid.
|
|
64
|
+
*
|
|
65
|
+
* @param token - Encrypted JWT string to decrypt
|
|
66
|
+
* @param secret - Secret key to decrypt the JWT (CryptoKey, KeyObject, string or Uint8Array)
|
|
67
|
+
* @returns Decrypted JWT payload string
|
|
68
|
+
*/
|
|
69
|
+
declare const decryptJWE: (token: string, secret: SecretInput, options?: JWTDecryptOptions) => Promise<string>;
|
|
70
|
+
/**
|
|
71
|
+
* Creates a `JWE (JSON Web Encryption)` encrypter and decrypter. It implements the `encryptJWE`
|
|
72
|
+
* and `decryptJWE` functions of the module.
|
|
73
|
+
*
|
|
74
|
+
* @param secret - Secret key used for encrypting and decrypting the JWE
|
|
75
|
+
* @returns encryptJWE and decryptJWE functions
|
|
76
|
+
*/
|
|
77
|
+
declare const createJWE: (secret: SecretInput) => {
|
|
78
|
+
encryptJWE: (payload: string, options?: EncryptOptions) => Promise<string>;
|
|
79
|
+
decryptJWE: (payload: string, options?: JWTDecryptOptions) => Promise<string>;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
declare const MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
83
|
+
declare const getEntropy: (secret: string) => number;
|
|
84
|
+
/**
|
|
85
|
+
* Create a secret in Uint8Array format
|
|
86
|
+
*
|
|
87
|
+
* @param secret - The secret as a string or Uint8Array
|
|
88
|
+
* @returns The secret in Uint8Array format
|
|
89
|
+
*/
|
|
90
|
+
declare const createSecret: (secret: SecretInput, length?: number) => crypto.KeyObject | Uint8Array<ArrayBufferLike>;
|
|
91
|
+
declare const getSecrets: (secret: SecretInput | DerivedKeyInput) => {
|
|
92
|
+
jwsSecret: SecretInput;
|
|
93
|
+
jweSecret: SecretInput;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @module @aura-stack/jose
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
type SecretInput = KeyObject | Uint8Array | string;
|
|
101
|
+
type DerivedKeyInput = {
|
|
102
|
+
jws: SecretInput;
|
|
103
|
+
jwe: SecretInput;
|
|
104
|
+
};
|
|
105
|
+
type DecodedJWTPayloadOptions = {
|
|
106
|
+
jws: JWTVerifyOptions;
|
|
107
|
+
jwt: JWTDecryptOptions;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Encode a JWT signed and encrypted token. The token first signed using JWS
|
|
111
|
+
* and then encrypted using JWE to ensure both integrity and confidentiality.
|
|
112
|
+
* It implements the `signJWS` and `encryptJWE` functions of the module.
|
|
113
|
+
*
|
|
114
|
+
* Based on the RFC 7519 standard
|
|
115
|
+
* - Official RFC: https://datatracker.ietf.org/doc/html/rfc7519
|
|
116
|
+
* - Nested JWTs should be signed and then encrypted: https://datatracker.ietf.org/doc/html/rfc7519#section-5.2
|
|
117
|
+
* - Ensuring the integrity and confidentiality of the claims: https://datatracker.ietf.org/doc/html/rfc7519#section-11.2
|
|
118
|
+
*
|
|
119
|
+
* @param token - Payload data to encode in the JWT
|
|
120
|
+
* @param secret - Secret key used for both signing and encrypting the JWT
|
|
121
|
+
* @returns Promise resolving to the signed and encrypted JWT string
|
|
122
|
+
*/
|
|
123
|
+
declare const encodeJWT: (token: JWTPayload, secret: SecretInput | DerivedKeyInput) => Promise<string>;
|
|
124
|
+
/**
|
|
125
|
+
* Decode a JWT signed and encrypted token. The token is first decrypted using JWE
|
|
126
|
+
* and then verified using JWS to ensure both confidentiality and integrity. It
|
|
127
|
+
* implements the `decryptJWE` and `verifyJWS` functions of the module.
|
|
128
|
+
*
|
|
129
|
+
* Based on the RFC 7519 standard
|
|
130
|
+
* - Official RFC: https://datatracker.ietf.org/doc/html/rfc7519
|
|
131
|
+
* - Validating a JWT: https://datatracker.ietf.org/doc/html/rfc7519#section-7.2
|
|
132
|
+
* @param token
|
|
133
|
+
* @param secret
|
|
134
|
+
* @returns
|
|
135
|
+
*/
|
|
136
|
+
declare const decodeJWT: (token: string, secret: SecretInput | DerivedKeyInput, options?: DecodedJWTPayloadOptions) => Promise<JWTPayload>;
|
|
137
|
+
/**
|
|
138
|
+
* Create a JWT handler with encode and decode methods to `signJWS/encryptJWE` and `verifyJWS/decryptJWE`
|
|
139
|
+
* JWT tokens. The JWTs are signed and verified using JWS and encrypted and decrypted using JWE. It
|
|
140
|
+
* implements the `signJWS`, `verifyJWS`, `encryptJWE` and `decryptJWE` functions of the module.
|
|
141
|
+
*
|
|
142
|
+
* @param secret - Secret key used for signing, verifying, encrypting and decrypting the JWT
|
|
143
|
+
* @returns JWT handler object with `signJWS/encryptJWE` and `verifyJWS/decryptJWE` methods
|
|
144
|
+
*/
|
|
145
|
+
declare const createJWT: (secret: SecretInput | DerivedKeyInput) => {
|
|
146
|
+
encodeJWT: (payload: JWTPayload) => Promise<string>;
|
|
147
|
+
decodeJWT: (token: string) => Promise<JWTPayload>;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate a derived key using HKDF (HMAC-based Extract-and-Expand Key Derivation Function)
|
|
152
|
+
*
|
|
153
|
+
* @param secret Value used as the input keying material
|
|
154
|
+
* @param salt Cryptographic salt
|
|
155
|
+
* @param info Context and application specific information
|
|
156
|
+
* @param length Size of the derived key in bytes (default is 32 bytes)
|
|
157
|
+
* @returns Derived key as Uint8Array and base64 encoded string
|
|
158
|
+
*/
|
|
159
|
+
declare const deriveKey: (secret: SecretInput, salt: BinaryLike, info: string, length?: number) => {
|
|
160
|
+
key: ArrayBuffer;
|
|
161
|
+
derivedKey: Buffer<ArrayBuffer>;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Create a derived key from a given secret.
|
|
165
|
+
*
|
|
166
|
+
* @param secret - The secret as a string or Uint8Array
|
|
167
|
+
* @returns The secret in Uint8Array format
|
|
168
|
+
*/
|
|
169
|
+
declare const createDeriveKey: (secret: SecretInput, salt?: BinaryLike, info?: string, length?: number) => {
|
|
170
|
+
key: ArrayBuffer;
|
|
171
|
+
derivedKey: Buffer<ArrayBuffer>;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export { type DerivedKeyInput as D, type EncryptedPayload as E, MIN_SECRET_ENTROPY_BITS as M, type SecretInput as S, type EncryptOptions as a, createSecret as b, createJWE as c, createJWS, decryptJWE as d, encryptJWE as e, getSecrets as f, getEntropy as g, type DecodedJWTPayloadOptions as h, encodeJWT as i, decodeJWT as j, createJWT as k, deriveKey as l, createDeriveKey as m, signJWS, verifyJWS };
|
package/dist/sign.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aura-stack/jose",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "JOSE utilities for @aura-stack/auth",
|
|
@@ -57,6 +57,8 @@
|
|
|
57
57
|
"jose": "^6.1.2"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
+
"@types/node": "^24.9.2",
|
|
61
|
+
"typescript": "^5.9.2",
|
|
60
62
|
"@aura-stack/tsconfig": "0.0.0",
|
|
61
63
|
"@aura-stack/tsup-config": "0.0.0"
|
|
62
64
|
},
|
package/dist/chunk-GXM4P5MQ.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isObject
|
|
3
|
-
} from "./chunk-ZHFHDRQH.js";
|
|
4
|
-
import {
|
|
5
|
-
InvalidSecretError
|
|
6
|
-
} from "./chunk-BMXFAB6Q.js";
|
|
7
|
-
|
|
8
|
-
// src/secret.ts
|
|
9
|
-
var createSecret = (secret) => {
|
|
10
|
-
if (secret === void 0) throw new InvalidSecretError("Secret is required");
|
|
11
|
-
if (typeof secret === "string") {
|
|
12
|
-
if (new TextEncoder().encode(secret).byteLength < 32) {
|
|
13
|
-
throw new InvalidSecretError("Secret string must be at least 32 characters long");
|
|
14
|
-
}
|
|
15
|
-
return new Uint8Array(Buffer.from(secret, "utf-8"));
|
|
16
|
-
}
|
|
17
|
-
return secret;
|
|
18
|
-
};
|
|
19
|
-
var getSecrets = (secret) => {
|
|
20
|
-
const jwsSecret = isObject(secret) && "jws" in secret ? secret.jws : secret;
|
|
21
|
-
const jweSecret = isObject(secret) && "jwe" in secret ? secret.jwe : secret;
|
|
22
|
-
return {
|
|
23
|
-
jwsSecret,
|
|
24
|
-
jweSecret
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export {
|
|
29
|
-
createSecret,
|
|
30
|
-
getSecrets
|
|
31
|
-
};
|