@djangocfg/crypto 2.1.235 → 2.1.236
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/package.json +2 -2
- package/dist/react.cjs +0 -300
- package/dist/react.mjs +0 -279
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/crypto",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.236",
|
|
4
4
|
"description": "Client-side AES-256-GCM decryption for Django-CFG encrypted API responses using Web Crypto API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"crypto",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
69
|
+
"@djangocfg/typescript-config": "^2.1.236",
|
|
70
70
|
"@types/node": "^24.7.2",
|
|
71
71
|
"@types/react": "^19.1.0",
|
|
72
72
|
"react": "^19.1.0",
|
package/dist/react.cjs
DELETED
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
-
|
|
22
|
-
// src/react/index.ts
|
|
23
|
-
var react_exports = {};
|
|
24
|
-
__export(react_exports, {
|
|
25
|
-
useDecrypt: () => useDecrypt,
|
|
26
|
-
useDecryptionClient: () => useDecryptionClient,
|
|
27
|
-
useIsEncrypted: () => useIsEncrypted,
|
|
28
|
-
useLazyDecrypt: () => useLazyDecrypt
|
|
29
|
-
});
|
|
30
|
-
module.exports = __toCommonJS(react_exports);
|
|
31
|
-
|
|
32
|
-
// src/react/hooks.ts
|
|
33
|
-
var import_react = require("react");
|
|
34
|
-
|
|
35
|
-
// src/key-derivation.ts
|
|
36
|
-
async function deriveKey(password, salt, iterations = 1e5, keyLength = 32) {
|
|
37
|
-
const encoder = new TextEncoder();
|
|
38
|
-
const passwordBuffer = encoder.encode(password);
|
|
39
|
-
const keyMaterial = await crypto.subtle.importKey(
|
|
40
|
-
"raw",
|
|
41
|
-
passwordBuffer,
|
|
42
|
-
"PBKDF2",
|
|
43
|
-
false,
|
|
44
|
-
["deriveBits", "deriveKey"]
|
|
45
|
-
);
|
|
46
|
-
return crypto.subtle.deriveKey(
|
|
47
|
-
{
|
|
48
|
-
name: "PBKDF2",
|
|
49
|
-
salt: salt.buffer,
|
|
50
|
-
iterations,
|
|
51
|
-
hash: "SHA-256"
|
|
52
|
-
},
|
|
53
|
-
keyMaterial,
|
|
54
|
-
{ name: "AES-GCM", length: keyLength * 8 },
|
|
55
|
-
false,
|
|
56
|
-
["decrypt"]
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
__name(deriveKey, "deriveKey");
|
|
60
|
-
async function buildSalt(keyPrefix = "djangocfg_encryption", userId, sessionId) {
|
|
61
|
-
const parts = [keyPrefix];
|
|
62
|
-
if (sessionId) {
|
|
63
|
-
parts.push(`session:${sessionId}`);
|
|
64
|
-
} else if (userId !== void 0) {
|
|
65
|
-
parts.push(`user:${userId}`);
|
|
66
|
-
} else {
|
|
67
|
-
parts.push("global");
|
|
68
|
-
}
|
|
69
|
-
const saltInput = parts.join(":");
|
|
70
|
-
const encoder = new TextEncoder();
|
|
71
|
-
const inputBuffer = encoder.encode(saltInput);
|
|
72
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", inputBuffer);
|
|
73
|
-
return new Uint8Array(hashBuffer).slice(0, 16);
|
|
74
|
-
}
|
|
75
|
-
__name(buildSalt, "buildSalt");
|
|
76
|
-
async function deriveKeyFromConfig(config) {
|
|
77
|
-
const {
|
|
78
|
-
secretKey,
|
|
79
|
-
userId,
|
|
80
|
-
sessionId,
|
|
81
|
-
iterations = 1e5,
|
|
82
|
-
keyPrefix = "djangocfg_encryption"
|
|
83
|
-
} = config;
|
|
84
|
-
const salt = await buildSalt(keyPrefix, userId, sessionId);
|
|
85
|
-
return deriveKey(secretKey, salt, iterations);
|
|
86
|
-
}
|
|
87
|
-
__name(deriveKeyFromConfig, "deriveKeyFromConfig");
|
|
88
|
-
|
|
89
|
-
// src/types.ts
|
|
90
|
-
function isEncryptedField(value) {
|
|
91
|
-
if (typeof value !== "object" || value === null) return false;
|
|
92
|
-
const obj = value;
|
|
93
|
-
return obj.encrypted === true && typeof obj.algorithm === "string" && typeof obj.iv === "string" && typeof obj.data === "string" && typeof obj.auth_tag === "string";
|
|
94
|
-
}
|
|
95
|
-
__name(isEncryptedField, "isEncryptedField");
|
|
96
|
-
function isEncryptedResponse(value) {
|
|
97
|
-
if (typeof value !== "object" || value === null) return false;
|
|
98
|
-
const obj = value;
|
|
99
|
-
return obj.encrypted === true && typeof obj.algorithm === "string" && typeof obj.salt === "string" && typeof obj.iv === "string" && typeof obj.data === "string" && typeof obj.auth_tag === "string";
|
|
100
|
-
}
|
|
101
|
-
__name(isEncryptedResponse, "isEncryptedResponse");
|
|
102
|
-
|
|
103
|
-
// src/decryption.ts
|
|
104
|
-
function base64ToBytes(base64) {
|
|
105
|
-
const binary = atob(base64);
|
|
106
|
-
const bytes = new Uint8Array(binary.length);
|
|
107
|
-
for (let i = 0; i < binary.length; i++) {
|
|
108
|
-
bytes[i] = binary.charCodeAt(i);
|
|
109
|
-
}
|
|
110
|
-
return bytes;
|
|
111
|
-
}
|
|
112
|
-
__name(base64ToBytes, "base64ToBytes");
|
|
113
|
-
async function decryptAES256GCM(ciphertext, key, iv, authTag) {
|
|
114
|
-
const combined = new Uint8Array(ciphertext.length + authTag.length);
|
|
115
|
-
combined.set(ciphertext);
|
|
116
|
-
combined.set(authTag, ciphertext.length);
|
|
117
|
-
const decrypted = await crypto.subtle.decrypt(
|
|
118
|
-
{
|
|
119
|
-
name: "AES-GCM",
|
|
120
|
-
iv: iv.buffer,
|
|
121
|
-
tagLength: 128
|
|
122
|
-
// 16 bytes = 128 bits
|
|
123
|
-
},
|
|
124
|
-
key,
|
|
125
|
-
combined
|
|
126
|
-
);
|
|
127
|
-
return new Uint8Array(decrypted);
|
|
128
|
-
}
|
|
129
|
-
__name(decryptAES256GCM, "decryptAES256GCM");
|
|
130
|
-
async function decryptField(field, key) {
|
|
131
|
-
if (field.algorithm !== "AES-256-GCM") {
|
|
132
|
-
throw new Error(`Unsupported algorithm: ${field.algorithm}`);
|
|
133
|
-
}
|
|
134
|
-
const iv = base64ToBytes(field.iv);
|
|
135
|
-
const ciphertext = base64ToBytes(field.data);
|
|
136
|
-
const authTag = base64ToBytes(field.auth_tag);
|
|
137
|
-
const decrypted = await decryptAES256GCM(ciphertext, key, iv, authTag);
|
|
138
|
-
const text = new TextDecoder().decode(decrypted);
|
|
139
|
-
return JSON.parse(text);
|
|
140
|
-
}
|
|
141
|
-
__name(decryptField, "decryptField");
|
|
142
|
-
async function decryptObject(data, key) {
|
|
143
|
-
if (data === null || data === void 0) {
|
|
144
|
-
return data;
|
|
145
|
-
}
|
|
146
|
-
if (isEncryptedField(data)) {
|
|
147
|
-
return decryptField(data, key);
|
|
148
|
-
}
|
|
149
|
-
if (Array.isArray(data)) {
|
|
150
|
-
const decrypted = await Promise.all(
|
|
151
|
-
data.map((item) => decryptObject(item, key))
|
|
152
|
-
);
|
|
153
|
-
return decrypted;
|
|
154
|
-
}
|
|
155
|
-
if (typeof data === "object") {
|
|
156
|
-
const result = {};
|
|
157
|
-
const entries = Object.entries(data);
|
|
158
|
-
for (const [objKey, value] of entries) {
|
|
159
|
-
result[objKey] = await decryptObject(value, key);
|
|
160
|
-
}
|
|
161
|
-
return result;
|
|
162
|
-
}
|
|
163
|
-
return data;
|
|
164
|
-
}
|
|
165
|
-
__name(decryptObject, "decryptObject");
|
|
166
|
-
async function createDecryptionClient(config) {
|
|
167
|
-
const key = await deriveKeyFromConfig(config);
|
|
168
|
-
return {
|
|
169
|
-
/**
|
|
170
|
-
* Decrypt a single encrypted field.
|
|
171
|
-
*/
|
|
172
|
-
decryptField: /* @__PURE__ */ __name((field) => decryptField(field, key), "decryptField"),
|
|
173
|
-
/**
|
|
174
|
-
* Recursively decrypt all encrypted fields in an object.
|
|
175
|
-
*/
|
|
176
|
-
decryptObject: /* @__PURE__ */ __name((data) => decryptObject(data, key), "decryptObject"),
|
|
177
|
-
/**
|
|
178
|
-
* Check if a value is an encrypted field.
|
|
179
|
-
*/
|
|
180
|
-
isEncryptedField,
|
|
181
|
-
/**
|
|
182
|
-
* Check if a value is an encrypted response.
|
|
183
|
-
*/
|
|
184
|
-
isEncryptedResponse
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
__name(createDecryptionClient, "createDecryptionClient");
|
|
188
|
-
|
|
189
|
-
// src/react/hooks.ts
|
|
190
|
-
function useDecrypt(encryptedData, config) {
|
|
191
|
-
const [state, setState] = (0, import_react.useState)({
|
|
192
|
-
data: void 0,
|
|
193
|
-
isLoading: true,
|
|
194
|
-
error: void 0,
|
|
195
|
-
isDecrypted: false
|
|
196
|
-
});
|
|
197
|
-
const keyRef = (0, import_react.useRef)(null);
|
|
198
|
-
const configRef = (0, import_react.useRef)(config);
|
|
199
|
-
const configChanged = configRef.current.secretKey !== config.secretKey || configRef.current.userId !== config.userId || configRef.current.sessionId !== config.sessionId;
|
|
200
|
-
if (configChanged) {
|
|
201
|
-
configRef.current = config;
|
|
202
|
-
keyRef.current = null;
|
|
203
|
-
}
|
|
204
|
-
(0, import_react.useEffect)(() => {
|
|
205
|
-
let cancelled = false;
|
|
206
|
-
async function decrypt() {
|
|
207
|
-
try {
|
|
208
|
-
setState((s) => ({ ...s, isLoading: true, error: void 0 }));
|
|
209
|
-
if (!keyRef.current) {
|
|
210
|
-
keyRef.current = await deriveKeyFromConfig(config);
|
|
211
|
-
}
|
|
212
|
-
const decrypted = await decryptObject(encryptedData, keyRef.current);
|
|
213
|
-
if (!cancelled) {
|
|
214
|
-
setState({
|
|
215
|
-
data: decrypted,
|
|
216
|
-
isLoading: false,
|
|
217
|
-
error: void 0,
|
|
218
|
-
isDecrypted: true
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
} catch (err) {
|
|
222
|
-
if (!cancelled) {
|
|
223
|
-
setState({
|
|
224
|
-
data: void 0,
|
|
225
|
-
isLoading: false,
|
|
226
|
-
error: err instanceof Error ? err : new Error("Decryption failed"),
|
|
227
|
-
isDecrypted: false
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
__name(decrypt, "decrypt");
|
|
233
|
-
decrypt();
|
|
234
|
-
return () => {
|
|
235
|
-
cancelled = true;
|
|
236
|
-
};
|
|
237
|
-
}, [encryptedData, config.secretKey, config.userId, config.sessionId]);
|
|
238
|
-
return state;
|
|
239
|
-
}
|
|
240
|
-
__name(useDecrypt, "useDecrypt");
|
|
241
|
-
function useDecryptionClient(config) {
|
|
242
|
-
const [client, setClient] = (0, import_react.useState)(null);
|
|
243
|
-
(0, import_react.useEffect)(() => {
|
|
244
|
-
createDecryptionClient(config).then(setClient);
|
|
245
|
-
}, [config.secretKey, config.userId, config.sessionId]);
|
|
246
|
-
return client;
|
|
247
|
-
}
|
|
248
|
-
__name(useDecryptionClient, "useDecryptionClient");
|
|
249
|
-
function useLazyDecrypt(config) {
|
|
250
|
-
const [state, setState] = (0, import_react.useState)({
|
|
251
|
-
data: void 0,
|
|
252
|
-
isLoading: false,
|
|
253
|
-
error: void 0,
|
|
254
|
-
isDecrypted: false
|
|
255
|
-
});
|
|
256
|
-
const keyRef = (0, import_react.useRef)(null);
|
|
257
|
-
const decrypt = (0, import_react.useCallback)(
|
|
258
|
-
async (encryptedData) => {
|
|
259
|
-
try {
|
|
260
|
-
setState((s) => ({ ...s, isLoading: true, error: void 0 }));
|
|
261
|
-
if (!keyRef.current) {
|
|
262
|
-
keyRef.current = await deriveKeyFromConfig(config);
|
|
263
|
-
}
|
|
264
|
-
const decrypted = await decryptObject(encryptedData, keyRef.current);
|
|
265
|
-
setState({
|
|
266
|
-
data: decrypted,
|
|
267
|
-
isLoading: false,
|
|
268
|
-
error: void 0,
|
|
269
|
-
isDecrypted: true
|
|
270
|
-
});
|
|
271
|
-
return decrypted;
|
|
272
|
-
} catch (err) {
|
|
273
|
-
const error = err instanceof Error ? err : new Error("Decryption failed");
|
|
274
|
-
setState({
|
|
275
|
-
data: void 0,
|
|
276
|
-
isLoading: false,
|
|
277
|
-
error,
|
|
278
|
-
isDecrypted: false
|
|
279
|
-
});
|
|
280
|
-
return void 0;
|
|
281
|
-
}
|
|
282
|
-
},
|
|
283
|
-
[config.secretKey, config.userId, config.sessionId]
|
|
284
|
-
);
|
|
285
|
-
const reset = (0, import_react.useCallback)(() => {
|
|
286
|
-
setState({
|
|
287
|
-
data: void 0,
|
|
288
|
-
isLoading: false,
|
|
289
|
-
error: void 0,
|
|
290
|
-
isDecrypted: false
|
|
291
|
-
});
|
|
292
|
-
}, []);
|
|
293
|
-
return { ...state, decrypt, reset };
|
|
294
|
-
}
|
|
295
|
-
__name(useLazyDecrypt, "useLazyDecrypt");
|
|
296
|
-
function useIsEncrypted(value) {
|
|
297
|
-
return (0, import_react.useMemo)(() => isEncryptedField(value), [value]);
|
|
298
|
-
}
|
|
299
|
-
__name(useIsEncrypted, "useIsEncrypted");
|
|
300
|
-
//# sourceMappingURL=react.cjs.map
|
package/dist/react.mjs
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
|
-
|
|
5
|
-
// src/react/hooks.ts
|
|
6
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
7
|
-
|
|
8
|
-
// src/key-derivation.ts
|
|
9
|
-
async function deriveKey(password, salt, iterations = 1e5, keyLength = 32) {
|
|
10
|
-
const encoder = new TextEncoder();
|
|
11
|
-
const passwordBuffer = encoder.encode(password);
|
|
12
|
-
const keyMaterial = await crypto.subtle.importKey(
|
|
13
|
-
"raw",
|
|
14
|
-
passwordBuffer,
|
|
15
|
-
"PBKDF2",
|
|
16
|
-
false,
|
|
17
|
-
["deriveBits", "deriveKey"]
|
|
18
|
-
);
|
|
19
|
-
return crypto.subtle.deriveKey(
|
|
20
|
-
{
|
|
21
|
-
name: "PBKDF2",
|
|
22
|
-
salt: salt.buffer,
|
|
23
|
-
iterations,
|
|
24
|
-
hash: "SHA-256"
|
|
25
|
-
},
|
|
26
|
-
keyMaterial,
|
|
27
|
-
{ name: "AES-GCM", length: keyLength * 8 },
|
|
28
|
-
false,
|
|
29
|
-
["decrypt"]
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
__name(deriveKey, "deriveKey");
|
|
33
|
-
async function buildSalt(keyPrefix = "djangocfg_encryption", userId, sessionId) {
|
|
34
|
-
const parts = [keyPrefix];
|
|
35
|
-
if (sessionId) {
|
|
36
|
-
parts.push(`session:${sessionId}`);
|
|
37
|
-
} else if (userId !== void 0) {
|
|
38
|
-
parts.push(`user:${userId}`);
|
|
39
|
-
} else {
|
|
40
|
-
parts.push("global");
|
|
41
|
-
}
|
|
42
|
-
const saltInput = parts.join(":");
|
|
43
|
-
const encoder = new TextEncoder();
|
|
44
|
-
const inputBuffer = encoder.encode(saltInput);
|
|
45
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", inputBuffer);
|
|
46
|
-
return new Uint8Array(hashBuffer).slice(0, 16);
|
|
47
|
-
}
|
|
48
|
-
__name(buildSalt, "buildSalt");
|
|
49
|
-
async function deriveKeyFromConfig(config) {
|
|
50
|
-
const {
|
|
51
|
-
secretKey,
|
|
52
|
-
userId,
|
|
53
|
-
sessionId,
|
|
54
|
-
iterations = 1e5,
|
|
55
|
-
keyPrefix = "djangocfg_encryption"
|
|
56
|
-
} = config;
|
|
57
|
-
const salt = await buildSalt(keyPrefix, userId, sessionId);
|
|
58
|
-
return deriveKey(secretKey, salt, iterations);
|
|
59
|
-
}
|
|
60
|
-
__name(deriveKeyFromConfig, "deriveKeyFromConfig");
|
|
61
|
-
|
|
62
|
-
// src/types.ts
|
|
63
|
-
function isEncryptedField(value) {
|
|
64
|
-
if (typeof value !== "object" || value === null) return false;
|
|
65
|
-
const obj = value;
|
|
66
|
-
return obj.encrypted === true && typeof obj.algorithm === "string" && typeof obj.iv === "string" && typeof obj.data === "string" && typeof obj.auth_tag === "string";
|
|
67
|
-
}
|
|
68
|
-
__name(isEncryptedField, "isEncryptedField");
|
|
69
|
-
function isEncryptedResponse(value) {
|
|
70
|
-
if (typeof value !== "object" || value === null) return false;
|
|
71
|
-
const obj = value;
|
|
72
|
-
return obj.encrypted === true && typeof obj.algorithm === "string" && typeof obj.salt === "string" && typeof obj.iv === "string" && typeof obj.data === "string" && typeof obj.auth_tag === "string";
|
|
73
|
-
}
|
|
74
|
-
__name(isEncryptedResponse, "isEncryptedResponse");
|
|
75
|
-
|
|
76
|
-
// src/decryption.ts
|
|
77
|
-
function base64ToBytes(base64) {
|
|
78
|
-
const binary = atob(base64);
|
|
79
|
-
const bytes = new Uint8Array(binary.length);
|
|
80
|
-
for (let i = 0; i < binary.length; i++) {
|
|
81
|
-
bytes[i] = binary.charCodeAt(i);
|
|
82
|
-
}
|
|
83
|
-
return bytes;
|
|
84
|
-
}
|
|
85
|
-
__name(base64ToBytes, "base64ToBytes");
|
|
86
|
-
async function decryptAES256GCM(ciphertext, key, iv, authTag) {
|
|
87
|
-
const combined = new Uint8Array(ciphertext.length + authTag.length);
|
|
88
|
-
combined.set(ciphertext);
|
|
89
|
-
combined.set(authTag, ciphertext.length);
|
|
90
|
-
const decrypted = await crypto.subtle.decrypt(
|
|
91
|
-
{
|
|
92
|
-
name: "AES-GCM",
|
|
93
|
-
iv: iv.buffer,
|
|
94
|
-
tagLength: 128
|
|
95
|
-
// 16 bytes = 128 bits
|
|
96
|
-
},
|
|
97
|
-
key,
|
|
98
|
-
combined
|
|
99
|
-
);
|
|
100
|
-
return new Uint8Array(decrypted);
|
|
101
|
-
}
|
|
102
|
-
__name(decryptAES256GCM, "decryptAES256GCM");
|
|
103
|
-
async function decryptField(field, key) {
|
|
104
|
-
if (field.algorithm !== "AES-256-GCM") {
|
|
105
|
-
throw new Error(`Unsupported algorithm: ${field.algorithm}`);
|
|
106
|
-
}
|
|
107
|
-
const iv = base64ToBytes(field.iv);
|
|
108
|
-
const ciphertext = base64ToBytes(field.data);
|
|
109
|
-
const authTag = base64ToBytes(field.auth_tag);
|
|
110
|
-
const decrypted = await decryptAES256GCM(ciphertext, key, iv, authTag);
|
|
111
|
-
const text = new TextDecoder().decode(decrypted);
|
|
112
|
-
return JSON.parse(text);
|
|
113
|
-
}
|
|
114
|
-
__name(decryptField, "decryptField");
|
|
115
|
-
async function decryptObject(data, key) {
|
|
116
|
-
if (data === null || data === void 0) {
|
|
117
|
-
return data;
|
|
118
|
-
}
|
|
119
|
-
if (isEncryptedField(data)) {
|
|
120
|
-
return decryptField(data, key);
|
|
121
|
-
}
|
|
122
|
-
if (Array.isArray(data)) {
|
|
123
|
-
const decrypted = await Promise.all(
|
|
124
|
-
data.map((item) => decryptObject(item, key))
|
|
125
|
-
);
|
|
126
|
-
return decrypted;
|
|
127
|
-
}
|
|
128
|
-
if (typeof data === "object") {
|
|
129
|
-
const result = {};
|
|
130
|
-
const entries = Object.entries(data);
|
|
131
|
-
for (const [objKey, value] of entries) {
|
|
132
|
-
result[objKey] = await decryptObject(value, key);
|
|
133
|
-
}
|
|
134
|
-
return result;
|
|
135
|
-
}
|
|
136
|
-
return data;
|
|
137
|
-
}
|
|
138
|
-
__name(decryptObject, "decryptObject");
|
|
139
|
-
async function createDecryptionClient(config) {
|
|
140
|
-
const key = await deriveKeyFromConfig(config);
|
|
141
|
-
return {
|
|
142
|
-
/**
|
|
143
|
-
* Decrypt a single encrypted field.
|
|
144
|
-
*/
|
|
145
|
-
decryptField: /* @__PURE__ */ __name((field) => decryptField(field, key), "decryptField"),
|
|
146
|
-
/**
|
|
147
|
-
* Recursively decrypt all encrypted fields in an object.
|
|
148
|
-
*/
|
|
149
|
-
decryptObject: /* @__PURE__ */ __name((data) => decryptObject(data, key), "decryptObject"),
|
|
150
|
-
/**
|
|
151
|
-
* Check if a value is an encrypted field.
|
|
152
|
-
*/
|
|
153
|
-
isEncryptedField,
|
|
154
|
-
/**
|
|
155
|
-
* Check if a value is an encrypted response.
|
|
156
|
-
*/
|
|
157
|
-
isEncryptedResponse
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
__name(createDecryptionClient, "createDecryptionClient");
|
|
161
|
-
|
|
162
|
-
// src/react/hooks.ts
|
|
163
|
-
function useDecrypt(encryptedData, config) {
|
|
164
|
-
const [state, setState] = useState({
|
|
165
|
-
data: void 0,
|
|
166
|
-
isLoading: true,
|
|
167
|
-
error: void 0,
|
|
168
|
-
isDecrypted: false
|
|
169
|
-
});
|
|
170
|
-
const keyRef = useRef(null);
|
|
171
|
-
const configRef = useRef(config);
|
|
172
|
-
const configChanged = configRef.current.secretKey !== config.secretKey || configRef.current.userId !== config.userId || configRef.current.sessionId !== config.sessionId;
|
|
173
|
-
if (configChanged) {
|
|
174
|
-
configRef.current = config;
|
|
175
|
-
keyRef.current = null;
|
|
176
|
-
}
|
|
177
|
-
useEffect(() => {
|
|
178
|
-
let cancelled = false;
|
|
179
|
-
async function decrypt() {
|
|
180
|
-
try {
|
|
181
|
-
setState((s) => ({ ...s, isLoading: true, error: void 0 }));
|
|
182
|
-
if (!keyRef.current) {
|
|
183
|
-
keyRef.current = await deriveKeyFromConfig(config);
|
|
184
|
-
}
|
|
185
|
-
const decrypted = await decryptObject(encryptedData, keyRef.current);
|
|
186
|
-
if (!cancelled) {
|
|
187
|
-
setState({
|
|
188
|
-
data: decrypted,
|
|
189
|
-
isLoading: false,
|
|
190
|
-
error: void 0,
|
|
191
|
-
isDecrypted: true
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
} catch (err) {
|
|
195
|
-
if (!cancelled) {
|
|
196
|
-
setState({
|
|
197
|
-
data: void 0,
|
|
198
|
-
isLoading: false,
|
|
199
|
-
error: err instanceof Error ? err : new Error("Decryption failed"),
|
|
200
|
-
isDecrypted: false
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
__name(decrypt, "decrypt");
|
|
206
|
-
decrypt();
|
|
207
|
-
return () => {
|
|
208
|
-
cancelled = true;
|
|
209
|
-
};
|
|
210
|
-
}, [encryptedData, config.secretKey, config.userId, config.sessionId]);
|
|
211
|
-
return state;
|
|
212
|
-
}
|
|
213
|
-
__name(useDecrypt, "useDecrypt");
|
|
214
|
-
function useDecryptionClient(config) {
|
|
215
|
-
const [client, setClient] = useState(null);
|
|
216
|
-
useEffect(() => {
|
|
217
|
-
createDecryptionClient(config).then(setClient);
|
|
218
|
-
}, [config.secretKey, config.userId, config.sessionId]);
|
|
219
|
-
return client;
|
|
220
|
-
}
|
|
221
|
-
__name(useDecryptionClient, "useDecryptionClient");
|
|
222
|
-
function useLazyDecrypt(config) {
|
|
223
|
-
const [state, setState] = useState({
|
|
224
|
-
data: void 0,
|
|
225
|
-
isLoading: false,
|
|
226
|
-
error: void 0,
|
|
227
|
-
isDecrypted: false
|
|
228
|
-
});
|
|
229
|
-
const keyRef = useRef(null);
|
|
230
|
-
const decrypt = useCallback(
|
|
231
|
-
async (encryptedData) => {
|
|
232
|
-
try {
|
|
233
|
-
setState((s) => ({ ...s, isLoading: true, error: void 0 }));
|
|
234
|
-
if (!keyRef.current) {
|
|
235
|
-
keyRef.current = await deriveKeyFromConfig(config);
|
|
236
|
-
}
|
|
237
|
-
const decrypted = await decryptObject(encryptedData, keyRef.current);
|
|
238
|
-
setState({
|
|
239
|
-
data: decrypted,
|
|
240
|
-
isLoading: false,
|
|
241
|
-
error: void 0,
|
|
242
|
-
isDecrypted: true
|
|
243
|
-
});
|
|
244
|
-
return decrypted;
|
|
245
|
-
} catch (err) {
|
|
246
|
-
const error = err instanceof Error ? err : new Error("Decryption failed");
|
|
247
|
-
setState({
|
|
248
|
-
data: void 0,
|
|
249
|
-
isLoading: false,
|
|
250
|
-
error,
|
|
251
|
-
isDecrypted: false
|
|
252
|
-
});
|
|
253
|
-
return void 0;
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
[config.secretKey, config.userId, config.sessionId]
|
|
257
|
-
);
|
|
258
|
-
const reset = useCallback(() => {
|
|
259
|
-
setState({
|
|
260
|
-
data: void 0,
|
|
261
|
-
isLoading: false,
|
|
262
|
-
error: void 0,
|
|
263
|
-
isDecrypted: false
|
|
264
|
-
});
|
|
265
|
-
}, []);
|
|
266
|
-
return { ...state, decrypt, reset };
|
|
267
|
-
}
|
|
268
|
-
__name(useLazyDecrypt, "useLazyDecrypt");
|
|
269
|
-
function useIsEncrypted(value) {
|
|
270
|
-
return useMemo(() => isEncryptedField(value), [value]);
|
|
271
|
-
}
|
|
272
|
-
__name(useIsEncrypted, "useIsEncrypted");
|
|
273
|
-
export {
|
|
274
|
-
useDecrypt,
|
|
275
|
-
useDecryptionClient,
|
|
276
|
-
useIsEncrypted,
|
|
277
|
-
useLazyDecrypt
|
|
278
|
-
};
|
|
279
|
-
//# sourceMappingURL=react.mjs.map
|