@aura-stack/jose 0.2.0 → 0.4.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/assert.js +2 -2
- package/dist/chunk-FCUM7BTG.js +67 -0
- package/dist/{chunk-ZHFHDRQH.js → chunk-MWFJ4CA5.js} +1 -1
- package/dist/{chunk-BMXFAB6Q.js → chunk-NGBYHSRN.js} +5 -1
- package/dist/chunk-OG4QRUXH.js +47 -0
- package/dist/{chunk-VPFE27PW.js → chunk-Q2LAK6W2.js} +9 -7
- package/dist/chunk-RQFUZSWH.js +19 -0
- package/dist/{chunk-ZHDED44B.js → chunk-WXGX6PJ5.js} +9 -7
- package/dist/crypto.cjs +46 -0
- package/dist/crypto.d.ts +19 -0
- package/dist/crypto.js +12 -0
- package/dist/deriveKey.cjs +74 -17
- package/dist/deriveKey.d.ts +2 -2
- package/dist/deriveKey.js +5 -4
- package/dist/encrypt.cjs +46 -19
- package/dist/encrypt.d.ts +2 -2
- package/dist/encrypt.js +5 -4
- package/dist/errors.cjs +7 -2
- package/dist/errors.d.ts +4 -1
- package/dist/errors.js +5 -3
- package/dist/index.cjs +102 -38
- package/dist/index.d.ts +2 -153
- package/dist/index.js +32 -15
- package/dist/secret.cjs +45 -6
- package/dist/secret.d.ts +2 -17
- package/dist/secret.js +8 -3
- package/dist/sign.cjs +46 -19
- package/dist/sign.d.ts +185 -2
- package/dist/sign.js +5 -4
- package/package.json +7 -1
- package/dist/chunk-GXM4P5MQ.js +0 -31
- package/dist/chunk-K5BQTFSO.js +0 -27
package/dist/assert.js
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isObject
|
|
3
|
+
} from "./chunk-MWFJ4CA5.js";
|
|
4
|
+
import {
|
|
5
|
+
encoder
|
|
6
|
+
} from "./chunk-RQFUZSWH.js";
|
|
7
|
+
import {
|
|
8
|
+
InvalidSecretError
|
|
9
|
+
} from "./chunk-NGBYHSRN.js";
|
|
10
|
+
|
|
11
|
+
// src/secret.ts
|
|
12
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
13
|
+
var getEntropy = (secret) => {
|
|
14
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
15
|
+
for (const char of secret) {
|
|
16
|
+
if (!charFreq.has(char)) {
|
|
17
|
+
charFreq.set(char, 0);
|
|
18
|
+
}
|
|
19
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
20
|
+
}
|
|
21
|
+
let entropy = 0;
|
|
22
|
+
const length = secret.length;
|
|
23
|
+
for (const freq of charFreq.values()) {
|
|
24
|
+
const p = freq / length;
|
|
25
|
+
entropy -= p * Math.log2(p);
|
|
26
|
+
}
|
|
27
|
+
return entropy;
|
|
28
|
+
};
|
|
29
|
+
var createSecret = (secret, length = 32) => {
|
|
30
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
31
|
+
if (typeof secret === "string") {
|
|
32
|
+
const encoded = encoder.encode(secret);
|
|
33
|
+
const byteLength = encoded.byteLength;
|
|
34
|
+
if (byteLength < length) {
|
|
35
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
36
|
+
}
|
|
37
|
+
const entropy = getEntropy(secret);
|
|
38
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
39
|
+
throw new InvalidSecretError(
|
|
40
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return encoded;
|
|
44
|
+
}
|
|
45
|
+
if (secret instanceof CryptoKey || secret instanceof Uint8Array) {
|
|
46
|
+
if (secret instanceof Uint8Array && secret.byteLength < length) {
|
|
47
|
+
throw new InvalidSecretError(`Secret must be at least ${length} bytes long`);
|
|
48
|
+
}
|
|
49
|
+
return secret;
|
|
50
|
+
}
|
|
51
|
+
throw new InvalidSecretError("Secret must be a string, Uint8Array, or CryptoKey");
|
|
52
|
+
};
|
|
53
|
+
var getSecrets = (secret) => {
|
|
54
|
+
const jwsSecret = isObject(secret) && "jws" in secret ? secret.jws : secret;
|
|
55
|
+
const jweSecret = isObject(secret) && "jwe" in secret ? secret.jwe : secret;
|
|
56
|
+
return {
|
|
57
|
+
jwsSecret,
|
|
58
|
+
jweSecret
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export {
|
|
63
|
+
MIN_SECRET_ENTROPY_BITS,
|
|
64
|
+
getEntropy,
|
|
65
|
+
createSecret,
|
|
66
|
+
getSecrets
|
|
67
|
+
};
|
|
@@ -33,6 +33,9 @@ var JWEEncryptionError = class extends AuraJoseError {
|
|
|
33
33
|
var InvalidSecretError = class extends AuraJoseError {
|
|
34
34
|
static code = "ERR_INVALID_SECRET";
|
|
35
35
|
};
|
|
36
|
+
var KeyDerivationError = class extends AuraJoseError {
|
|
37
|
+
static code = "ERR_KEY_DERIVATION";
|
|
38
|
+
};
|
|
36
39
|
|
|
37
40
|
export {
|
|
38
41
|
AuraJoseError,
|
|
@@ -43,5 +46,6 @@ export {
|
|
|
43
46
|
JWSSigningError,
|
|
44
47
|
JWEDecryptionError,
|
|
45
48
|
JWEEncryptionError,
|
|
46
|
-
InvalidSecretError
|
|
49
|
+
InvalidSecretError,
|
|
50
|
+
KeyDerivationError
|
|
47
51
|
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSecret
|
|
3
|
+
} from "./chunk-FCUM7BTG.js";
|
|
4
|
+
import {
|
|
5
|
+
encoder,
|
|
6
|
+
getSubtleCrypto
|
|
7
|
+
} from "./chunk-RQFUZSWH.js";
|
|
8
|
+
import {
|
|
9
|
+
KeyDerivationError
|
|
10
|
+
} from "./chunk-NGBYHSRN.js";
|
|
11
|
+
|
|
12
|
+
// src/deriveKey.ts
|
|
13
|
+
var deriveKey = async (secret, salt, info, length = 32) => {
|
|
14
|
+
try {
|
|
15
|
+
const subtle = getSubtleCrypto();
|
|
16
|
+
const secretBuffer = secret.buffer.slice(secret.byteOffset, secret.byteOffset + secret.byteLength);
|
|
17
|
+
const baseKey = await subtle.importKey("raw", secretBuffer, "HKDF", false, ["deriveBits"]);
|
|
18
|
+
const saltBuffer = typeof salt === "string" ? encoder.encode(salt) : salt;
|
|
19
|
+
const infoBuffer = typeof info === "string" ? encoder.encode(info) : info;
|
|
20
|
+
const derivedBits = await subtle.deriveBits(
|
|
21
|
+
{
|
|
22
|
+
name: "HKDF",
|
|
23
|
+
hash: "SHA-256",
|
|
24
|
+
salt: saltBuffer,
|
|
25
|
+
info: infoBuffer
|
|
26
|
+
},
|
|
27
|
+
baseKey,
|
|
28
|
+
length << 3
|
|
29
|
+
);
|
|
30
|
+
return new Uint8Array(derivedBits);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
throw new KeyDerivationError("Failed to create a derived key (HKDF)", { cause: error });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var createDeriveKey = async (secret, salt, info, length = 32) => {
|
|
36
|
+
const secretKey = createSecret(secret);
|
|
37
|
+
if (secretKey instanceof CryptoKey) {
|
|
38
|
+
throw new KeyDerivationError("Cannot derive key from CryptoKey. Use Uint8Array or string secret instead.");
|
|
39
|
+
}
|
|
40
|
+
const key = await deriveKey(secretKey, salt ?? "Aura Jose secret salt", info ?? "Aura Jose secret derivation", length);
|
|
41
|
+
return key;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
deriveKey,
|
|
46
|
+
createDeriveKey
|
|
47
|
+
};
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSecret
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FCUM7BTG.js";
|
|
4
4
|
import {
|
|
5
5
|
isAuraJoseError,
|
|
6
6
|
isFalsy
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MWFJ4CA5.js";
|
|
8
|
+
import {
|
|
9
|
+
getRandomBytes
|
|
10
|
+
} from "./chunk-RQFUZSWH.js";
|
|
8
11
|
import {
|
|
9
12
|
InvalidPayloadError,
|
|
10
13
|
JWEDecryptionError,
|
|
11
14
|
JWEEncryptionError
|
|
12
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-NGBYHSRN.js";
|
|
13
16
|
|
|
14
17
|
// src/encrypt.ts
|
|
15
|
-
import
|
|
16
|
-
import { EncryptJWT, jwtDecrypt } from "jose";
|
|
18
|
+
import { base64url, EncryptJWT, jwtDecrypt } from "jose";
|
|
17
19
|
var encryptJWE = async (payload, secret, options) => {
|
|
18
20
|
try {
|
|
19
21
|
if (isFalsy(payload)) {
|
|
20
22
|
throw new InvalidPayloadError("The payload must be a non-empty string");
|
|
21
23
|
}
|
|
22
24
|
const secretKey = createSecret(secret);
|
|
23
|
-
const jti =
|
|
24
|
-
return new EncryptJWT({ payload }).setProtectedHeader({ alg: "dir", enc: "A256GCM", typ: "JWT", cty: "JWT" }).setIssuedAt().setNotBefore(options?.nbf ?? "0s").setExpirationTime(options?.exp ?? "15d").setJti(jti).encrypt(secretKey);
|
|
25
|
+
const jti = base64url.encode(getRandomBytes(32));
|
|
26
|
+
return await new EncryptJWT({ payload }).setProtectedHeader({ alg: "dir", enc: "A256GCM", typ: "JWT", cty: "JWT" }).setIssuedAt().setNotBefore(options?.nbf ?? "0s").setExpirationTime(options?.exp ?? "15d").setJti(jti).encrypt(secretKey);
|
|
25
27
|
} catch (error) {
|
|
26
28
|
if (isAuraJoseError(error)) {
|
|
27
29
|
throw error;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/crypto.ts
|
|
2
|
+
var encoder = new TextEncoder();
|
|
3
|
+
var decoder = new TextDecoder();
|
|
4
|
+
var getRandomBytes = (size) => {
|
|
5
|
+
return globalThis.crypto.getRandomValues(new Uint8Array(size));
|
|
6
|
+
};
|
|
7
|
+
var getSubtleCrypto = () => {
|
|
8
|
+
if (globalThis.crypto?.subtle) {
|
|
9
|
+
return globalThis.crypto.subtle;
|
|
10
|
+
}
|
|
11
|
+
throw new Error("SubtleCrypto is not available in this runtime");
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
encoder,
|
|
16
|
+
decoder,
|
|
17
|
+
getRandomBytes,
|
|
18
|
+
getSubtleCrypto
|
|
19
|
+
};
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSecret
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FCUM7BTG.js";
|
|
4
4
|
import {
|
|
5
5
|
isAuraJoseError,
|
|
6
6
|
isFalsy,
|
|
7
7
|
isInvalidPayload
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-MWFJ4CA5.js";
|
|
9
|
+
import {
|
|
10
|
+
getRandomBytes
|
|
11
|
+
} from "./chunk-RQFUZSWH.js";
|
|
9
12
|
import {
|
|
10
13
|
InvalidPayloadError,
|
|
11
14
|
JWSSigningError,
|
|
12
15
|
JWSVerificationError
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-NGBYHSRN.js";
|
|
14
17
|
|
|
15
18
|
// src/sign.ts
|
|
16
|
-
import
|
|
17
|
-
import { jwtVerify, SignJWT } from "jose";
|
|
19
|
+
import { base64url, jwtVerify, SignJWT } from "jose";
|
|
18
20
|
var signJWS = async (payload, secret) => {
|
|
19
21
|
try {
|
|
20
22
|
if (isInvalidPayload(payload)) {
|
|
21
23
|
throw new InvalidPayloadError("The payload must be a non-empty object");
|
|
22
24
|
}
|
|
23
25
|
const secretKey = createSecret(secret);
|
|
24
|
-
const jti =
|
|
25
|
-
return new SignJWT(payload).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuedAt().setNotBefore(payload.nbf ?? "0s").setExpirationTime(payload.exp ?? "15d").setJti(jti).sign(secretKey);
|
|
26
|
+
const jti = base64url.encode(getRandomBytes(32));
|
|
27
|
+
return await new SignJWT(payload).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuedAt().setNotBefore(payload.nbf ?? "0s").setExpirationTime(payload.exp ?? "15d").setJti(jti).sign(secretKey);
|
|
26
28
|
} catch (error) {
|
|
27
29
|
if (isAuraJoseError(error)) {
|
|
28
30
|
throw error;
|
package/dist/crypto.cjs
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/crypto.ts
|
|
21
|
+
var crypto_exports = {};
|
|
22
|
+
__export(crypto_exports, {
|
|
23
|
+
decoder: () => decoder,
|
|
24
|
+
encoder: () => encoder,
|
|
25
|
+
getRandomBytes: () => getRandomBytes,
|
|
26
|
+
getSubtleCrypto: () => getSubtleCrypto
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(crypto_exports);
|
|
29
|
+
var encoder = new TextEncoder();
|
|
30
|
+
var decoder = new TextDecoder();
|
|
31
|
+
var getRandomBytes = (size) => {
|
|
32
|
+
return globalThis.crypto.getRandomValues(new Uint8Array(size));
|
|
33
|
+
};
|
|
34
|
+
var getSubtleCrypto = () => {
|
|
35
|
+
if (globalThis.crypto?.subtle) {
|
|
36
|
+
return globalThis.crypto.subtle;
|
|
37
|
+
}
|
|
38
|
+
throw new Error("SubtleCrypto is not available in this runtime");
|
|
39
|
+
};
|
|
40
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
41
|
+
0 && (module.exports = {
|
|
42
|
+
decoder,
|
|
43
|
+
encoder,
|
|
44
|
+
getRandomBytes,
|
|
45
|
+
getSubtleCrypto
|
|
46
|
+
});
|
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare const encoder: TextEncoder;
|
|
2
|
+
declare const decoder: TextDecoder;
|
|
3
|
+
/**
|
|
4
|
+
* Generate random bytes using the Web Crypto API
|
|
5
|
+
* Works in Node.js 15+, Deno, Bun, and browsers
|
|
6
|
+
*
|
|
7
|
+
* @param size - Number of random bytes to generate with a max value of 65 bytes
|
|
8
|
+
* @returns Uint8Array containing random bytes
|
|
9
|
+
*/
|
|
10
|
+
declare const getRandomBytes: (size: number) => Uint8Array;
|
|
11
|
+
/**
|
|
12
|
+
* Get a unified source of entropy - prefers crypto.subtle but falls back if needed
|
|
13
|
+
* All modern runtimes support globalThis.crypto.subtle
|
|
14
|
+
*
|
|
15
|
+
* @returns SubtleCrypto interface for cryptographic operations
|
|
16
|
+
*/
|
|
17
|
+
declare const getSubtleCrypto: () => SubtleCrypto;
|
|
18
|
+
|
|
19
|
+
export { decoder, encoder, getRandomBytes, getSubtleCrypto };
|
package/dist/crypto.js
ADDED
package/dist/deriveKey.cjs
CHANGED
|
@@ -24,7 +24,6 @@ __export(deriveKey_exports, {
|
|
|
24
24
|
deriveKey: () => deriveKey
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(deriveKey_exports);
|
|
27
|
-
var import_node_crypto = require("crypto");
|
|
28
27
|
|
|
29
28
|
// src/errors.ts
|
|
30
29
|
var AuraJoseError = class extends Error {
|
|
@@ -40,35 +39,93 @@ var AuraJoseError = class extends Error {
|
|
|
40
39
|
var InvalidSecretError = class extends AuraJoseError {
|
|
41
40
|
static code = "ERR_INVALID_SECRET";
|
|
42
41
|
};
|
|
42
|
+
var KeyDerivationError = class extends AuraJoseError {
|
|
43
|
+
static code = "ERR_KEY_DERIVATION";
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// src/crypto.ts
|
|
47
|
+
var encoder = new TextEncoder();
|
|
48
|
+
var decoder = new TextDecoder();
|
|
49
|
+
var getSubtleCrypto = () => {
|
|
50
|
+
if (globalThis.crypto?.subtle) {
|
|
51
|
+
return globalThis.crypto.subtle;
|
|
52
|
+
}
|
|
53
|
+
throw new Error("SubtleCrypto is not available in this runtime");
|
|
54
|
+
};
|
|
43
55
|
|
|
44
56
|
// src/secret.ts
|
|
45
|
-
var
|
|
46
|
-
|
|
57
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
58
|
+
var getEntropy = (secret) => {
|
|
59
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
60
|
+
for (const char of secret) {
|
|
61
|
+
if (!charFreq.has(char)) {
|
|
62
|
+
charFreq.set(char, 0);
|
|
63
|
+
}
|
|
64
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
65
|
+
}
|
|
66
|
+
let entropy = 0;
|
|
67
|
+
const length = secret.length;
|
|
68
|
+
for (const freq of charFreq.values()) {
|
|
69
|
+
const p = freq / length;
|
|
70
|
+
entropy -= p * Math.log2(p);
|
|
71
|
+
}
|
|
72
|
+
return entropy;
|
|
73
|
+
};
|
|
74
|
+
var createSecret = (secret, length = 32) => {
|
|
75
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
47
76
|
if (typeof secret === "string") {
|
|
48
|
-
|
|
49
|
-
|
|
77
|
+
const encoded = encoder.encode(secret);
|
|
78
|
+
const byteLength = encoded.byteLength;
|
|
79
|
+
if (byteLength < length) {
|
|
80
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
81
|
+
}
|
|
82
|
+
const entropy = getEntropy(secret);
|
|
83
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
84
|
+
throw new InvalidSecretError(
|
|
85
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
86
|
+
);
|
|
50
87
|
}
|
|
51
|
-
return
|
|
88
|
+
return encoded;
|
|
52
89
|
}
|
|
53
|
-
|
|
90
|
+
if (secret instanceof CryptoKey || secret instanceof Uint8Array) {
|
|
91
|
+
if (secret instanceof Uint8Array && secret.byteLength < length) {
|
|
92
|
+
throw new InvalidSecretError(`Secret must be at least ${length} bytes long`);
|
|
93
|
+
}
|
|
94
|
+
return secret;
|
|
95
|
+
}
|
|
96
|
+
throw new InvalidSecretError("Secret must be a string, Uint8Array, or CryptoKey");
|
|
54
97
|
};
|
|
55
98
|
|
|
56
99
|
// src/deriveKey.ts
|
|
57
|
-
var deriveKey = (secret, salt, info, length = 32) => {
|
|
100
|
+
var deriveKey = async (secret, salt, info, length = 32) => {
|
|
58
101
|
try {
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
102
|
+
const subtle = getSubtleCrypto();
|
|
103
|
+
const secretBuffer = secret.buffer.slice(secret.byteOffset, secret.byteOffset + secret.byteLength);
|
|
104
|
+
const baseKey = await subtle.importKey("raw", secretBuffer, "HKDF", false, ["deriveBits"]);
|
|
105
|
+
const saltBuffer = typeof salt === "string" ? encoder.encode(salt) : salt;
|
|
106
|
+
const infoBuffer = typeof info === "string" ? encoder.encode(info) : info;
|
|
107
|
+
const derivedBits = await subtle.deriveBits(
|
|
108
|
+
{
|
|
109
|
+
name: "HKDF",
|
|
110
|
+
hash: "SHA-256",
|
|
111
|
+
salt: saltBuffer,
|
|
112
|
+
info: infoBuffer
|
|
113
|
+
},
|
|
114
|
+
baseKey,
|
|
115
|
+
length << 3
|
|
116
|
+
);
|
|
117
|
+
return new Uint8Array(derivedBits);
|
|
65
118
|
} catch (error) {
|
|
66
|
-
throw new
|
|
119
|
+
throw new KeyDerivationError("Failed to create a derived key (HKDF)", { cause: error });
|
|
67
120
|
}
|
|
68
121
|
};
|
|
69
|
-
var createDeriveKey = (secret, salt, info, length = 32) => {
|
|
122
|
+
var createDeriveKey = async (secret, salt, info, length = 32) => {
|
|
70
123
|
const secretKey = createSecret(secret);
|
|
71
|
-
|
|
124
|
+
if (secretKey instanceof CryptoKey) {
|
|
125
|
+
throw new KeyDerivationError("Cannot derive key from CryptoKey. Use Uint8Array or string secret instead.");
|
|
126
|
+
}
|
|
127
|
+
const key = await deriveKey(secretKey, salt ?? "Aura Jose secret salt", info ?? "Aura Jose secret derivation", length);
|
|
128
|
+
return key;
|
|
72
129
|
};
|
|
73
130
|
// Annotate the CommonJS export names for ESM import in node:
|
|
74
131
|
0 && (module.exports = {
|
package/dist/deriveKey.d.ts
CHANGED
package/dist/deriveKey.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createDeriveKey,
|
|
3
3
|
deriveKey
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-OG4QRUXH.js";
|
|
5
|
+
import "./chunk-FCUM7BTG.js";
|
|
6
|
+
import "./chunk-MWFJ4CA5.js";
|
|
7
|
+
import "./chunk-RQFUZSWH.js";
|
|
8
|
+
import "./chunk-NGBYHSRN.js";
|
|
8
9
|
export {
|
|
9
10
|
createDeriveKey,
|
|
10
11
|
deriveKey
|
package/dist/encrypt.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/encrypt.ts
|
|
@@ -35,7 +25,6 @@ __export(encrypt_exports, {
|
|
|
35
25
|
encryptJWE: () => encryptJWE
|
|
36
26
|
});
|
|
37
27
|
module.exports = __toCommonJS(encrypt_exports);
|
|
38
|
-
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
39
28
|
var import_jose = require("jose");
|
|
40
29
|
|
|
41
30
|
// src/errors.ts
|
|
@@ -70,16 +59,54 @@ var isFalsy = (value) => {
|
|
|
70
59
|
return value === null || value === void 0 || value === false || value === 0 || value === "" || Number.isNaN(value);
|
|
71
60
|
};
|
|
72
61
|
|
|
62
|
+
// src/crypto.ts
|
|
63
|
+
var encoder = new TextEncoder();
|
|
64
|
+
var decoder = new TextDecoder();
|
|
65
|
+
var getRandomBytes = (size) => {
|
|
66
|
+
return globalThis.crypto.getRandomValues(new Uint8Array(size));
|
|
67
|
+
};
|
|
68
|
+
|
|
73
69
|
// src/secret.ts
|
|
74
|
-
var
|
|
75
|
-
|
|
70
|
+
var MIN_SECRET_ENTROPY_BITS = 4.5;
|
|
71
|
+
var getEntropy = (secret) => {
|
|
72
|
+
const charFreq = /* @__PURE__ */ new Map();
|
|
73
|
+
for (const char of secret) {
|
|
74
|
+
if (!charFreq.has(char)) {
|
|
75
|
+
charFreq.set(char, 0);
|
|
76
|
+
}
|
|
77
|
+
charFreq.set(char, charFreq.get(char) + 1);
|
|
78
|
+
}
|
|
79
|
+
let entropy = 0;
|
|
80
|
+
const length = secret.length;
|
|
81
|
+
for (const freq of charFreq.values()) {
|
|
82
|
+
const p = freq / length;
|
|
83
|
+
entropy -= p * Math.log2(p);
|
|
84
|
+
}
|
|
85
|
+
return entropy;
|
|
86
|
+
};
|
|
87
|
+
var createSecret = (secret, length = 32) => {
|
|
88
|
+
if (!Boolean(secret)) throw new InvalidSecretError("Secret is required");
|
|
76
89
|
if (typeof secret === "string") {
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
const encoded = encoder.encode(secret);
|
|
91
|
+
const byteLength = encoded.byteLength;
|
|
92
|
+
if (byteLength < length) {
|
|
93
|
+
throw new InvalidSecretError(`Secret string must be at least ${length} bytes long`);
|
|
94
|
+
}
|
|
95
|
+
const entropy = getEntropy(secret);
|
|
96
|
+
if (entropy < MIN_SECRET_ENTROPY_BITS) {
|
|
97
|
+
throw new InvalidSecretError(
|
|
98
|
+
`Secret string must have an entropy of at least ${MIN_SECRET_ENTROPY_BITS} bits per character`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
return encoded;
|
|
102
|
+
}
|
|
103
|
+
if (secret instanceof CryptoKey || secret instanceof Uint8Array) {
|
|
104
|
+
if (secret instanceof Uint8Array && secret.byteLength < length) {
|
|
105
|
+
throw new InvalidSecretError(`Secret must be at least ${length} bytes long`);
|
|
79
106
|
}
|
|
80
|
-
return
|
|
107
|
+
return secret;
|
|
81
108
|
}
|
|
82
|
-
|
|
109
|
+
throw new InvalidSecretError("Secret must be a string, Uint8Array, or CryptoKey");
|
|
83
110
|
};
|
|
84
111
|
|
|
85
112
|
// src/encrypt.ts
|
|
@@ -89,8 +116,8 @@ var encryptJWE = async (payload, secret, options) => {
|
|
|
89
116
|
throw new InvalidPayloadError("The payload must be a non-empty string");
|
|
90
117
|
}
|
|
91
118
|
const secretKey = createSecret(secret);
|
|
92
|
-
const jti =
|
|
93
|
-
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);
|
|
119
|
+
const jti = import_jose.base64url.encode(getRandomBytes(32));
|
|
120
|
+
return await 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
121
|
} catch (error) {
|
|
95
122
|
if (isAuraJoseError(error)) {
|
|
96
123
|
throw 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 { E as EncryptOptions, a as EncryptedPayload, c as createJWE, d as decryptJWE, e as encryptJWE } from './sign.js';
|
|
3
|
+
import './crypto.js';
|
package/dist/encrypt.js
CHANGED
|
@@ -2,10 +2,11 @@ import {
|
|
|
2
2
|
createJWE,
|
|
3
3
|
decryptJWE,
|
|
4
4
|
encryptJWE
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-Q2LAK6W2.js";
|
|
6
|
+
import "./chunk-FCUM7BTG.js";
|
|
7
|
+
import "./chunk-MWFJ4CA5.js";
|
|
8
|
+
import "./chunk-RQFUZSWH.js";
|
|
9
|
+
import "./chunk-NGBYHSRN.js";
|
|
9
10
|
export {
|
|
10
11
|
createJWE,
|
|
11
12
|
decryptJWE,
|
package/dist/errors.cjs
CHANGED
|
@@ -28,7 +28,8 @@ __export(errors_exports, {
|
|
|
28
28
|
JWSSigningError: () => JWSSigningError,
|
|
29
29
|
JWSVerificationError: () => JWSVerificationError,
|
|
30
30
|
JWTDecodingError: () => JWTDecodingError,
|
|
31
|
-
JWTEncodingError: () => JWTEncodingError
|
|
31
|
+
JWTEncodingError: () => JWTEncodingError,
|
|
32
|
+
KeyDerivationError: () => KeyDerivationError
|
|
32
33
|
});
|
|
33
34
|
module.exports = __toCommonJS(errors_exports);
|
|
34
35
|
var AuraJoseError = class extends Error {
|
|
@@ -65,6 +66,9 @@ var JWEEncryptionError = class extends AuraJoseError {
|
|
|
65
66
|
var InvalidSecretError = class extends AuraJoseError {
|
|
66
67
|
static code = "ERR_INVALID_SECRET";
|
|
67
68
|
};
|
|
69
|
+
var KeyDerivationError = class extends AuraJoseError {
|
|
70
|
+
static code = "ERR_KEY_DERIVATION";
|
|
71
|
+
};
|
|
68
72
|
// Annotate the CommonJS export names for ESM import in node:
|
|
69
73
|
0 && (module.exports = {
|
|
70
74
|
AuraJoseError,
|
|
@@ -75,5 +79,6 @@ var InvalidSecretError = class extends AuraJoseError {
|
|
|
75
79
|
JWSSigningError,
|
|
76
80
|
JWSVerificationError,
|
|
77
81
|
JWTDecodingError,
|
|
78
|
-
JWTEncodingError
|
|
82
|
+
JWTEncodingError,
|
|
83
|
+
KeyDerivationError
|
|
79
84
|
});
|
package/dist/errors.d.ts
CHANGED
|
@@ -30,5 +30,8 @@ declare class JWEEncryptionError extends AuraJoseError {
|
|
|
30
30
|
declare class InvalidSecretError extends AuraJoseError {
|
|
31
31
|
static code: string;
|
|
32
32
|
}
|
|
33
|
+
declare class KeyDerivationError extends AuraJoseError {
|
|
34
|
+
static code: string;
|
|
35
|
+
}
|
|
33
36
|
|
|
34
|
-
export { AuraJoseError, InvalidPayloadError, InvalidSecretError, JWEDecryptionError, JWEEncryptionError, JWSSigningError, JWSVerificationError, JWTDecodingError, JWTEncodingError };
|
|
37
|
+
export { AuraJoseError, InvalidPayloadError, InvalidSecretError, JWEDecryptionError, JWEEncryptionError, JWSSigningError, JWSVerificationError, JWTDecodingError, JWTEncodingError, KeyDerivationError };
|
package/dist/errors.js
CHANGED
|
@@ -7,8 +7,9 @@ import {
|
|
|
7
7
|
JWSSigningError,
|
|
8
8
|
JWSVerificationError,
|
|
9
9
|
JWTDecodingError,
|
|
10
|
-
JWTEncodingError
|
|
11
|
-
|
|
10
|
+
JWTEncodingError,
|
|
11
|
+
KeyDerivationError
|
|
12
|
+
} from "./chunk-NGBYHSRN.js";
|
|
12
13
|
export {
|
|
13
14
|
AuraJoseError,
|
|
14
15
|
InvalidPayloadError,
|
|
@@ -18,5 +19,6 @@ export {
|
|
|
18
19
|
JWSSigningError,
|
|
19
20
|
JWSVerificationError,
|
|
20
21
|
JWTDecodingError,
|
|
21
|
-
JWTEncodingError
|
|
22
|
+
JWTEncodingError,
|
|
23
|
+
KeyDerivationError
|
|
22
24
|
};
|