@raytio/core 11.5.0 → 11.6.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.
Files changed (133) hide show
  1. package/README.md +1708 -217
  2. package/dist/accessApplication/api/legacy/convertRelationships.d.ts +3 -5
  3. package/dist/accessApplication/api/legacy/convertRelationships.js +3 -3
  4. package/dist/crypto/cognitoAttributes.d.ts +3 -0
  5. package/dist/crypto/cognitoAttributes.js +15 -4
  6. package/dist/crypto/getAADecryptor.d.ts +1 -1
  7. package/dist/crypto/getAADecryptor.js +1 -3
  8. package/dist/crypto/index.d.ts +3 -0
  9. package/dist/crypto/index.js +6 -0
  10. package/dist/crypto/kdf/argon2.d.ts +67 -0
  11. package/dist/crypto/kdf/argon2.js +99 -0
  12. package/dist/crypto/kdf/index.d.ts +43 -0
  13. package/dist/crypto/kdf/index.js +106 -0
  14. package/dist/crypto/kdf/pbkdf2.d.ts +16 -0
  15. package/dist/crypto/kdf/pbkdf2.js +45 -0
  16. package/dist/crypto/kdf/twoSecretKdf.d.ts +37 -0
  17. package/dist/crypto/kdf/twoSecretKdf.js +66 -0
  18. package/dist/crypto/kdf/types.d.ts +65 -0
  19. package/dist/crypto/kdf/types.js +50 -0
  20. package/dist/crypto/kdf/utils.d.ts +59 -0
  21. package/dist/crypto/kdf/utils.js +110 -0
  22. package/dist/crypto/localSecret/format.d.ts +48 -0
  23. package/dist/crypto/localSecret/format.js +157 -0
  24. package/dist/crypto/localSecret/generator.d.ts +23 -0
  25. package/dist/crypto/localSecret/generator.js +53 -0
  26. package/dist/crypto/localSecret/index.d.ts +12 -0
  27. package/dist/crypto/localSecret/index.js +46 -0
  28. package/dist/crypto/localSecret/storage.d.ts +53 -0
  29. package/dist/crypto/localSecret/storage.js +207 -0
  30. package/dist/crypto/localSecret/types.d.ts +68 -0
  31. package/dist/crypto/localSecret/types.js +31 -0
  32. package/dist/crypto/pgpKey/encryption.d.ts +49 -0
  33. package/dist/crypto/pgpKey/encryption.js +104 -0
  34. package/dist/crypto/pgpKey/export.d.ts +59 -0
  35. package/dist/crypto/pgpKey/export.js +322 -0
  36. package/dist/crypto/pgpKey/format.d.ts +61 -0
  37. package/dist/crypto/pgpKey/format.js +143 -0
  38. package/dist/crypto/pgpKey/generator.d.ts +20 -0
  39. package/dist/crypto/pgpKey/generator.js +76 -0
  40. package/dist/crypto/pgpKey/import.d.ts +69 -0
  41. package/dist/crypto/pgpKey/import.js +239 -0
  42. package/dist/crypto/pgpKey/index.d.ts +19 -0
  43. package/dist/crypto/pgpKey/index.js +67 -0
  44. package/dist/crypto/pgpKey/signing.d.ts +44 -0
  45. package/dist/crypto/pgpKey/signing.js +71 -0
  46. package/dist/crypto/pgpKey/storage.d.ts +43 -0
  47. package/dist/crypto/pgpKey/storage.js +141 -0
  48. package/dist/crypto/pgpKey/types.d.ts +86 -0
  49. package/dist/crypto/pgpKey/types.js +25 -0
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.js +1 -0
  52. package/dist/rules/calculateScore.d.ts +1 -1
  53. package/dist/rules/convertInstanceToRuleInput.js +99 -97
  54. package/dist/rules/evaluateBadge.d.ts +36 -0
  55. package/dist/rules/evaluateBadge.js +36 -0
  56. package/dist/rules/index.d.ts +1 -0
  57. package/dist/rules/index.js +1 -0
  58. package/dist/rules/types/config.d.ts +1 -1
  59. package/dist/rules/types/dataValueTypes.d.ts +4 -4
  60. package/dist/schema/expandSchema/constants.js +1 -1
  61. package/dist/schema/expandSchema/expandSchema.d.ts +3 -3
  62. package/dist/schema/expandSchema/expandSchema.js +4 -4
  63. package/dist/schema/expandSchema/i18n.d.ts +6 -1
  64. package/dist/schema/expandSchema/i18n.js +32 -4
  65. package/dist/schema/expandSchema/maybeUseI18n.d.ts +2 -2
  66. package/dist/schema/expandSchema/maybeUseI18n.js +68 -11
  67. package/dist/schema/expandSchema/processSchema.js +14 -5
  68. package/dist/schema/expandSchema/removePrivateFields.d.ts +75 -22
  69. package/dist/schema/expandSchema/sortSchemaProperties.d.ts +4 -1
  70. package/dist/schema/expandSchema/sortSchemaProperties.js +24 -1
  71. package/dist/schema/labels.js +1 -2
  72. package/dist/util/canonicalJsonify.d.ts +7 -1
  73. package/dist/util/canonicalJsonify.js +3 -2
  74. package/dist/verifications/safeHarbour.js +5 -0
  75. package/dist/verifications/verifyCheck/getOwnRealVerifications.js +2 -0
  76. package/package.json +6 -4
  77. package/dist/__tests__/docs.test.d.ts +0 -1
  78. package/dist/__tests__/docs.test.js +0 -24
  79. package/dist/accessApplication/api/__tests__/fetchKeysForSubmission.test.d.ts +0 -1
  80. package/dist/accessApplication/api/__tests__/fetchKeysForSubmission.test.js +0 -28
  81. package/dist/accessApplication/api/__tests__/fetchPOsOrAOsForSubmission.test.d.ts +0 -1
  82. package/dist/accessApplication/api/__tests__/fetchPOsOrAOsForSubmission.test.js +0 -23
  83. package/dist/accessApplication/api/__tests__/fetchRelationshipsForSubmission.test.d.ts +0 -1
  84. package/dist/accessApplication/api/__tests__/fetchRelationshipsForSubmission.test.js +0 -27
  85. package/dist/accessApplication/api/__tests__/getMissingDataForInstance.test.d.ts +0 -1
  86. package/dist/accessApplication/api/__tests__/getMissingDataForInstance.test.js +0 -30
  87. package/dist/accessApplication/api/legacy/__tests__/convertRelationships.test.d.ts +0 -1
  88. package/dist/accessApplication/api/legacy/__tests__/convertRelationships.test.js +0 -37
  89. package/dist/rules/helpers/__tests__/addInfiniteThresholdBoundaries.test.d.ts +0 -1
  90. package/dist/rules/helpers/__tests__/addInfiniteThresholdBoundaries.test.js +0 -27
  91. package/dist/rules/helpers/__tests__/checkTypeofValue.test.d.ts +0 -1
  92. package/dist/rules/helpers/__tests__/checkTypeofValue.test.js +0 -49
  93. package/dist/rules/helpers/__tests__/getValuesFromPath.test.d.ts +0 -1
  94. package/dist/rules/helpers/__tests__/getValuesFromPath.test.js +0 -67
  95. package/dist/rules/helpers/__tests__/thresholds.test.d.ts +0 -1
  96. package/dist/rules/helpers/__tests__/thresholds.test.js +0 -32
  97. package/dist/rules/operators/__tests__/bool.test.d.ts +0 -1
  98. package/dist/rules/operators/__tests__/bool.test.js +0 -21
  99. package/dist/rules/operators/__tests__/date.test.d.ts +0 -1
  100. package/dist/rules/operators/__tests__/date.test.js +0 -81
  101. package/dist/rules/operators/__tests__/hfield.test.d.ts +0 -1
  102. package/dist/rules/operators/__tests__/hfield.test.js +0 -38
  103. package/dist/rules/operators/__tests__/hschema.test.d.ts +0 -1
  104. package/dist/rules/operators/__tests__/hschema.test.js +0 -24
  105. package/dist/rules/operators/__tests__/number.test.d.ts +0 -1
  106. package/dist/rules/operators/__tests__/number.test.js +0 -53
  107. package/dist/rules/operators/__tests__/string.test.d.ts +0 -1
  108. package/dist/rules/operators/__tests__/string.test.js +0 -74
  109. package/dist/schema/expandSchema/__tests__/addLoadingTimes.test.d.ts +0 -1
  110. package/dist/schema/expandSchema/__tests__/addLoadingTimes.test.js +0 -24
  111. package/dist/schema/expandSchema/__tests__/expandSchema.test.d.ts +0 -1
  112. package/dist/schema/expandSchema/__tests__/expandSchema.test.js +0 -96
  113. package/dist/schema/expandSchema/__tests__/i18n.test.d.ts +0 -1
  114. package/dist/schema/expandSchema/__tests__/i18n.test.js +0 -32
  115. package/dist/schema/expandSchema/__tests__/maybeUseI18n.test.d.ts +0 -1
  116. package/dist/schema/expandSchema/__tests__/maybeUseI18n.test.js +0 -98
  117. package/dist/schema/expandSchema/__tests__/processSchema.test.d.ts +0 -1
  118. package/dist/schema/expandSchema/__tests__/processSchema.test.js +0 -326
  119. package/dist/schema/expandSchema/__tests__/sortSchemaProperties.test.d.ts +0 -1
  120. package/dist/schema/expandSchema/__tests__/sortSchemaProperties.test.js +0 -182
  121. package/dist/schema/expandSchema/__tests__/util.test.d.ts +0 -1
  122. package/dist/schema/expandSchema/__tests__/util.test.js +0 -19
  123. package/dist/verifications/cleanInstance.d.ts +0 -9
  124. package/dist/verifications/cleanInstance.js +0 -15
  125. package/dist/verifications/verifyCheck/__tests__/getOwnRealVerifications.test.d.ts +0 -1
  126. package/dist/verifications/verifyCheck/__tests__/getOwnRealVerifications.test.js +0 -221
  127. package/dist/verifications/verifyCheck/__tests__/getSomeoneElsesRealVerifications.test.d.ts +0 -1
  128. package/dist/verifications/verifyCheck/__tests__/getSomeoneElsesRealVerifications.test.js +0 -206
  129. package/dist/verifications/verifyCheck/operations/__tests__/checkOwnVerification.test.d.ts +0 -1
  130. package/dist/verifications/verifyCheck/operations/__tests__/checkOwnVerification.test.js +0 -138
  131. package/dist/verifications/verifyCheck/operations/__tests__/checkSomeoneElsesVerifications.test.d.ts +0 -1
  132. package/dist/verifications/verifyCheck/operations/__tests__/checkSomeoneElsesVerifications.test.js +0 -49
  133. package/dist/verifications/verifyCheck/operations/__tests__/sampleBundle.json +0 -44
@@ -3,11 +3,9 @@ import type { IId, NId, PId, Relationship } from "@raytio/types";
3
3
  export type ServerRelationship = Omit<Relationship, "p_id" | "start" | "end"> & {
4
4
  id: PId;
5
5
  from_id: NId;
6
- } & ({
7
- to_id: NId;
8
- } | {
9
- to_i_id: IId;
10
- });
6
+ to_id?: NId | null;
7
+ to_i_id?: IId | null;
8
+ };
11
9
  /**
12
10
  * Converts relationship type used by the server into the (Urn format) type used by the client
13
11
  * @param serverRelationship relationship type used in the server
@@ -13,8 +13,8 @@ function convertServerRelationship(serverRelationship) {
13
13
  * This functionality is similar to LinkToCrust, but in this case the API has already worked out
14
14
  * which instance the PO links to (if any) so we simply convert it into a {@link Urn}
15
15
  */
16
- const end = "to_id" in serverRelationship
17
- ? `urn:profile_object:${serverRelationship.to_id}`
18
- : `urn:instance:${serverRelationship.to_i_id}`;
16
+ const end = serverRelationship.to_i_id
17
+ ? `urn:instance:${serverRelationship.to_i_id}`
18
+ : `urn:profile_object:${serverRelationship.to_id}`;
19
19
  return Object.assign({ p_id: id, start: `urn:profile_object:${from_id}`, end }, (0, ramda_1.omit)(["id", "from_id", "to_id", "to_i_id"], serverRelationship));
20
20
  }
@@ -4,6 +4,9 @@ import type { ICognitoUserAttributeData } from "amazon-cognito-identity-js";
4
4
  * Given a `UserDoc` from the maxcryptor, this returns an object
5
5
  * which you can provide to `Auth.updateUserAttributes()`. It is
6
6
  * an object of stringified Json.
7
+ *
8
+ * Note: Only includes attributes that exist in userDoc. Missing attributes
9
+ * are filtered out to avoid Cognito "Attribute value must not be null" errors.
7
10
  */
8
11
  export declare const toCognitoAttributes: (userDoc: UserDoc) => {
9
12
  [customCognitoName: string]: string;
@@ -9,16 +9,27 @@ const ATTRIBUTE_MAP = {
9
9
  "custom:aek_private": ["encryption_key_pair", "private_key"],
10
10
  "custom:ask_public": ["signing_key_pair", "public_key"],
11
11
  "custom:ask_private": ["signing_key_pair", "private_key"],
12
+ // Two-Secret Key Derivation (2SKD) attributes - Issue #1649
13
+ "custom:kdf_version": ["kdf_version"],
14
+ "custom:kdf_config": ["kdf_config"],
12
15
  };
13
16
  /**
14
17
  * Given a `UserDoc` from the maxcryptor, this returns an object
15
18
  * which you can provide to `Auth.updateUserAttributes()`. It is
16
19
  * an object of stringified Json.
20
+ *
21
+ * Note: Only includes attributes that exist in userDoc. Missing attributes
22
+ * are filtered out to avoid Cognito "Attribute value must not be null" errors.
17
23
  */
18
- const toCognitoAttributes = (userDoc) => Object.fromEntries(Object.entries(ATTRIBUTE_MAP).map(([cognitoKey, deepPath]) => [
19
- cognitoKey,
20
- JSON.stringify((0, ramda_1.path)(deepPath, userDoc)),
21
- ]));
24
+ const toCognitoAttributes = (userDoc) => Object.fromEntries(Object.entries(ATTRIBUTE_MAP)
25
+ .map(([cognitoKey, deepPath]) => {
26
+ const value = (0, ramda_1.path)(deepPath, userDoc);
27
+ // Filter out undefined values - Cognito rejects null attribute values
28
+ if (value === undefined)
29
+ return undefined;
30
+ return [cognitoKey, JSON.stringify(value)];
31
+ })
32
+ .filter((entry) => entry !== undefined));
22
33
  exports.toCognitoAttributes = toCognitoAttributes;
23
34
  /**
24
35
  * This function converts Cognito's userAttributes into a maxcryptor UserDoc.
@@ -11,7 +11,7 @@ type PublicKeyNode = CommonNodeFields<KId> & {
11
11
  */
12
12
  export declare function getAAPublicKey({ apiUrl, apiToken, aId, }: {
13
13
  apiUrl: string;
14
- apiToken: string;
14
+ apiToken?: string;
15
15
  aId: AId;
16
16
  }): Promise<PublicKeyNode>;
17
17
  /**
@@ -8,9 +8,7 @@ const util_1 = require("../util");
8
8
  * @returns the id and Key information of the Applications Public Key
9
9
  */
10
10
  async function getAAPublicKey({ apiUrl, apiToken, aId, }) {
11
- const [publicKey] = await fetch(`${apiUrl}/db/v1/dsm_access_application_public_keys?aa_id=eq.${aId}`, {
12
- headers: { Authorization: `Bearer ${apiToken}` },
13
- }).then(util_1.handleResponse);
11
+ const [publicKey] = await fetch(`${apiUrl}/db/v1/dsm_access_application_public_keys?aa_id=eq.${aId}`, Object.assign({}, (apiToken && { headers: { Authorization: `Bearer ${apiToken}` } }))).then(util_1.handleResponse);
14
12
  if (!publicKey) {
15
13
  throw new Error("Could not Find Encryption Key");
16
14
  }
@@ -2,3 +2,6 @@ export * from "./cognitoAttributes";
2
2
  export * from "./decryptSharedData";
3
3
  export * from "./getAADecryptor";
4
4
  export * from "./helpers";
5
+ export * from "./kdf";
6
+ export * from "./localSecret";
7
+ export * from "./pgpKey";
@@ -19,3 +19,9 @@ __exportStar(require("./cognitoAttributes"), exports);
19
19
  __exportStar(require("./decryptSharedData"), exports);
20
20
  __exportStar(require("./getAADecryptor"), exports);
21
21
  __exportStar(require("./helpers"), exports);
22
+ // KDF module - Two-Secret Key Derivation (Issue #1649)
23
+ __exportStar(require("./kdf"), exports);
24
+ // LocalSecret module - device-bound secrets (Issue #1649)
25
+ __exportStar(require("./localSecret"), exports);
26
+ // PGP Key module - device-bound PGP keys (Issue #1374)
27
+ __exportStar(require("./pgpKey"), exports);
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Argon2id Key Derivation
3
+ *
4
+ * Modern memory-hard key derivation using Argon2id.
5
+ * Requires the argon2-browser package for WASM implementation.
6
+ * Issue #1649
7
+ */
8
+ import type { Argon2idConfig, KdfResult } from "./types";
9
+ /**
10
+ * Argon2 type constants
11
+ * These match the values from argon2-browser's ArgonType enum
12
+ */
13
+ export declare const ARGON2_TYPE: {
14
+ readonly Argon2d: 0;
15
+ readonly Argon2i: 1;
16
+ readonly Argon2id: 2;
17
+ };
18
+ type Argon2Module = {
19
+ hash: (options: {
20
+ pass: string | Uint8Array;
21
+ salt: Uint8Array;
22
+ type: number;
23
+ time: number;
24
+ mem: number;
25
+ parallelism: number;
26
+ hashLen: number;
27
+ }) => Promise<{
28
+ hash: Uint8Array;
29
+ encoded: string;
30
+ }>;
31
+ ArgonType?: {
32
+ Argon2d: number;
33
+ Argon2i: number;
34
+ Argon2id: number;
35
+ };
36
+ };
37
+ /**
38
+ * Set the Argon2 module reference
39
+ *
40
+ * This must be called before using deriveArgon2id.
41
+ * The module is passed in from packages/client where argon2-browser is imported.
42
+ *
43
+ * @param module - The argon2-browser module
44
+ */
45
+ export declare function setArgon2Module(module: Argon2Module): void;
46
+ /**
47
+ * Check if Argon2 module is available
48
+ */
49
+ export declare function isArgon2Available(): boolean;
50
+ /**
51
+ * Derive a key using Argon2id
52
+ *
53
+ * @param password - User's password (will be normalized)
54
+ * @param config - Argon2id configuration from Cognito attributes
55
+ * @returns KdfResult containing the derived 32-byte key
56
+ * @throws Error if argon2 module is not available
57
+ */
58
+ export declare function deriveArgon2id(password: string, config: Argon2idConfig): Promise<KdfResult>;
59
+ /**
60
+ * Create a new Argon2id configuration
61
+ *
62
+ * @param salt - Base64 encoded salt (optional, will generate if not provided)
63
+ * @param params - Optional custom parameters
64
+ * @returns Argon2idConfig ready for storage
65
+ */
66
+ export declare function createArgon2idConfig(salt: string, params?: Partial<Pick<Argon2idConfig, "memory" | "iterations" | "parallelism">>): Argon2idConfig;
67
+ export {};
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ /**
3
+ * Argon2id Key Derivation
4
+ *
5
+ * Modern memory-hard key derivation using Argon2id.
6
+ * Requires the argon2-browser package for WASM implementation.
7
+ * Issue #1649
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ARGON2_TYPE = void 0;
11
+ exports.setArgon2Module = setArgon2Module;
12
+ exports.isArgon2Available = isArgon2Available;
13
+ exports.deriveArgon2id = deriveArgon2id;
14
+ exports.createArgon2idConfig = createArgon2idConfig;
15
+ const types_1 = require("./types");
16
+ const utils_1 = require("./utils");
17
+ /**
18
+ * Argon2 type constants
19
+ * These match the values from argon2-browser's ArgonType enum
20
+ */
21
+ exports.ARGON2_TYPE = {
22
+ Argon2d: 0,
23
+ Argon2i: 1,
24
+ Argon2id: 2,
25
+ };
26
+ // Module-level reference to argon2, set via setArgon2Module
27
+ let argon2Module = null;
28
+ /**
29
+ * Set the Argon2 module reference
30
+ *
31
+ * This must be called before using deriveArgon2id.
32
+ * The module is passed in from packages/client where argon2-browser is imported.
33
+ *
34
+ * @param module - The argon2-browser module
35
+ */
36
+ function setArgon2Module(module) {
37
+ // eslint-disable-next-line fp/no-mutation -- Module-level singleton pattern
38
+ argon2Module = module;
39
+ }
40
+ /**
41
+ * Check if Argon2 module is available
42
+ */
43
+ function isArgon2Available() {
44
+ return argon2Module !== null;
45
+ }
46
+ /**
47
+ * Derive a key using Argon2id
48
+ *
49
+ * @param password - User's password (will be normalized)
50
+ * @param config - Argon2id configuration from Cognito attributes
51
+ * @returns KdfResult containing the derived 32-byte key
52
+ * @throws Error if argon2 module is not available
53
+ */
54
+ async function deriveArgon2id(password, config) {
55
+ var _a, _b, _c;
56
+ if (!argon2Module) {
57
+ throw new Error("Argon2 module not available. Call setArgon2Module() first.");
58
+ }
59
+ // Normalize password for consistent derivation
60
+ const normalizedPassword = (0, utils_1.normalizePassword)(password);
61
+ // Decode salt from base64
62
+ const salt = (0, utils_1.base64ToUint8Array)(config.salt);
63
+ // Use config values or defaults
64
+ const memory = (_a = config.memory) !== null && _a !== void 0 ? _a : types_1.DEFAULT_ARGON2ID_PARAMS.memory;
65
+ const iterations = (_b = config.iterations) !== null && _b !== void 0 ? _b : types_1.DEFAULT_ARGON2ID_PARAMS.iterations;
66
+ const parallelism = (_c = config.parallelism) !== null && _c !== void 0 ? _c : types_1.DEFAULT_ARGON2ID_PARAMS.parallelism;
67
+ // Derive key using Argon2id
68
+ const result = await argon2Module.hash({
69
+ pass: normalizedPassword,
70
+ salt,
71
+ type: exports.ARGON2_TYPE.Argon2id,
72
+ time: iterations,
73
+ mem: memory,
74
+ parallelism,
75
+ hashLen: 32, // 256 bits
76
+ });
77
+ return {
78
+ key: result.hash,
79
+ };
80
+ }
81
+ /**
82
+ * Create a new Argon2id configuration
83
+ *
84
+ * @param salt - Base64 encoded salt (optional, will generate if not provided)
85
+ * @param params - Optional custom parameters
86
+ * @returns Argon2idConfig ready for storage
87
+ */
88
+ function createArgon2idConfig(salt, params) {
89
+ var _a, _b, _c;
90
+ return {
91
+ algorithm_name: "Argon2id",
92
+ memory: (_a = params === null || params === void 0 ? void 0 : params.memory) !== null && _a !== void 0 ? _a : types_1.DEFAULT_ARGON2ID_PARAMS.memory,
93
+ iterations: (_b = params === null || params === void 0 ? void 0 : params.iterations) !== null && _b !== void 0 ? _b : types_1.DEFAULT_ARGON2ID_PARAMS.iterations,
94
+ parallelism: (_c = params === null || params === void 0 ? void 0 : params.parallelism) !== null && _c !== void 0 ? _c : types_1.DEFAULT_ARGON2ID_PARAMS.parallelism,
95
+ salt,
96
+ version: 2,
97
+ requires_local_secret: true,
98
+ };
99
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Key Derivation Function (KDF) Module
3
+ *
4
+ * Provides a unified interface for key derivation supporting both:
5
+ * - Legacy PBKDF2 (v1)
6
+ * - Modern Argon2id with Two-Secret Key Derivation (v2)
7
+ *
8
+ * Issue #1649
9
+ */
10
+ import type { KdfConfig, KdfResult } from "./types";
11
+ export * from "./types";
12
+ export { base64ToUint8Array, uint8ArrayToBase64, xorBytes, normalizePassword, generateRandomBytes, generateSalt, constantTimeEqual, } from "./utils";
13
+ export { derivePbkdf2 } from "./pbkdf2";
14
+ export { deriveArgon2id, setArgon2Module, isArgon2Available, createArgon2idConfig, } from "./argon2";
15
+ export { deriveTwoSecretKdf, isValidLocalSecret } from "./twoSecretKdf";
16
+ /**
17
+ * Derive a key using the appropriate KDF based on configuration
18
+ *
19
+ * This is the main entry point for key derivation. It automatically
20
+ * selects the correct algorithm based on the config.
21
+ *
22
+ * @param password - User's password
23
+ * @param config - KDF configuration from Cognito attributes
24
+ * @param localSecret - Optional LocalSecret for 2SKD (required for Argon2id with requires_local_secret)
25
+ * @returns KdfResult containing the derived key
26
+ * @throws LocalSecretRequiredError if LocalSecret is required but not provided
27
+ * @throws UnknownKdfAlgorithmError if the algorithm is not recognized
28
+ */
29
+ export declare function deriveKey(password: string, config: KdfConfig, localSecret?: Uint8Array | null): Promise<KdfResult>;
30
+ /**
31
+ * Check if a KDF configuration requires LocalSecret
32
+ *
33
+ * @param config - KDF configuration
34
+ * @returns true if LocalSecret is required
35
+ */
36
+ export declare function requiresLocalSecret(config: KdfConfig): boolean;
37
+ /**
38
+ * Get the KDF version from configuration
39
+ *
40
+ * @param config - KDF configuration
41
+ * @returns Version number (1 for PBKDF2, 2 for Argon2id with 2SKD)
42
+ */
43
+ export declare function getKdfVersion(config: KdfConfig): number;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ /**
3
+ * Key Derivation Function (KDF) Module
4
+ *
5
+ * Provides a unified interface for key derivation supporting both:
6
+ * - Legacy PBKDF2 (v1)
7
+ * - Modern Argon2id with Two-Secret Key Derivation (v2)
8
+ *
9
+ * Issue #1649
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
23
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.isValidLocalSecret = exports.deriveTwoSecretKdf = exports.createArgon2idConfig = exports.isArgon2Available = exports.setArgon2Module = exports.deriveArgon2id = exports.derivePbkdf2 = exports.constantTimeEqual = exports.generateSalt = exports.generateRandomBytes = exports.normalizePassword = exports.xorBytes = exports.uint8ArrayToBase64 = exports.base64ToUint8Array = void 0;
27
+ exports.deriveKey = deriveKey;
28
+ exports.requiresLocalSecret = requiresLocalSecret;
29
+ exports.getKdfVersion = getKdfVersion;
30
+ const types_1 = require("./types");
31
+ const pbkdf2_1 = require("./pbkdf2");
32
+ const twoSecretKdf_1 = require("./twoSecretKdf");
33
+ // Re-export types
34
+ __exportStar(require("./types"), exports);
35
+ // Re-export utils
36
+ var utils_1 = require("./utils");
37
+ Object.defineProperty(exports, "base64ToUint8Array", { enumerable: true, get: function () { return utils_1.base64ToUint8Array; } });
38
+ Object.defineProperty(exports, "uint8ArrayToBase64", { enumerable: true, get: function () { return utils_1.uint8ArrayToBase64; } });
39
+ Object.defineProperty(exports, "xorBytes", { enumerable: true, get: function () { return utils_1.xorBytes; } });
40
+ Object.defineProperty(exports, "normalizePassword", { enumerable: true, get: function () { return utils_1.normalizePassword; } });
41
+ Object.defineProperty(exports, "generateRandomBytes", { enumerable: true, get: function () { return utils_1.generateRandomBytes; } });
42
+ Object.defineProperty(exports, "generateSalt", { enumerable: true, get: function () { return utils_1.generateSalt; } });
43
+ Object.defineProperty(exports, "constantTimeEqual", { enumerable: true, get: function () { return utils_1.constantTimeEqual; } });
44
+ // Re-export PBKDF2
45
+ var pbkdf2_2 = require("./pbkdf2");
46
+ Object.defineProperty(exports, "derivePbkdf2", { enumerable: true, get: function () { return pbkdf2_2.derivePbkdf2; } });
47
+ // Re-export Argon2id
48
+ var argon2_1 = require("./argon2");
49
+ Object.defineProperty(exports, "deriveArgon2id", { enumerable: true, get: function () { return argon2_1.deriveArgon2id; } });
50
+ Object.defineProperty(exports, "setArgon2Module", { enumerable: true, get: function () { return argon2_1.setArgon2Module; } });
51
+ Object.defineProperty(exports, "isArgon2Available", { enumerable: true, get: function () { return argon2_1.isArgon2Available; } });
52
+ Object.defineProperty(exports, "createArgon2idConfig", { enumerable: true, get: function () { return argon2_1.createArgon2idConfig; } });
53
+ // Re-export Two-Secret KDF
54
+ var twoSecretKdf_2 = require("./twoSecretKdf");
55
+ Object.defineProperty(exports, "deriveTwoSecretKdf", { enumerable: true, get: function () { return twoSecretKdf_2.deriveTwoSecretKdf; } });
56
+ Object.defineProperty(exports, "isValidLocalSecret", { enumerable: true, get: function () { return twoSecretKdf_2.isValidLocalSecret; } });
57
+ /**
58
+ * Derive a key using the appropriate KDF based on configuration
59
+ *
60
+ * This is the main entry point for key derivation. It automatically
61
+ * selects the correct algorithm based on the config.
62
+ *
63
+ * @param password - User's password
64
+ * @param config - KDF configuration from Cognito attributes
65
+ * @param localSecret - Optional LocalSecret for 2SKD (required for Argon2id with requires_local_secret)
66
+ * @returns KdfResult containing the derived key
67
+ * @throws LocalSecretRequiredError if LocalSecret is required but not provided
68
+ * @throws UnknownKdfAlgorithmError if the algorithm is not recognized
69
+ */
70
+ async function deriveKey(password, config, localSecret) {
71
+ if ((0, types_1.isPbkdf2Config)(config)) {
72
+ // Legacy v1: PBKDF2 only
73
+ return (0, pbkdf2_1.derivePbkdf2)(password, config);
74
+ }
75
+ if ((0, types_1.isArgon2idConfig)(config)) {
76
+ // v2: Argon2id with optional 2SKD
77
+ return (0, twoSecretKdf_1.deriveTwoSecretKdf)(password, config, localSecret);
78
+ }
79
+ // Unknown algorithm
80
+ throw new types_1.UnknownKdfAlgorithmError(config.algorithm_name);
81
+ }
82
+ /**
83
+ * Check if a KDF configuration requires LocalSecret
84
+ *
85
+ * @param config - KDF configuration
86
+ * @returns true if LocalSecret is required
87
+ */
88
+ function requiresLocalSecret(config) {
89
+ return (0, types_1.isArgon2idConfig)(config) && config.requires_local_secret === true;
90
+ }
91
+ /**
92
+ * Get the KDF version from configuration
93
+ *
94
+ * @param config - KDF configuration
95
+ * @returns Version number (1 for PBKDF2, 2 for Argon2id with 2SKD)
96
+ */
97
+ function getKdfVersion(config) {
98
+ var _a;
99
+ if ((0, types_1.isPbkdf2Config)(config)) {
100
+ return 1;
101
+ }
102
+ if ((0, types_1.isArgon2idConfig)(config)) {
103
+ return (_a = config.version) !== null && _a !== void 0 ? _a : 2;
104
+ }
105
+ return 0; // Unknown
106
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * PBKDF2 Key Derivation
3
+ *
4
+ * Legacy v1 key derivation using PBKDF2-SHA512.
5
+ * This module extracts the existing PBKDF2 logic for backward compatibility.
6
+ * Issue #1649
7
+ */
8
+ import type { KdfResult, Pbkdf2Config } from "./types";
9
+ /**
10
+ * Derive a key using PBKDF2
11
+ *
12
+ * @param password - User's password
13
+ * @param config - PBKDF2 configuration from Cognito attributes
14
+ * @returns KdfResult containing the derived 32-byte key
15
+ */
16
+ export declare function derivePbkdf2(password: string, config: Pbkdf2Config): Promise<KdfResult>;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * PBKDF2 Key Derivation
4
+ *
5
+ * Legacy v1 key derivation using PBKDF2-SHA512.
6
+ * This module extracts the existing PBKDF2 logic for backward compatibility.
7
+ * Issue #1649
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.derivePbkdf2 = derivePbkdf2;
11
+ const utils_1 = require("./utils");
12
+ /**
13
+ * Derive a key using PBKDF2
14
+ *
15
+ * @param password - User's password
16
+ * @param config - PBKDF2 configuration from Cognito attributes
17
+ * @returns KdfResult containing the derived 32-byte key
18
+ */
19
+ async function derivePbkdf2(password, config) {
20
+ const encoder = new TextEncoder();
21
+ const passwordBuffer = encoder.encode(password);
22
+ // Import password as key material
23
+ const passwordKey = await crypto.subtle.importKey("raw", passwordBuffer, "PBKDF2", false, ["deriveBits", "deriveKey"]);
24
+ // Decode salt from base64
25
+ const salt = (0, utils_1.base64ToUint8Array)(config.salt);
26
+ // Normalize hash name (e.g., "SHA512" -> "SHA-512", "SHA-512" -> "SHA-512")
27
+ const hashUpper = config.hash.toUpperCase();
28
+ // Handle both "SHA512" and "SHA-512" formats
29
+ const hashName = hashUpper.includes("-")
30
+ ? hashUpper
31
+ : hashUpper.replace(/^(SHA)(\d+)$/, "$1-$2");
32
+ // Derive the key
33
+ const derivedKey = await crypto.subtle.deriveKey({
34
+ name: "PBKDF2",
35
+ salt,
36
+ iterations: config.iterations,
37
+ hash: hashName,
38
+ }, passwordKey, { name: "AES-GCM", length: 256 }, true, // extractable
39
+ ["encrypt", "decrypt"]);
40
+ // Export as raw bytes
41
+ const keyBuffer = await crypto.subtle.exportKey("raw", derivedKey);
42
+ return {
43
+ key: new Uint8Array(keyBuffer),
44
+ };
45
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Two-Secret Key Derivation (2SKD)
3
+ *
4
+ * Combines password-derived key with LocalSecret using XOR.
5
+ * This follows the 1Password security model where both secrets
6
+ * are required to derive the Key Encryption Key (KEK).
7
+ *
8
+ * Security properties:
9
+ * - Password alone cannot derive KEK
10
+ * - LocalSecret alone cannot derive KEK
11
+ * - Both are required, providing two-factor encryption
12
+ *
13
+ * Issue #1649
14
+ */
15
+ import type { Argon2idConfig, KdfResult } from "./types";
16
+ /**
17
+ * Derive KEK using Two-Secret Key Derivation
18
+ *
19
+ * Combines:
20
+ * 1. Password → Argon2id → 32 bytes
21
+ * 2. LocalSecret → 32 bytes
22
+ * 3. XOR(1, 2) → KEK
23
+ *
24
+ * @param password - User's password
25
+ * @param config - Argon2id configuration
26
+ * @param localSecret - Device-bound LocalSecret (32 bytes)
27
+ * @returns KdfResult containing the derived KEK
28
+ * @throws LocalSecretRequiredError if localSecret is not provided but required
29
+ */
30
+ export declare function deriveTwoSecretKdf(password: string, config: Argon2idConfig, localSecret: Uint8Array | null | undefined): Promise<KdfResult>;
31
+ /**
32
+ * Verify that a LocalSecret is valid
33
+ *
34
+ * @param localSecret - The LocalSecret to verify
35
+ * @returns true if valid
36
+ */
37
+ export declare function isValidLocalSecret(localSecret: Uint8Array | null | undefined): localSecret is Uint8Array;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /**
3
+ * Two-Secret Key Derivation (2SKD)
4
+ *
5
+ * Combines password-derived key with LocalSecret using XOR.
6
+ * This follows the 1Password security model where both secrets
7
+ * are required to derive the Key Encryption Key (KEK).
8
+ *
9
+ * Security properties:
10
+ * - Password alone cannot derive KEK
11
+ * - LocalSecret alone cannot derive KEK
12
+ * - Both are required, providing two-factor encryption
13
+ *
14
+ * Issue #1649
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.deriveTwoSecretKdf = deriveTwoSecretKdf;
18
+ exports.isValidLocalSecret = isValidLocalSecret;
19
+ const types_1 = require("./types");
20
+ const argon2_1 = require("./argon2");
21
+ const utils_1 = require("./utils");
22
+ /**
23
+ * Derive KEK using Two-Secret Key Derivation
24
+ *
25
+ * Combines:
26
+ * 1. Password → Argon2id → 32 bytes
27
+ * 2. LocalSecret → 32 bytes
28
+ * 3. XOR(1, 2) → KEK
29
+ *
30
+ * @param password - User's password
31
+ * @param config - Argon2id configuration
32
+ * @param localSecret - Device-bound LocalSecret (32 bytes)
33
+ * @returns KdfResult containing the derived KEK
34
+ * @throws LocalSecretRequiredError if localSecret is not provided but required
35
+ */
36
+ async function deriveTwoSecretKdf(password, config, localSecret) {
37
+ // Check if LocalSecret is required
38
+ if (config.requires_local_secret && !localSecret) {
39
+ throw new types_1.LocalSecretRequiredError();
40
+ }
41
+ // Derive key from password using Argon2id
42
+ const passwordDerived = await (0, argon2_1.deriveArgon2id)(password, config);
43
+ // If no LocalSecret, return password-derived key
44
+ // (fallback for accounts not using 2SKD)
45
+ if (!localSecret) {
46
+ return passwordDerived;
47
+ }
48
+ // Validate LocalSecret length
49
+ if (localSecret.length !== 32) {
50
+ throw new Error(`LocalSecret must be 32 bytes (got ${localSecret.length})`);
51
+ }
52
+ // XOR password-derived key with LocalSecret
53
+ const combinedKey = (0, utils_1.xorBytes)(passwordDerived.key, localSecret);
54
+ return {
55
+ key: combinedKey,
56
+ };
57
+ }
58
+ /**
59
+ * Verify that a LocalSecret is valid
60
+ *
61
+ * @param localSecret - The LocalSecret to verify
62
+ * @returns true if valid
63
+ */
64
+ function isValidLocalSecret(localSecret) {
65
+ return localSecret instanceof Uint8Array && localSecret.length === 32;
66
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Key Derivation Function (KDF) Types
3
+ *
4
+ * Types for the Two-Secret Key Derivation (2SKD) system.
5
+ * Issue #1649
6
+ */
7
+ /**
8
+ * PBKDF2 configuration (legacy v1)
9
+ */
10
+ export interface Pbkdf2Config {
11
+ algorithm_name: "PBKDF2";
12
+ iterations: number;
13
+ hash: string;
14
+ salt: string;
15
+ }
16
+ /**
17
+ * Argon2id configuration (v2 with 2SKD)
18
+ */
19
+ export interface Argon2idConfig {
20
+ algorithm_name: "Argon2id";
21
+ memory: number;
22
+ iterations: number;
23
+ parallelism: number;
24
+ salt: string;
25
+ version?: number;
26
+ requires_local_secret?: boolean;
27
+ }
28
+ /**
29
+ * Union type for all KDF configurations
30
+ */
31
+ export type KdfConfig = Pbkdf2Config | Argon2idConfig;
32
+ /**
33
+ * Result of key derivation
34
+ */
35
+ export interface KdfResult {
36
+ key: Uint8Array;
37
+ }
38
+ /**
39
+ * Error thrown when LocalSecret is required but not provided
40
+ */
41
+ export declare class LocalSecretRequiredError extends Error {
42
+ constructor(message?: string);
43
+ }
44
+ /**
45
+ * Error thrown when KDF algorithm is unknown
46
+ */
47
+ export declare class UnknownKdfAlgorithmError extends Error {
48
+ constructor(algorithm: string);
49
+ }
50
+ /**
51
+ * Default Argon2id parameters (matching Bitwarden recommendations)
52
+ */
53
+ export declare const DEFAULT_ARGON2ID_PARAMS: {
54
+ readonly memory: 65536;
55
+ readonly iterations: 3;
56
+ readonly parallelism: 4;
57
+ };
58
+ /**
59
+ * Type guard for PBKDF2 config
60
+ */
61
+ export declare function isPbkdf2Config(config: KdfConfig): config is Pbkdf2Config;
62
+ /**
63
+ * Type guard for Argon2id config
64
+ */
65
+ export declare function isArgon2idConfig(config: KdfConfig): config is Argon2idConfig;