@haex-space/vault-sdk 2.5.117 → 2.5.119
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/{client-DSvkG_lC.d.mts → client-CJTSbNLI.d.mts} +1 -1
- package/dist/{client-CA59HZfa.d.ts → client-E86CS0KK.d.ts} +1 -1
- package/dist/index.d.mts +43 -5
- package/dist/index.d.ts +43 -5
- package/dist/index.js +727 -487
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +716 -479
- package/dist/index.mjs.map +1 -1
- package/dist/node.d.mts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/react.d.mts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +66 -28
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +66 -28
- package/dist/react.mjs.map +1 -1
- package/dist/runtime/nuxt.plugin.client.d.mts +2 -2
- package/dist/runtime/nuxt.plugin.client.d.ts +2 -2
- package/dist/runtime/nuxt.plugin.client.js.map +1 -1
- package/dist/runtime/nuxt.plugin.client.mjs.map +1 -1
- package/dist/svelte.d.mts +2 -2
- package/dist/svelte.d.ts +2 -2
- package/dist/svelte.js +66 -28
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +66 -28
- package/dist/svelte.mjs.map +1 -1
- package/dist/{types-neLTvZJ_.d.mts → types-TFcm6hpl.d.mts} +19 -1
- package/dist/{types-neLTvZJ_.d.ts → types-TFcm6hpl.d.ts} +19 -1
- package/dist/vue.d.mts +2 -2
- package/dist/vue.d.ts +2 -2
- package/dist/vue.js +66 -28
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +66 -28
- package/dist/vue.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -2,62 +2,363 @@
|
|
|
2
2
|
|
|
3
3
|
var sqliteProxy = require('drizzle-orm/sqlite-proxy');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __esm = (fn, res) => function __init() {
|
|
8
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
9
|
+
};
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/crypto/vaultKey.ts
|
|
16
|
+
async function deriveKeyFromPassword(password, salt) {
|
|
17
|
+
const encoder = new TextEncoder();
|
|
18
|
+
const passwordBuffer = encoder.encode(password);
|
|
19
|
+
const saltBuffer = new Uint8Array(salt);
|
|
20
|
+
const keyMaterial = await crypto.subtle.importKey(
|
|
21
|
+
"raw",
|
|
22
|
+
passwordBuffer,
|
|
23
|
+
"PBKDF2",
|
|
24
|
+
false,
|
|
25
|
+
["deriveKey"]
|
|
26
|
+
);
|
|
27
|
+
return await crypto.subtle.deriveKey(
|
|
28
|
+
{
|
|
29
|
+
name: "PBKDF2",
|
|
30
|
+
salt: saltBuffer,
|
|
31
|
+
iterations: PBKDF2_ITERATIONS,
|
|
32
|
+
hash: "SHA-256"
|
|
33
|
+
},
|
|
34
|
+
keyMaterial,
|
|
35
|
+
{ name: ALGORITHM, length: KEY_LENGTH },
|
|
36
|
+
false,
|
|
37
|
+
// not extractable
|
|
38
|
+
["encrypt", "decrypt"]
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
function generateVaultKey() {
|
|
42
|
+
return crypto.getRandomValues(new Uint8Array(32));
|
|
43
|
+
}
|
|
44
|
+
async function encryptString(data, derivedKey) {
|
|
45
|
+
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
46
|
+
const encoder = new TextEncoder();
|
|
47
|
+
const dataBuffer = encoder.encode(data);
|
|
48
|
+
const encryptedBuffer = await crypto.subtle.encrypt(
|
|
49
|
+
{
|
|
50
|
+
name: ALGORITHM,
|
|
51
|
+
iv: nonce
|
|
52
|
+
},
|
|
53
|
+
derivedKey,
|
|
54
|
+
dataBuffer
|
|
55
|
+
);
|
|
56
|
+
return {
|
|
57
|
+
encryptedData: arrayBufferToBase64(encryptedBuffer),
|
|
58
|
+
nonce: arrayBufferToBase64(nonce)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async function decryptString(encryptedData, nonce, derivedKey) {
|
|
62
|
+
const encryptedBuffer = base64ToArrayBuffer(encryptedData);
|
|
63
|
+
const nonceBuffer = base64ToArrayBuffer(nonce);
|
|
64
|
+
const encryptedDataBuffer = new Uint8Array(encryptedBuffer);
|
|
65
|
+
const iv = new Uint8Array(nonceBuffer);
|
|
66
|
+
const decryptedBuffer = await crypto.subtle.decrypt(
|
|
67
|
+
{
|
|
68
|
+
name: ALGORITHM,
|
|
69
|
+
iv
|
|
70
|
+
},
|
|
71
|
+
derivedKey,
|
|
72
|
+
encryptedDataBuffer
|
|
73
|
+
);
|
|
74
|
+
const decoder = new TextDecoder();
|
|
75
|
+
return decoder.decode(decryptedBuffer);
|
|
76
|
+
}
|
|
77
|
+
async function encryptVaultKey(vaultKey, password) {
|
|
78
|
+
const salt = crypto.getRandomValues(new Uint8Array(32));
|
|
79
|
+
const derivedKey = await deriveKeyFromPassword(password, salt);
|
|
80
|
+
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
81
|
+
const vaultKeyBuffer = new Uint8Array(vaultKey);
|
|
82
|
+
const encryptedBuffer = await crypto.subtle.encrypt(
|
|
83
|
+
{
|
|
84
|
+
name: ALGORITHM,
|
|
85
|
+
iv: nonce
|
|
86
|
+
},
|
|
87
|
+
derivedKey,
|
|
88
|
+
vaultKeyBuffer
|
|
89
|
+
);
|
|
90
|
+
return {
|
|
91
|
+
encryptedVaultKey: arrayBufferToBase64(encryptedBuffer),
|
|
92
|
+
salt: arrayBufferToBase64(salt),
|
|
93
|
+
vaultKeyNonce: arrayBufferToBase64(nonce)
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function decryptVaultKey(encryptedVaultKey, salt, vaultKeyNonce, password) {
|
|
97
|
+
const encryptedBuffer = base64ToArrayBuffer(encryptedVaultKey);
|
|
98
|
+
const saltBuffer = base64ToArrayBuffer(salt);
|
|
99
|
+
const nonceBuffer = base64ToArrayBuffer(vaultKeyNonce);
|
|
100
|
+
const derivedKey = await deriveKeyFromPassword(password, saltBuffer);
|
|
101
|
+
const encryptedData = new Uint8Array(encryptedBuffer);
|
|
102
|
+
const iv = new Uint8Array(nonceBuffer);
|
|
103
|
+
const decryptedBuffer = await crypto.subtle.decrypt(
|
|
104
|
+
{
|
|
105
|
+
name: ALGORITHM,
|
|
106
|
+
iv
|
|
107
|
+
},
|
|
108
|
+
derivedKey,
|
|
109
|
+
encryptedData
|
|
110
|
+
);
|
|
111
|
+
return new Uint8Array(decryptedBuffer);
|
|
112
|
+
}
|
|
113
|
+
async function decryptVaultName(encryptedVaultName, vaultNameNonce, vaultNameSalt, password) {
|
|
114
|
+
const saltBuffer = base64ToArrayBuffer(vaultNameSalt);
|
|
115
|
+
const derivedKey = await deriveKeyFromPassword(password, saltBuffer);
|
|
116
|
+
return decryptString(encryptedVaultName, vaultNameNonce, derivedKey);
|
|
117
|
+
}
|
|
118
|
+
async function encryptCrdtData(data, vaultKey) {
|
|
119
|
+
const vaultKeyBuffer = new Uint8Array(vaultKey);
|
|
120
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
121
|
+
"raw",
|
|
122
|
+
vaultKeyBuffer,
|
|
123
|
+
{ name: ALGORITHM },
|
|
124
|
+
false,
|
|
125
|
+
["encrypt"]
|
|
126
|
+
);
|
|
127
|
+
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
128
|
+
const encoder = new TextEncoder();
|
|
129
|
+
const dataBuffer = encoder.encode(JSON.stringify(data));
|
|
130
|
+
const encryptedBuffer = await crypto.subtle.encrypt(
|
|
131
|
+
{
|
|
132
|
+
name: ALGORITHM,
|
|
133
|
+
iv: nonce
|
|
134
|
+
},
|
|
135
|
+
cryptoKey,
|
|
136
|
+
dataBuffer
|
|
137
|
+
);
|
|
138
|
+
return {
|
|
139
|
+
encryptedData: arrayBufferToBase64(encryptedBuffer),
|
|
140
|
+
nonce: arrayBufferToBase64(nonce)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async function wrapKey(keyToWrap, wrappingKey) {
|
|
144
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
145
|
+
"raw",
|
|
146
|
+
new Uint8Array(wrappingKey),
|
|
147
|
+
{ name: ALGORITHM },
|
|
148
|
+
false,
|
|
149
|
+
["encrypt"]
|
|
150
|
+
);
|
|
151
|
+
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
152
|
+
const ciphertext = await crypto.subtle.encrypt(
|
|
153
|
+
{ name: ALGORITHM, iv: nonce },
|
|
154
|
+
cryptoKey,
|
|
155
|
+
new Uint8Array(keyToWrap)
|
|
156
|
+
);
|
|
157
|
+
const result = new Uint8Array(12 + ciphertext.byteLength);
|
|
158
|
+
result.set(nonce, 0);
|
|
159
|
+
result.set(new Uint8Array(ciphertext), 12);
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
async function unwrapKey(wrappedKey, wrappingKey) {
|
|
163
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
164
|
+
"raw",
|
|
165
|
+
new Uint8Array(wrappingKey),
|
|
166
|
+
{ name: ALGORITHM },
|
|
167
|
+
false,
|
|
168
|
+
["decrypt"]
|
|
169
|
+
);
|
|
170
|
+
const nonce = wrappedKey.slice(0, 12);
|
|
171
|
+
const ciphertext = wrappedKey.slice(12);
|
|
172
|
+
const plaintext = await crypto.subtle.decrypt(
|
|
173
|
+
{ name: ALGORITHM, iv: nonce },
|
|
174
|
+
cryptoKey,
|
|
175
|
+
ciphertext
|
|
176
|
+
);
|
|
177
|
+
return new Uint8Array(plaintext);
|
|
178
|
+
}
|
|
179
|
+
async function decryptCrdtData(encryptedData, nonce, vaultKey) {
|
|
180
|
+
const vaultKeyBuffer = new Uint8Array(vaultKey);
|
|
181
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
182
|
+
"raw",
|
|
183
|
+
vaultKeyBuffer,
|
|
184
|
+
{ name: ALGORITHM },
|
|
185
|
+
false,
|
|
186
|
+
["decrypt"]
|
|
187
|
+
);
|
|
188
|
+
const encryptedBuffer = base64ToArrayBuffer(encryptedData);
|
|
189
|
+
const nonceBuffer = base64ToArrayBuffer(nonce);
|
|
190
|
+
const encryptedDataBuffer = new Uint8Array(encryptedBuffer);
|
|
191
|
+
const iv = new Uint8Array(nonceBuffer);
|
|
192
|
+
const decryptedBuffer = await crypto.subtle.decrypt(
|
|
193
|
+
{
|
|
194
|
+
name: ALGORITHM,
|
|
195
|
+
iv
|
|
196
|
+
},
|
|
197
|
+
cryptoKey,
|
|
198
|
+
encryptedDataBuffer
|
|
199
|
+
);
|
|
200
|
+
const decoder = new TextDecoder();
|
|
201
|
+
const jsonString = decoder.decode(decryptedBuffer);
|
|
202
|
+
return JSON.parse(jsonString);
|
|
203
|
+
}
|
|
204
|
+
function arrayBufferToBase64(buffer) {
|
|
205
|
+
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
206
|
+
if (typeof Buffer !== "undefined") {
|
|
207
|
+
return Buffer.from(bytes).toString("base64");
|
|
19
208
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
setItem(key, value) {
|
|
27
|
-
lsStorage.set(key, String(value));
|
|
28
|
-
},
|
|
29
|
-
removeItem(key) {
|
|
30
|
-
lsStorage.delete(key);
|
|
31
|
-
},
|
|
32
|
-
clear() {
|
|
33
|
-
lsStorage.clear();
|
|
34
|
-
},
|
|
35
|
-
get length() {
|
|
36
|
-
return lsStorage.size;
|
|
37
|
-
},
|
|
38
|
-
key(index) {
|
|
39
|
-
return Array.from(lsStorage.keys())[index] || null;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
try {
|
|
43
|
-
Object.defineProperty(window, "localStorage", {
|
|
44
|
-
value: localStoragePoly,
|
|
45
|
-
writable: true,
|
|
46
|
-
configurable: true
|
|
47
|
-
});
|
|
48
|
-
} catch {
|
|
49
|
-
window.localStorage = localStoragePoly;
|
|
209
|
+
let binary = "";
|
|
210
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
211
|
+
const byte = bytes[i];
|
|
212
|
+
if (byte !== void 0) {
|
|
213
|
+
binary += String.fromCharCode(byte);
|
|
50
214
|
}
|
|
51
|
-
console.log("[HaexSpace] localStorage replaced with in-memory polyfill");
|
|
52
215
|
}
|
|
216
|
+
return btoa(binary);
|
|
53
217
|
}
|
|
54
|
-
function
|
|
55
|
-
if (typeof
|
|
56
|
-
return;
|
|
218
|
+
function base64ToArrayBuffer(base64) {
|
|
219
|
+
if (typeof Buffer !== "undefined") {
|
|
220
|
+
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
57
221
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
222
|
+
const binary = atob(base64);
|
|
223
|
+
const bytes = new Uint8Array(binary.length);
|
|
224
|
+
for (let i = 0; i < binary.length; i++) {
|
|
225
|
+
bytes[i] = binary.charCodeAt(i);
|
|
226
|
+
}
|
|
227
|
+
return bytes;
|
|
228
|
+
}
|
|
229
|
+
var PBKDF2_ITERATIONS, KEY_LENGTH, ALGORITHM;
|
|
230
|
+
var init_vaultKey = __esm({
|
|
231
|
+
"src/crypto/vaultKey.ts"() {
|
|
232
|
+
PBKDF2_ITERATIONS = 6e5;
|
|
233
|
+
KEY_LENGTH = 256;
|
|
234
|
+
ALGORITHM = "AES-GCM";
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// src/crypto/userKeypair.ts
|
|
239
|
+
var userKeypair_exports = {};
|
|
240
|
+
__export(userKeypair_exports, {
|
|
241
|
+
KEY_AGREEMENT_ALGO: () => exports.KEY_AGREEMENT_ALGO,
|
|
242
|
+
SIGNING_ALGO: () => exports.SIGNING_ALGO,
|
|
243
|
+
decryptPrivateKeyAsync: () => decryptPrivateKeyAsync,
|
|
244
|
+
encryptPrivateKeyAsync: () => encryptPrivateKeyAsync,
|
|
245
|
+
exportUserKeypairAsync: () => exportUserKeypairAsync,
|
|
246
|
+
generateUserKeypairAsync: () => generateUserKeypairAsync,
|
|
247
|
+
importPrivateKeyForKeyAgreementAsync: () => importPrivateKeyForKeyAgreementAsync,
|
|
248
|
+
importPublicKeyForKeyAgreementAsync: () => importPublicKeyForKeyAgreementAsync,
|
|
249
|
+
importUserPrivateKeyAsync: () => importUserPrivateKeyAsync,
|
|
250
|
+
importUserPublicKeyAsync: () => importUserPublicKeyAsync
|
|
251
|
+
});
|
|
252
|
+
async function generateUserKeypairAsync() {
|
|
253
|
+
const keypair = await crypto.subtle.generateKey(exports.SIGNING_ALGO, true, ["sign", "verify"]);
|
|
254
|
+
return { publicKey: keypair.publicKey, privateKey: keypair.privateKey };
|
|
255
|
+
}
|
|
256
|
+
async function exportUserKeypairAsync(keypair) {
|
|
257
|
+
const pub = await crypto.subtle.exportKey("spki", keypair.publicKey);
|
|
258
|
+
const priv = await crypto.subtle.exportKey("pkcs8", keypair.privateKey);
|
|
259
|
+
return { publicKey: arrayBufferToBase64(pub), privateKey: arrayBufferToBase64(priv) };
|
|
260
|
+
}
|
|
261
|
+
async function importUserPublicKeyAsync(base64) {
|
|
262
|
+
return crypto.subtle.importKey("spki", base64ToArrayBuffer(base64), exports.SIGNING_ALGO, true, ["verify"]);
|
|
263
|
+
}
|
|
264
|
+
async function importUserPrivateKeyAsync(base64) {
|
|
265
|
+
return crypto.subtle.importKey("pkcs8", base64ToArrayBuffer(base64), exports.SIGNING_ALGO, true, ["sign"]);
|
|
266
|
+
}
|
|
267
|
+
async function importPublicKeyForKeyAgreementAsync(base64) {
|
|
268
|
+
return crypto.subtle.importKey("spki", base64ToArrayBuffer(base64), exports.KEY_AGREEMENT_ALGO, true, []);
|
|
269
|
+
}
|
|
270
|
+
async function importPrivateKeyForKeyAgreementAsync(base64) {
|
|
271
|
+
return crypto.subtle.importKey("pkcs8", base64ToArrayBuffer(base64), exports.KEY_AGREEMENT_ALGO, true, ["deriveBits"]);
|
|
272
|
+
}
|
|
273
|
+
async function encryptPrivateKeyAsync(privateKeyBase64, password) {
|
|
274
|
+
const salt = crypto.getRandomValues(new Uint8Array(32));
|
|
275
|
+
const derivedKey = await deriveKeyFromPassword(password, salt);
|
|
276
|
+
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
277
|
+
const encrypted = await crypto.subtle.encrypt(
|
|
278
|
+
{ name: "AES-GCM", iv: nonce },
|
|
279
|
+
derivedKey,
|
|
280
|
+
new TextEncoder().encode(privateKeyBase64)
|
|
281
|
+
);
|
|
282
|
+
return {
|
|
283
|
+
encryptedPrivateKey: arrayBufferToBase64(encrypted),
|
|
284
|
+
nonce: arrayBufferToBase64(nonce),
|
|
285
|
+
salt: arrayBufferToBase64(salt)
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
async function decryptPrivateKeyAsync(encryptedPrivateKey, nonce, salt, password) {
|
|
289
|
+
const derivedKey = await deriveKeyFromPassword(password, base64ToArrayBuffer(salt));
|
|
290
|
+
const decrypted = await crypto.subtle.decrypt(
|
|
291
|
+
{ name: "AES-GCM", iv: base64ToArrayBuffer(nonce) },
|
|
292
|
+
derivedKey,
|
|
293
|
+
base64ToArrayBuffer(encryptedPrivateKey)
|
|
294
|
+
);
|
|
295
|
+
return new TextDecoder().decode(decrypted);
|
|
296
|
+
}
|
|
297
|
+
exports.SIGNING_ALGO = void 0; exports.KEY_AGREEMENT_ALGO = void 0;
|
|
298
|
+
var init_userKeypair = __esm({
|
|
299
|
+
"src/crypto/userKeypair.ts"() {
|
|
300
|
+
init_vaultKey();
|
|
301
|
+
exports.SIGNING_ALGO = { name: "ECDSA", namedCurve: "P-256" };
|
|
302
|
+
exports.KEY_AGREEMENT_ALGO = { name: "ECDH", namedCurve: "P-256" };
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// src/polyfills/localStorage.ts
|
|
307
|
+
function installLocalStoragePolyfill() {
|
|
308
|
+
if (typeof window === "undefined") {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
console.log("[HaexSpace] Storage Polyfill loading immediately");
|
|
312
|
+
let localStorageWorks = false;
|
|
313
|
+
try {
|
|
314
|
+
const testKey = "__ls_test__";
|
|
315
|
+
localStorage.setItem(testKey, testKey);
|
|
316
|
+
localStorage.removeItem(testKey);
|
|
317
|
+
localStorageWorks = true;
|
|
318
|
+
} catch {
|
|
319
|
+
console.warn("[HaexSpace] localStorage blocked \u2013 using in-memory fallback");
|
|
320
|
+
}
|
|
321
|
+
if (!localStorageWorks) {
|
|
322
|
+
const lsStorage = /* @__PURE__ */ new Map();
|
|
323
|
+
const localStoragePoly = {
|
|
324
|
+
getItem(key) {
|
|
325
|
+
return lsStorage.get(key) || null;
|
|
326
|
+
},
|
|
327
|
+
setItem(key, value) {
|
|
328
|
+
lsStorage.set(key, String(value));
|
|
329
|
+
},
|
|
330
|
+
removeItem(key) {
|
|
331
|
+
lsStorage.delete(key);
|
|
332
|
+
},
|
|
333
|
+
clear() {
|
|
334
|
+
lsStorage.clear();
|
|
335
|
+
},
|
|
336
|
+
get length() {
|
|
337
|
+
return lsStorage.size;
|
|
338
|
+
},
|
|
339
|
+
key(index) {
|
|
340
|
+
return Array.from(lsStorage.keys())[index] || null;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
try {
|
|
344
|
+
Object.defineProperty(window, "localStorage", {
|
|
345
|
+
value: localStoragePoly,
|
|
346
|
+
writable: true,
|
|
347
|
+
configurable: true
|
|
348
|
+
});
|
|
349
|
+
} catch {
|
|
350
|
+
window.localStorage = localStoragePoly;
|
|
351
|
+
}
|
|
352
|
+
console.log("[HaexSpace] localStorage replaced with in-memory polyfill");
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function installSessionStoragePolyfill() {
|
|
356
|
+
if (typeof window === "undefined") {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
const sessionStoragePoly = {
|
|
361
|
+
getItem() {
|
|
61
362
|
return null;
|
|
62
363
|
},
|
|
63
364
|
setItem() {
|
|
@@ -643,404 +944,187 @@ var LOCALSEND_COMMANDS = {
|
|
|
643
944
|
/** Get current settings */
|
|
644
945
|
getSettings: "localsend_get_settings",
|
|
645
946
|
/** Update settings */
|
|
646
|
-
setSettings: "localsend_set_settings",
|
|
647
|
-
// Discovery (desktop only)
|
|
648
|
-
/** Start device discovery via multicast UDP */
|
|
649
|
-
startDiscovery: "localsend_start_discovery",
|
|
650
|
-
/** Stop device discovery */
|
|
651
|
-
stopDiscovery: "localsend_stop_discovery",
|
|
652
|
-
/** Get list of discovered devices */
|
|
653
|
-
getDevices: "localsend_get_devices",
|
|
654
|
-
// Network scan (mobile only)
|
|
655
|
-
/** Scan network for devices via HTTP */
|
|
656
|
-
scanNetwork: "localsend_scan_network",
|
|
657
|
-
// Server (receiving files)
|
|
658
|
-
/** Start the HTTPS server for receiving files */
|
|
659
|
-
startServer: "localsend_start_server",
|
|
660
|
-
/** Stop the HTTPS server */
|
|
661
|
-
stopServer: "localsend_stop_server",
|
|
662
|
-
/** Get server status */
|
|
663
|
-
getServerStatus: "localsend_get_server_status",
|
|
664
|
-
/** Get pending incoming transfer requests */
|
|
665
|
-
getPendingTransfers: "localsend_get_pending_transfers",
|
|
666
|
-
/** Accept an incoming transfer */
|
|
667
|
-
acceptTransfer: "localsend_accept_transfer",
|
|
668
|
-
/** Reject an incoming transfer */
|
|
669
|
-
rejectTransfer: "localsend_reject_transfer",
|
|
670
|
-
// Client (sending files)
|
|
671
|
-
/** Prepare files for sending - collect metadata */
|
|
672
|
-
prepareFiles: "localsend_prepare_files",
|
|
673
|
-
/** Send files to a device */
|
|
674
|
-
sendFiles: "localsend_send_files",
|
|
675
|
-
/** Cancel an outgoing transfer */
|
|
676
|
-
cancelSend: "localsend_cancel_send"
|
|
677
|
-
};
|
|
678
|
-
|
|
679
|
-
// src/commands/spaces.ts
|
|
680
|
-
var SPACE_COMMANDS = {
|
|
681
|
-
/** Bulk assign rows to spaces */
|
|
682
|
-
assign: "extension_space_assign",
|
|
683
|
-
/** Bulk unassign rows from spaces */
|
|
684
|
-
unassign: "extension_space_unassign",
|
|
685
|
-
/** Get space assignments for a table */
|
|
686
|
-
getAssignments: "extension_space_get_assignments",
|
|
687
|
-
/** List all spaces the user is a member of (with decrypted names) */
|
|
688
|
-
list: "extension_space_list",
|
|
689
|
-
/** Create a new shared space */
|
|
690
|
-
create: "extension_space_create",
|
|
691
|
-
/** List available sync backends */
|
|
692
|
-
listBackends: "extension_space_list_backends"
|
|
693
|
-
};
|
|
694
|
-
|
|
695
|
-
// src/commands/index.ts
|
|
696
|
-
var TAURI_COMMANDS = {
|
|
697
|
-
database: DATABASE_COMMANDS,
|
|
698
|
-
permissions: PERMISSIONS_COMMANDS,
|
|
699
|
-
web: WEB_COMMANDS,
|
|
700
|
-
webStorage: WEB_STORAGE_COMMANDS,
|
|
701
|
-
filesystem: FILESYSTEM_COMMANDS,
|
|
702
|
-
externalBridge: EXTERNAL_BRIDGE_COMMANDS,
|
|
703
|
-
extension: EXTENSION_COMMANDS,
|
|
704
|
-
remoteStorage: REMOTE_STORAGE_COMMANDS,
|
|
705
|
-
localsend: LOCALSEND_COMMANDS,
|
|
706
|
-
spaces: SPACE_COMMANDS
|
|
707
|
-
};
|
|
708
|
-
|
|
709
|
-
// src/api/storage.ts
|
|
710
|
-
var StorageAPI = class {
|
|
711
|
-
constructor(client) {
|
|
712
|
-
this.client = client;
|
|
713
|
-
}
|
|
714
|
-
async getItem(key) {
|
|
715
|
-
return this.client.request(WEB_STORAGE_COMMANDS.getItem, { key });
|
|
716
|
-
}
|
|
717
|
-
async setItem(key, value) {
|
|
718
|
-
await this.client.request(WEB_STORAGE_COMMANDS.setItem, { key, value });
|
|
719
|
-
}
|
|
720
|
-
async removeItem(key) {
|
|
721
|
-
await this.client.request(WEB_STORAGE_COMMANDS.removeItem, { key });
|
|
722
|
-
}
|
|
723
|
-
async clear() {
|
|
724
|
-
await this.client.request(WEB_STORAGE_COMMANDS.clear);
|
|
725
|
-
}
|
|
726
|
-
async keys() {
|
|
727
|
-
return this.client.request(WEB_STORAGE_COMMANDS.keys);
|
|
728
|
-
}
|
|
729
|
-
};
|
|
730
|
-
|
|
731
|
-
// src/api/database.ts
|
|
732
|
-
var DatabaseAPI = class {
|
|
733
|
-
constructor(client) {
|
|
734
|
-
this.client = client;
|
|
735
|
-
}
|
|
736
|
-
async query(query, params) {
|
|
737
|
-
const result = await this.client.request(
|
|
738
|
-
DATABASE_COMMANDS.query,
|
|
739
|
-
{
|
|
740
|
-
query,
|
|
741
|
-
params: params || []
|
|
742
|
-
}
|
|
743
|
-
);
|
|
744
|
-
return result.rows;
|
|
745
|
-
}
|
|
746
|
-
async queryOne(query, params) {
|
|
747
|
-
const rows = await this.query(query, params);
|
|
748
|
-
return rows.length > 0 ? rows[0] ?? null : null;
|
|
749
|
-
}
|
|
750
|
-
async execute(query, params) {
|
|
751
|
-
return this.client.request(DATABASE_COMMANDS.execute, {
|
|
752
|
-
query,
|
|
753
|
-
params: params || []
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
async transaction(statements) {
|
|
757
|
-
await this.client.request(DATABASE_COMMANDS.transaction, {
|
|
758
|
-
statements
|
|
759
|
-
});
|
|
760
|
-
}
|
|
761
|
-
async createTable(tableName, columns) {
|
|
762
|
-
const query = `CREATE TABLE IF NOT EXISTS ${tableName} (${columns})`;
|
|
763
|
-
await this.execute(query);
|
|
764
|
-
}
|
|
765
|
-
async dropTable(tableName) {
|
|
766
|
-
const query = `DROP TABLE IF EXISTS ${tableName}`;
|
|
767
|
-
await this.execute(query);
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* Registers and applies extension migrations with HaexVault
|
|
771
|
-
*
|
|
772
|
-
* HaexVault will:
|
|
773
|
-
* 1. Validate all SQL statements (ensure only extension's own tables are accessed)
|
|
774
|
-
* 2. Store migrations with applied_at = NULL
|
|
775
|
-
* 3. Query pending migrations sorted by name
|
|
776
|
-
* 4. Apply pending migrations and set up CRDT triggers
|
|
777
|
-
* 5. Mark successful migrations with applied_at timestamp
|
|
778
|
-
*
|
|
779
|
-
* @param extensionVersion - The version of the extension
|
|
780
|
-
* @param migrations - Array of migration objects with name and SQL content
|
|
781
|
-
* @returns Promise with migration result (applied count, already applied count, applied migration names)
|
|
782
|
-
*/
|
|
783
|
-
async registerMigrationsAsync(extensionVersion, migrations) {
|
|
784
|
-
return this.client.request(
|
|
785
|
-
DATABASE_COMMANDS.registerMigrations,
|
|
786
|
-
{
|
|
787
|
-
extensionVersion,
|
|
788
|
-
migrations
|
|
789
|
-
}
|
|
790
|
-
);
|
|
791
|
-
}
|
|
792
|
-
async insert(tableName, data) {
|
|
793
|
-
const keys = Object.keys(data);
|
|
794
|
-
const values = Object.values(data);
|
|
795
|
-
const placeholders = keys.map(() => "?").join(", ");
|
|
796
|
-
const query = `INSERT INTO ${tableName} (${keys.join(
|
|
797
|
-
", "
|
|
798
|
-
)}) VALUES (${placeholders})`;
|
|
799
|
-
const result = await this.execute(query, values);
|
|
800
|
-
return result.lastInsertId ?? -1;
|
|
801
|
-
}
|
|
802
|
-
async update(tableName, data, where, whereParams) {
|
|
803
|
-
const keys = Object.keys(data);
|
|
804
|
-
const values = Object.values(data);
|
|
805
|
-
const setClause = keys.map((key) => `${key} = ?`).join(", ");
|
|
806
|
-
const query = `UPDATE ${tableName} SET ${setClause} WHERE ${where}`;
|
|
807
|
-
const result = await this.execute(query, [
|
|
808
|
-
...values,
|
|
809
|
-
...whereParams || []
|
|
810
|
-
]);
|
|
811
|
-
return result.rowsAffected;
|
|
812
|
-
}
|
|
813
|
-
async delete(tableName, where, whereParams) {
|
|
814
|
-
const query = `DELETE FROM ${tableName} WHERE ${where}`;
|
|
815
|
-
const result = await this.execute(query, whereParams);
|
|
816
|
-
return result.rowsAffected;
|
|
817
|
-
}
|
|
818
|
-
async count(tableName, where, whereParams) {
|
|
819
|
-
const query = where ? `SELECT COUNT(*) as count FROM ${tableName} WHERE ${where}` : `SELECT COUNT(*) as count FROM ${tableName}`;
|
|
820
|
-
const result = await this.queryOne(query, whereParams);
|
|
821
|
-
return result?.count ?? 0;
|
|
822
|
-
}
|
|
823
|
-
};
|
|
824
|
-
|
|
825
|
-
// src/crypto/vaultKey.ts
|
|
826
|
-
var PBKDF2_ITERATIONS = 6e5;
|
|
827
|
-
var KEY_LENGTH = 256;
|
|
828
|
-
var ALGORITHM = "AES-GCM";
|
|
829
|
-
async function deriveKeyFromPassword(password, salt) {
|
|
830
|
-
const encoder = new TextEncoder();
|
|
831
|
-
const passwordBuffer = encoder.encode(password);
|
|
832
|
-
const saltBuffer = new Uint8Array(salt);
|
|
833
|
-
const keyMaterial = await crypto.subtle.importKey(
|
|
834
|
-
"raw",
|
|
835
|
-
passwordBuffer,
|
|
836
|
-
"PBKDF2",
|
|
837
|
-
false,
|
|
838
|
-
["deriveKey"]
|
|
839
|
-
);
|
|
840
|
-
return await crypto.subtle.deriveKey(
|
|
841
|
-
{
|
|
842
|
-
name: "PBKDF2",
|
|
843
|
-
salt: saltBuffer,
|
|
844
|
-
iterations: PBKDF2_ITERATIONS,
|
|
845
|
-
hash: "SHA-256"
|
|
846
|
-
},
|
|
847
|
-
keyMaterial,
|
|
848
|
-
{ name: ALGORITHM, length: KEY_LENGTH },
|
|
849
|
-
false,
|
|
850
|
-
// not extractable
|
|
851
|
-
["encrypt", "decrypt"]
|
|
852
|
-
);
|
|
853
|
-
}
|
|
854
|
-
function generateVaultKey() {
|
|
855
|
-
return crypto.getRandomValues(new Uint8Array(32));
|
|
856
|
-
}
|
|
857
|
-
async function encryptString(data, derivedKey) {
|
|
858
|
-
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
859
|
-
const encoder = new TextEncoder();
|
|
860
|
-
const dataBuffer = encoder.encode(data);
|
|
861
|
-
const encryptedBuffer = await crypto.subtle.encrypt(
|
|
862
|
-
{
|
|
863
|
-
name: ALGORITHM,
|
|
864
|
-
iv: nonce
|
|
865
|
-
},
|
|
866
|
-
derivedKey,
|
|
867
|
-
dataBuffer
|
|
868
|
-
);
|
|
869
|
-
return {
|
|
870
|
-
encryptedData: arrayBufferToBase64(encryptedBuffer),
|
|
871
|
-
nonce: arrayBufferToBase64(nonce)
|
|
872
|
-
};
|
|
873
|
-
}
|
|
874
|
-
async function decryptString(encryptedData, nonce, derivedKey) {
|
|
875
|
-
const encryptedBuffer = base64ToArrayBuffer(encryptedData);
|
|
876
|
-
const nonceBuffer = base64ToArrayBuffer(nonce);
|
|
877
|
-
const encryptedDataBuffer = new Uint8Array(encryptedBuffer);
|
|
878
|
-
const iv = new Uint8Array(nonceBuffer);
|
|
879
|
-
const decryptedBuffer = await crypto.subtle.decrypt(
|
|
880
|
-
{
|
|
881
|
-
name: ALGORITHM,
|
|
882
|
-
iv
|
|
883
|
-
},
|
|
884
|
-
derivedKey,
|
|
885
|
-
encryptedDataBuffer
|
|
886
|
-
);
|
|
887
|
-
const decoder = new TextDecoder();
|
|
888
|
-
return decoder.decode(decryptedBuffer);
|
|
889
|
-
}
|
|
890
|
-
async function encryptVaultKey(vaultKey, password) {
|
|
891
|
-
const salt = crypto.getRandomValues(new Uint8Array(32));
|
|
892
|
-
const derivedKey = await deriveKeyFromPassword(password, salt);
|
|
893
|
-
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
894
|
-
const vaultKeyBuffer = new Uint8Array(vaultKey);
|
|
895
|
-
const encryptedBuffer = await crypto.subtle.encrypt(
|
|
896
|
-
{
|
|
897
|
-
name: ALGORITHM,
|
|
898
|
-
iv: nonce
|
|
899
|
-
},
|
|
900
|
-
derivedKey,
|
|
901
|
-
vaultKeyBuffer
|
|
902
|
-
);
|
|
903
|
-
return {
|
|
904
|
-
encryptedVaultKey: arrayBufferToBase64(encryptedBuffer),
|
|
905
|
-
salt: arrayBufferToBase64(salt),
|
|
906
|
-
vaultKeyNonce: arrayBufferToBase64(nonce)
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
async function decryptVaultKey(encryptedVaultKey, salt, vaultKeyNonce, password) {
|
|
910
|
-
const encryptedBuffer = base64ToArrayBuffer(encryptedVaultKey);
|
|
911
|
-
const saltBuffer = base64ToArrayBuffer(salt);
|
|
912
|
-
const nonceBuffer = base64ToArrayBuffer(vaultKeyNonce);
|
|
913
|
-
const derivedKey = await deriveKeyFromPassword(password, saltBuffer);
|
|
914
|
-
const encryptedData = new Uint8Array(encryptedBuffer);
|
|
915
|
-
const iv = new Uint8Array(nonceBuffer);
|
|
916
|
-
const decryptedBuffer = await crypto.subtle.decrypt(
|
|
917
|
-
{
|
|
918
|
-
name: ALGORITHM,
|
|
919
|
-
iv
|
|
920
|
-
},
|
|
921
|
-
derivedKey,
|
|
922
|
-
encryptedData
|
|
923
|
-
);
|
|
924
|
-
return new Uint8Array(decryptedBuffer);
|
|
925
|
-
}
|
|
926
|
-
async function decryptVaultName(encryptedVaultName, vaultNameNonce, vaultNameSalt, password) {
|
|
927
|
-
const saltBuffer = base64ToArrayBuffer(vaultNameSalt);
|
|
928
|
-
const derivedKey = await deriveKeyFromPassword(password, saltBuffer);
|
|
929
|
-
return decryptString(encryptedVaultName, vaultNameNonce, derivedKey);
|
|
930
|
-
}
|
|
931
|
-
async function encryptCrdtData(data, vaultKey) {
|
|
932
|
-
const vaultKeyBuffer = new Uint8Array(vaultKey);
|
|
933
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
934
|
-
"raw",
|
|
935
|
-
vaultKeyBuffer,
|
|
936
|
-
{ name: ALGORITHM },
|
|
937
|
-
false,
|
|
938
|
-
["encrypt"]
|
|
939
|
-
);
|
|
940
|
-
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
941
|
-
const encoder = new TextEncoder();
|
|
942
|
-
const dataBuffer = encoder.encode(JSON.stringify(data));
|
|
943
|
-
const encryptedBuffer = await crypto.subtle.encrypt(
|
|
944
|
-
{
|
|
945
|
-
name: ALGORITHM,
|
|
946
|
-
iv: nonce
|
|
947
|
-
},
|
|
948
|
-
cryptoKey,
|
|
949
|
-
dataBuffer
|
|
950
|
-
);
|
|
951
|
-
return {
|
|
952
|
-
encryptedData: arrayBufferToBase64(encryptedBuffer),
|
|
953
|
-
nonce: arrayBufferToBase64(nonce)
|
|
954
|
-
};
|
|
955
|
-
}
|
|
956
|
-
async function wrapKey(keyToWrap, wrappingKey) {
|
|
957
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
958
|
-
"raw",
|
|
959
|
-
new Uint8Array(wrappingKey),
|
|
960
|
-
{ name: ALGORITHM },
|
|
961
|
-
false,
|
|
962
|
-
["encrypt"]
|
|
963
|
-
);
|
|
964
|
-
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
965
|
-
const ciphertext = await crypto.subtle.encrypt(
|
|
966
|
-
{ name: ALGORITHM, iv: nonce },
|
|
967
|
-
cryptoKey,
|
|
968
|
-
new Uint8Array(keyToWrap)
|
|
969
|
-
);
|
|
970
|
-
const result = new Uint8Array(12 + ciphertext.byteLength);
|
|
971
|
-
result.set(nonce, 0);
|
|
972
|
-
result.set(new Uint8Array(ciphertext), 12);
|
|
973
|
-
return result;
|
|
974
|
-
}
|
|
975
|
-
async function unwrapKey(wrappedKey, wrappingKey) {
|
|
976
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
977
|
-
"raw",
|
|
978
|
-
new Uint8Array(wrappingKey),
|
|
979
|
-
{ name: ALGORITHM },
|
|
980
|
-
false,
|
|
981
|
-
["decrypt"]
|
|
982
|
-
);
|
|
983
|
-
const nonce = wrappedKey.slice(0, 12);
|
|
984
|
-
const ciphertext = wrappedKey.slice(12);
|
|
985
|
-
const plaintext = await crypto.subtle.decrypt(
|
|
986
|
-
{ name: ALGORITHM, iv: nonce },
|
|
987
|
-
cryptoKey,
|
|
988
|
-
ciphertext
|
|
989
|
-
);
|
|
990
|
-
return new Uint8Array(plaintext);
|
|
991
|
-
}
|
|
992
|
-
async function decryptCrdtData(encryptedData, nonce, vaultKey) {
|
|
993
|
-
const vaultKeyBuffer = new Uint8Array(vaultKey);
|
|
994
|
-
const cryptoKey = await crypto.subtle.importKey(
|
|
995
|
-
"raw",
|
|
996
|
-
vaultKeyBuffer,
|
|
997
|
-
{ name: ALGORITHM },
|
|
998
|
-
false,
|
|
999
|
-
["decrypt"]
|
|
1000
|
-
);
|
|
1001
|
-
const encryptedBuffer = base64ToArrayBuffer(encryptedData);
|
|
1002
|
-
const nonceBuffer = base64ToArrayBuffer(nonce);
|
|
1003
|
-
const encryptedDataBuffer = new Uint8Array(encryptedBuffer);
|
|
1004
|
-
const iv = new Uint8Array(nonceBuffer);
|
|
1005
|
-
const decryptedBuffer = await crypto.subtle.decrypt(
|
|
1006
|
-
{
|
|
1007
|
-
name: ALGORITHM,
|
|
1008
|
-
iv
|
|
1009
|
-
},
|
|
1010
|
-
cryptoKey,
|
|
1011
|
-
encryptedDataBuffer
|
|
1012
|
-
);
|
|
1013
|
-
const decoder = new TextDecoder();
|
|
1014
|
-
const jsonString = decoder.decode(decryptedBuffer);
|
|
1015
|
-
return JSON.parse(jsonString);
|
|
1016
|
-
}
|
|
1017
|
-
function arrayBufferToBase64(buffer) {
|
|
1018
|
-
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
1019
|
-
if (typeof Buffer !== "undefined") {
|
|
1020
|
-
return Buffer.from(bytes).toString("base64");
|
|
947
|
+
setSettings: "localsend_set_settings",
|
|
948
|
+
// Discovery (desktop only)
|
|
949
|
+
/** Start device discovery via multicast UDP */
|
|
950
|
+
startDiscovery: "localsend_start_discovery",
|
|
951
|
+
/** Stop device discovery */
|
|
952
|
+
stopDiscovery: "localsend_stop_discovery",
|
|
953
|
+
/** Get list of discovered devices */
|
|
954
|
+
getDevices: "localsend_get_devices",
|
|
955
|
+
// Network scan (mobile only)
|
|
956
|
+
/** Scan network for devices via HTTP */
|
|
957
|
+
scanNetwork: "localsend_scan_network",
|
|
958
|
+
// Server (receiving files)
|
|
959
|
+
/** Start the HTTPS server for receiving files */
|
|
960
|
+
startServer: "localsend_start_server",
|
|
961
|
+
/** Stop the HTTPS server */
|
|
962
|
+
stopServer: "localsend_stop_server",
|
|
963
|
+
/** Get server status */
|
|
964
|
+
getServerStatus: "localsend_get_server_status",
|
|
965
|
+
/** Get pending incoming transfer requests */
|
|
966
|
+
getPendingTransfers: "localsend_get_pending_transfers",
|
|
967
|
+
/** Accept an incoming transfer */
|
|
968
|
+
acceptTransfer: "localsend_accept_transfer",
|
|
969
|
+
/** Reject an incoming transfer */
|
|
970
|
+
rejectTransfer: "localsend_reject_transfer",
|
|
971
|
+
// Client (sending files)
|
|
972
|
+
/** Prepare files for sending - collect metadata */
|
|
973
|
+
prepareFiles: "localsend_prepare_files",
|
|
974
|
+
/** Send files to a device */
|
|
975
|
+
sendFiles: "localsend_send_files",
|
|
976
|
+
/** Cancel an outgoing transfer */
|
|
977
|
+
cancelSend: "localsend_cancel_send"
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
// src/commands/spaces.ts
|
|
981
|
+
var SPACE_COMMANDS = {
|
|
982
|
+
/** Bulk assign rows to spaces */
|
|
983
|
+
assign: "extension_space_assign",
|
|
984
|
+
/** Bulk unassign rows from spaces */
|
|
985
|
+
unassign: "extension_space_unassign",
|
|
986
|
+
/** Get space assignments for a table */
|
|
987
|
+
getAssignments: "extension_space_get_assignments",
|
|
988
|
+
/** List all spaces the user is a member of (with decrypted names) */
|
|
989
|
+
list: "extension_space_list",
|
|
990
|
+
/** Create a new shared space */
|
|
991
|
+
create: "extension_space_create",
|
|
992
|
+
/** List available sync backends */
|
|
993
|
+
listBackends: "extension_space_list_backends"
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
// src/commands/index.ts
|
|
997
|
+
var TAURI_COMMANDS = {
|
|
998
|
+
database: DATABASE_COMMANDS,
|
|
999
|
+
permissions: PERMISSIONS_COMMANDS,
|
|
1000
|
+
web: WEB_COMMANDS,
|
|
1001
|
+
webStorage: WEB_STORAGE_COMMANDS,
|
|
1002
|
+
filesystem: FILESYSTEM_COMMANDS,
|
|
1003
|
+
externalBridge: EXTERNAL_BRIDGE_COMMANDS,
|
|
1004
|
+
extension: EXTENSION_COMMANDS,
|
|
1005
|
+
remoteStorage: REMOTE_STORAGE_COMMANDS,
|
|
1006
|
+
localsend: LOCALSEND_COMMANDS,
|
|
1007
|
+
spaces: SPACE_COMMANDS
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
// src/api/storage.ts
|
|
1011
|
+
var StorageAPI = class {
|
|
1012
|
+
constructor(client) {
|
|
1013
|
+
this.client = client;
|
|
1021
1014
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
const byte = bytes[i];
|
|
1025
|
-
if (byte !== void 0) {
|
|
1026
|
-
binary += String.fromCharCode(byte);
|
|
1027
|
-
}
|
|
1015
|
+
async getItem(key) {
|
|
1016
|
+
return this.client.request(WEB_STORAGE_COMMANDS.getItem, { key });
|
|
1028
1017
|
}
|
|
1029
|
-
|
|
1030
|
-
}
|
|
1031
|
-
function base64ToArrayBuffer(base64) {
|
|
1032
|
-
if (typeof Buffer !== "undefined") {
|
|
1033
|
-
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
1018
|
+
async setItem(key, value) {
|
|
1019
|
+
await this.client.request(WEB_STORAGE_COMMANDS.setItem, { key, value });
|
|
1034
1020
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
for (let i = 0; i < binary.length; i++) {
|
|
1038
|
-
bytes[i] = binary.charCodeAt(i);
|
|
1021
|
+
async removeItem(key) {
|
|
1022
|
+
await this.client.request(WEB_STORAGE_COMMANDS.removeItem, { key });
|
|
1039
1023
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1024
|
+
async clear() {
|
|
1025
|
+
await this.client.request(WEB_STORAGE_COMMANDS.clear);
|
|
1026
|
+
}
|
|
1027
|
+
async keys() {
|
|
1028
|
+
return this.client.request(WEB_STORAGE_COMMANDS.keys);
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
|
|
1032
|
+
// src/api/database.ts
|
|
1033
|
+
var DatabaseAPI = class {
|
|
1034
|
+
constructor(client) {
|
|
1035
|
+
this.client = client;
|
|
1036
|
+
}
|
|
1037
|
+
async query(query, params) {
|
|
1038
|
+
const result = await this.client.request(
|
|
1039
|
+
DATABASE_COMMANDS.query,
|
|
1040
|
+
{
|
|
1041
|
+
query,
|
|
1042
|
+
params: params || []
|
|
1043
|
+
}
|
|
1044
|
+
);
|
|
1045
|
+
return result.rows;
|
|
1046
|
+
}
|
|
1047
|
+
async queryOne(query, params) {
|
|
1048
|
+
const rows = await this.query(query, params);
|
|
1049
|
+
return rows.length > 0 ? rows[0] ?? null : null;
|
|
1050
|
+
}
|
|
1051
|
+
async execute(query, params) {
|
|
1052
|
+
return this.client.request(DATABASE_COMMANDS.execute, {
|
|
1053
|
+
query,
|
|
1054
|
+
params: params || []
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
async transaction(statements) {
|
|
1058
|
+
await this.client.request(DATABASE_COMMANDS.transaction, {
|
|
1059
|
+
statements
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
async createTable(tableName, columns) {
|
|
1063
|
+
const query = `CREATE TABLE IF NOT EXISTS ${tableName} (${columns})`;
|
|
1064
|
+
await this.execute(query);
|
|
1065
|
+
}
|
|
1066
|
+
async dropTable(tableName) {
|
|
1067
|
+
const query = `DROP TABLE IF EXISTS ${tableName}`;
|
|
1068
|
+
await this.execute(query);
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* Registers and applies extension migrations with HaexVault
|
|
1072
|
+
*
|
|
1073
|
+
* HaexVault will:
|
|
1074
|
+
* 1. Validate all SQL statements (ensure only extension's own tables are accessed)
|
|
1075
|
+
* 2. Store migrations with applied_at = NULL
|
|
1076
|
+
* 3. Query pending migrations sorted by name
|
|
1077
|
+
* 4. Apply pending migrations and set up CRDT triggers
|
|
1078
|
+
* 5. Mark successful migrations with applied_at timestamp
|
|
1079
|
+
*
|
|
1080
|
+
* @param extensionVersion - The version of the extension
|
|
1081
|
+
* @param migrations - Array of migration objects with name and SQL content
|
|
1082
|
+
* @returns Promise with migration result (applied count, already applied count, applied migration names)
|
|
1083
|
+
*/
|
|
1084
|
+
async registerMigrationsAsync(extensionVersion, migrations) {
|
|
1085
|
+
return this.client.request(
|
|
1086
|
+
DATABASE_COMMANDS.registerMigrations,
|
|
1087
|
+
{
|
|
1088
|
+
extensionVersion,
|
|
1089
|
+
migrations
|
|
1090
|
+
}
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
async insert(tableName, data) {
|
|
1094
|
+
const keys = Object.keys(data);
|
|
1095
|
+
const values = Object.values(data);
|
|
1096
|
+
const placeholders = keys.map(() => "?").join(", ");
|
|
1097
|
+
const query = `INSERT INTO ${tableName} (${keys.join(
|
|
1098
|
+
", "
|
|
1099
|
+
)}) VALUES (${placeholders})`;
|
|
1100
|
+
const result = await this.execute(query, values);
|
|
1101
|
+
return result.lastInsertId ?? -1;
|
|
1102
|
+
}
|
|
1103
|
+
async update(tableName, data, where, whereParams) {
|
|
1104
|
+
const keys = Object.keys(data);
|
|
1105
|
+
const values = Object.values(data);
|
|
1106
|
+
const setClause = keys.map((key) => `${key} = ?`).join(", ");
|
|
1107
|
+
const query = `UPDATE ${tableName} SET ${setClause} WHERE ${where}`;
|
|
1108
|
+
const result = await this.execute(query, [
|
|
1109
|
+
...values,
|
|
1110
|
+
...whereParams || []
|
|
1111
|
+
]);
|
|
1112
|
+
return result.rowsAffected;
|
|
1113
|
+
}
|
|
1114
|
+
async delete(tableName, where, whereParams) {
|
|
1115
|
+
const query = `DELETE FROM ${tableName} WHERE ${where}`;
|
|
1116
|
+
const result = await this.execute(query, whereParams);
|
|
1117
|
+
return result.rowsAffected;
|
|
1118
|
+
}
|
|
1119
|
+
async count(tableName, where, whereParams) {
|
|
1120
|
+
const query = where ? `SELECT COUNT(*) as count FROM ${tableName} WHERE ${where}` : `SELECT COUNT(*) as count FROM ${tableName}`;
|
|
1121
|
+
const result = await this.queryOne(query, whereParams);
|
|
1122
|
+
return result?.count ?? 0;
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1042
1125
|
|
|
1043
1126
|
// src/api/filesystem.ts
|
|
1127
|
+
init_vaultKey();
|
|
1044
1128
|
var FilesystemAPI = class {
|
|
1045
1129
|
constructor(client) {
|
|
1046
1130
|
this.client = client;
|
|
@@ -1426,6 +1510,7 @@ var PermissionsAPI = class {
|
|
|
1426
1510
|
};
|
|
1427
1511
|
|
|
1428
1512
|
// src/api/remoteStorage.ts
|
|
1513
|
+
init_vaultKey();
|
|
1429
1514
|
var RemoteStorageAPI = class {
|
|
1430
1515
|
constructor(client) {
|
|
1431
1516
|
this.client = client;
|
|
@@ -2848,61 +2933,174 @@ async function verifyExtensionSignature(files, manifest) {
|
|
|
2848
2933
|
}
|
|
2849
2934
|
}
|
|
2850
2935
|
|
|
2851
|
-
// src/
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2936
|
+
// src/index.ts
|
|
2937
|
+
init_vaultKey();
|
|
2938
|
+
init_userKeypair();
|
|
2939
|
+
|
|
2940
|
+
// src/crypto/didKey.ts
|
|
2941
|
+
init_userKeypair();
|
|
2942
|
+
init_vaultKey();
|
|
2943
|
+
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
2944
|
+
function base58btcEncode(bytes) {
|
|
2945
|
+
let zeros = 0;
|
|
2946
|
+
for (const b of bytes) {
|
|
2947
|
+
if (b !== 0) break;
|
|
2948
|
+
zeros++;
|
|
2949
|
+
}
|
|
2950
|
+
const digits = [];
|
|
2951
|
+
for (const b of bytes) {
|
|
2952
|
+
let carry = b;
|
|
2953
|
+
for (let j = 0; j < digits.length; j++) {
|
|
2954
|
+
carry += digits[j] << 8;
|
|
2955
|
+
digits[j] = carry % 58;
|
|
2956
|
+
carry = carry / 58 | 0;
|
|
2957
|
+
}
|
|
2958
|
+
while (carry > 0) {
|
|
2959
|
+
digits.push(carry % 58);
|
|
2960
|
+
carry = carry / 58 | 0;
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
return "1".repeat(zeros) + digits.reverse().map((d) => BASE58_ALPHABET[d]).join("");
|
|
2964
|
+
}
|
|
2965
|
+
function base58btcDecode(str) {
|
|
2966
|
+
let zeros = 0;
|
|
2967
|
+
for (const c of str) {
|
|
2968
|
+
if (c !== "1") break;
|
|
2969
|
+
zeros++;
|
|
2970
|
+
}
|
|
2971
|
+
const bytes = [];
|
|
2972
|
+
for (const c of str) {
|
|
2973
|
+
const value = BASE58_ALPHABET.indexOf(c);
|
|
2974
|
+
if (value === -1) throw new Error(`Invalid base58 character: ${c}`);
|
|
2975
|
+
let carry = value;
|
|
2976
|
+
for (let j = 0; j < bytes.length; j++) {
|
|
2977
|
+
carry += bytes[j] * 58;
|
|
2978
|
+
bytes[j] = carry & 255;
|
|
2979
|
+
carry >>= 8;
|
|
2980
|
+
}
|
|
2981
|
+
while (carry > 0) {
|
|
2982
|
+
bytes.push(carry & 255);
|
|
2983
|
+
carry >>= 8;
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
const result = new Uint8Array(zeros + bytes.length);
|
|
2987
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
2988
|
+
result[zeros + i] = bytes[bytes.length - 1 - i];
|
|
2989
|
+
}
|
|
2990
|
+
return result;
|
|
2865
2991
|
}
|
|
2866
|
-
|
|
2867
|
-
|
|
2992
|
+
function compressP256Point(uncompressed) {
|
|
2993
|
+
if (uncompressed.length !== 65 || uncompressed[0] !== 4) {
|
|
2994
|
+
throw new Error("Expected 65-byte uncompressed P-256 point (0x04 prefix)");
|
|
2995
|
+
}
|
|
2996
|
+
const x = uncompressed.slice(1, 33);
|
|
2997
|
+
const yLastByte = uncompressed[64];
|
|
2998
|
+
const prefix = (yLastByte & 1) === 0 ? 2 : 3;
|
|
2999
|
+
const compressed = new Uint8Array(33);
|
|
3000
|
+
compressed[0] = prefix;
|
|
3001
|
+
compressed.set(x, 1);
|
|
3002
|
+
return compressed;
|
|
3003
|
+
}
|
|
3004
|
+
function decompressP256Point(compressed) {
|
|
3005
|
+
if (compressed.length !== 33 || compressed[0] !== 2 && compressed[0] !== 3) {
|
|
3006
|
+
throw new Error("Expected 33-byte compressed P-256 point");
|
|
3007
|
+
}
|
|
3008
|
+
const isOdd = compressed[0] === 3;
|
|
3009
|
+
const x = bytesToBigInt(compressed.slice(1));
|
|
3010
|
+
const p = BigInt("0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff");
|
|
3011
|
+
const b = BigInt("0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b");
|
|
3012
|
+
const a = p - 3n;
|
|
3013
|
+
const ySquared = (modPow(x, 3n, p) + a * x + b) % p;
|
|
3014
|
+
let y = modSqrt(ySquared, p);
|
|
3015
|
+
const yIsOdd = (y & 1n) === 1n;
|
|
3016
|
+
if (isOdd !== yIsOdd) {
|
|
3017
|
+
y = p - y;
|
|
3018
|
+
}
|
|
3019
|
+
const uncompressed = new Uint8Array(65);
|
|
3020
|
+
uncompressed[0] = 4;
|
|
3021
|
+
uncompressed.set(bigIntToBytes(x, 32), 1);
|
|
3022
|
+
uncompressed.set(bigIntToBytes(y, 32), 33);
|
|
3023
|
+
return uncompressed;
|
|
3024
|
+
}
|
|
3025
|
+
function bytesToBigInt(bytes) {
|
|
3026
|
+
let result = 0n;
|
|
3027
|
+
for (const b of bytes) {
|
|
3028
|
+
result = result << 8n | BigInt(b);
|
|
3029
|
+
}
|
|
3030
|
+
return result;
|
|
2868
3031
|
}
|
|
2869
|
-
|
|
2870
|
-
|
|
3032
|
+
function bigIntToBytes(n, length) {
|
|
3033
|
+
const bytes = new Uint8Array(length);
|
|
3034
|
+
let val = n;
|
|
3035
|
+
for (let i = length - 1; i >= 0; i--) {
|
|
3036
|
+
bytes[i] = Number(val & 0xffn);
|
|
3037
|
+
val >>= 8n;
|
|
3038
|
+
}
|
|
3039
|
+
return bytes;
|
|
2871
3040
|
}
|
|
2872
|
-
|
|
2873
|
-
|
|
3041
|
+
function modPow(base, exp, mod) {
|
|
3042
|
+
let result = 1n;
|
|
3043
|
+
base = base % mod;
|
|
3044
|
+
while (exp > 0n) {
|
|
3045
|
+
if (exp & 1n) result = result * base % mod;
|
|
3046
|
+
exp >>= 1n;
|
|
3047
|
+
base = base * base % mod;
|
|
3048
|
+
}
|
|
3049
|
+
return result;
|
|
2874
3050
|
}
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
3051
|
+
function modSqrt(a, p) {
|
|
3052
|
+
return modPow(a, (p + 1n) / 4n, p);
|
|
3053
|
+
}
|
|
3054
|
+
var P256_MULTICODEC_PREFIX = new Uint8Array([128, 36]);
|
|
3055
|
+
async function publicKeyToDidKeyAsync(publicKeyBase64) {
|
|
3056
|
+
const cryptoKey = await importUserPublicKeyAsync(publicKeyBase64);
|
|
3057
|
+
const rawBytes = new Uint8Array(await crypto.subtle.exportKey("raw", cryptoKey));
|
|
3058
|
+
const compressed = compressP256Point(rawBytes);
|
|
3059
|
+
const multicodecBytes = new Uint8Array(P256_MULTICODEC_PREFIX.length + compressed.length);
|
|
3060
|
+
multicodecBytes.set(P256_MULTICODEC_PREFIX);
|
|
3061
|
+
multicodecBytes.set(compressed, P256_MULTICODEC_PREFIX.length);
|
|
3062
|
+
return `did:key:z${base58btcEncode(multicodecBytes)}`;
|
|
3063
|
+
}
|
|
3064
|
+
async function didKeyToPublicKeyAsync(did) {
|
|
3065
|
+
if (!did.startsWith("did:key:z")) {
|
|
3066
|
+
throw new Error("Only did:key with base58-btc multibase (z prefix) is supported");
|
|
3067
|
+
}
|
|
3068
|
+
const multicodecBytes = base58btcDecode(did.slice("did:key:z".length));
|
|
3069
|
+
if (multicodecBytes[0] !== P256_MULTICODEC_PREFIX[0] || multicodecBytes[1] !== P256_MULTICODEC_PREFIX[1]) {
|
|
3070
|
+
throw new Error("Unsupported key type in did:key (expected P-256)");
|
|
3071
|
+
}
|
|
3072
|
+
const compressed = multicodecBytes.slice(P256_MULTICODEC_PREFIX.length);
|
|
3073
|
+
const uncompressed = decompressP256Point(compressed);
|
|
3074
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
3075
|
+
"raw",
|
|
3076
|
+
uncompressed.buffer,
|
|
3077
|
+
{ name: "ECDSA", namedCurve: "P-256" },
|
|
3078
|
+
true,
|
|
3079
|
+
["verify"]
|
|
2883
3080
|
);
|
|
3081
|
+
const spki = await crypto.subtle.exportKey("spki", cryptoKey);
|
|
3082
|
+
return arrayBufferToBase64(spki);
|
|
3083
|
+
}
|
|
3084
|
+
async function generateIdentityAsync() {
|
|
3085
|
+
const { generateUserKeypairAsync: generateUserKeypairAsync2, exportUserKeypairAsync: exportUserKeypairAsync2 } = await Promise.resolve().then(() => (init_userKeypair(), userKeypair_exports));
|
|
3086
|
+
const keypair = await generateUserKeypairAsync2();
|
|
3087
|
+
const exported = await exportUserKeypairAsync2(keypair);
|
|
3088
|
+
const did = await publicKeyToDidKeyAsync(exported.publicKey);
|
|
2884
3089
|
return {
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
3090
|
+
did,
|
|
3091
|
+
publicKeyBase64: exported.publicKey,
|
|
3092
|
+
privateKeyBase64: exported.privateKey
|
|
2888
3093
|
};
|
|
2889
3094
|
}
|
|
2890
|
-
async function decryptPrivateKeyAsync(encryptedPrivateKey, nonce, salt, password) {
|
|
2891
|
-
const derivedKey = await deriveKeyFromPassword(password, base64ToArrayBuffer(salt));
|
|
2892
|
-
const decrypted = await crypto.subtle.decrypt(
|
|
2893
|
-
{ name: "AES-GCM", iv: base64ToArrayBuffer(nonce) },
|
|
2894
|
-
derivedKey,
|
|
2895
|
-
base64ToArrayBuffer(encryptedPrivateKey)
|
|
2896
|
-
);
|
|
2897
|
-
return new TextDecoder().decode(decrypted);
|
|
2898
|
-
}
|
|
2899
3095
|
|
|
2900
3096
|
// src/crypto/spaceKey.ts
|
|
3097
|
+
init_userKeypair();
|
|
3098
|
+
init_vaultKey();
|
|
2901
3099
|
function generateSpaceKey() {
|
|
2902
3100
|
return generateVaultKey();
|
|
2903
3101
|
}
|
|
2904
3102
|
async function encryptSpaceKeyForRecipientAsync(spaceKey, recipientPublicKeyBase64) {
|
|
2905
|
-
const ephemeral = await crypto.subtle.generateKey(KEY_AGREEMENT_ALGO, true, ["deriveBits"]);
|
|
3103
|
+
const ephemeral = await crypto.subtle.generateKey(exports.KEY_AGREEMENT_ALGO, true, ["deriveBits"]);
|
|
2906
3104
|
const recipientKey = await importPublicKeyForKeyAgreementAsync(recipientPublicKeyBase64);
|
|
2907
3105
|
const sharedBits = await crypto.subtle.deriveBits(
|
|
2908
3106
|
{ name: "ECDH", public: recipientKey },
|
|
@@ -2934,7 +3132,7 @@ async function decryptSpaceKeyAsync(encrypted, ownPrivateKeyBase64) {
|
|
|
2934
3132
|
const ephPubKey = await crypto.subtle.importKey(
|
|
2935
3133
|
"spki",
|
|
2936
3134
|
base64ToArrayBuffer(encrypted.ephemeralPublicKey),
|
|
2937
|
-
KEY_AGREEMENT_ALGO,
|
|
3135
|
+
exports.KEY_AGREEMENT_ALGO,
|
|
2938
3136
|
true,
|
|
2939
3137
|
[]
|
|
2940
3138
|
);
|
|
@@ -2985,7 +3183,45 @@ async function decryptSpaceNameAsync(spaceKey, encryptedName, nameNonce) {
|
|
|
2985
3183
|
return decryptString(encryptedName, nameNonce, cryptoKey);
|
|
2986
3184
|
}
|
|
2987
3185
|
|
|
3186
|
+
// src/crypto/claims.ts
|
|
3187
|
+
init_userKeypair();
|
|
3188
|
+
async function signClaimPresentationAsync(did, publicKeyBase64, claims, privateKeyBase64) {
|
|
3189
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3190
|
+
const sortedEntries = Object.entries(claims).sort(([a], [b]) => a.localeCompare(b));
|
|
3191
|
+
const canonical = [did, timestamp, ...sortedEntries.map(([k, v]) => `${k}=${v}`)].join("\0");
|
|
3192
|
+
const privateKey = await importUserPrivateKeyAsync(privateKeyBase64);
|
|
3193
|
+
const data = new TextEncoder().encode(canonical);
|
|
3194
|
+
const sig = await crypto.subtle.sign(
|
|
3195
|
+
{ name: "ECDSA", hash: "SHA-256" },
|
|
3196
|
+
privateKey,
|
|
3197
|
+
data
|
|
3198
|
+
);
|
|
3199
|
+
return {
|
|
3200
|
+
did,
|
|
3201
|
+
publicKey: publicKeyBase64,
|
|
3202
|
+
claims,
|
|
3203
|
+
timestamp,
|
|
3204
|
+
signature: btoa(String.fromCharCode(...new Uint8Array(sig)))
|
|
3205
|
+
};
|
|
3206
|
+
}
|
|
3207
|
+
async function verifyClaimPresentationAsync(presentation) {
|
|
3208
|
+
const { did, publicKey, claims, timestamp, signature } = presentation;
|
|
3209
|
+
const sortedEntries = Object.entries(claims).sort(([a], [b]) => a.localeCompare(b));
|
|
3210
|
+
const canonical = [did, timestamp, ...sortedEntries.map(([k, v]) => `${k}=${v}`)].join("\0");
|
|
3211
|
+
const pubKey = await importUserPublicKeyAsync(publicKey);
|
|
3212
|
+
const data = new TextEncoder().encode(canonical);
|
|
3213
|
+
const sigBytes = Uint8Array.from(atob(signature), (c) => c.charCodeAt(0));
|
|
3214
|
+
return crypto.subtle.verify(
|
|
3215
|
+
{ name: "ECDSA", hash: "SHA-256" },
|
|
3216
|
+
pubKey,
|
|
3217
|
+
sigBytes,
|
|
3218
|
+
data
|
|
3219
|
+
);
|
|
3220
|
+
}
|
|
3221
|
+
|
|
2988
3222
|
// src/crypto/recordSigning.ts
|
|
3223
|
+
init_userKeypair();
|
|
3224
|
+
init_vaultKey();
|
|
2989
3225
|
function canonicalize(record) {
|
|
2990
3226
|
const parts = [
|
|
2991
3227
|
record.tableName,
|
|
@@ -3048,6 +3284,7 @@ async function verifySpaceChallengeAsync(spaceId, timestamp, signatureBase64, pu
|
|
|
3048
3284
|
}
|
|
3049
3285
|
|
|
3050
3286
|
// src/crypto/passkey.ts
|
|
3287
|
+
init_vaultKey();
|
|
3051
3288
|
function toArrayBuffer(data) {
|
|
3052
3289
|
if (data instanceof ArrayBuffer) {
|
|
3053
3290
|
return data;
|
|
@@ -3229,14 +3466,12 @@ exports.HAEXSPACE_MESSAGE_TYPES = HAEXSPACE_MESSAGE_TYPES;
|
|
|
3229
3466
|
exports.HAEXTENSION_EVENTS = HAEXTENSION_EVENTS;
|
|
3230
3467
|
exports.HaexVaultSdk = HaexVaultSdk;
|
|
3231
3468
|
exports.HaexVaultSdkError = HaexVaultSdkError;
|
|
3232
|
-
exports.KEY_AGREEMENT_ALGO = KEY_AGREEMENT_ALGO;
|
|
3233
3469
|
exports.LOCALSEND_EVENTS = LOCALSEND_EVENTS;
|
|
3234
3470
|
exports.LocalSendAPI = LocalSendAPI;
|
|
3235
3471
|
exports.PermissionErrorCode = PermissionErrorCode;
|
|
3236
3472
|
exports.PermissionStatus = PermissionStatus;
|
|
3237
3473
|
exports.PermissionsAPI = PermissionsAPI;
|
|
3238
3474
|
exports.RemoteStorageAPI = RemoteStorageAPI;
|
|
3239
|
-
exports.SIGNING_ALGO = SIGNING_ALGO;
|
|
3240
3475
|
exports.SPACE_COMMANDS = SPACE_COMMANDS;
|
|
3241
3476
|
exports.SpacesAPI = SpacesAPI;
|
|
3242
3477
|
exports.TABLE_SEPARATOR = TABLE_SEPARATOR;
|
|
@@ -3254,6 +3489,7 @@ exports.decryptString = decryptString;
|
|
|
3254
3489
|
exports.decryptVaultKey = decryptVaultKey;
|
|
3255
3490
|
exports.decryptVaultName = decryptVaultName;
|
|
3256
3491
|
exports.deriveKeyFromPassword = deriveKeyFromPassword;
|
|
3492
|
+
exports.didKeyToPublicKeyAsync = didKeyToPublicKeyAsync;
|
|
3257
3493
|
exports.encryptCrdtData = encryptCrdtData;
|
|
3258
3494
|
exports.encryptPrivateKeyAsync = encryptPrivateKeyAsync;
|
|
3259
3495
|
exports.encryptSpaceKeyForRecipientAsync = encryptSpaceKeyForRecipientAsync;
|
|
@@ -3266,6 +3502,7 @@ exports.exportPublicKeyAsync = exportPublicKeyAsync;
|
|
|
3266
3502
|
exports.exportPublicKeyCoseAsync = exportPublicKeyCoseAsync;
|
|
3267
3503
|
exports.exportUserKeypairAsync = exportUserKeypairAsync;
|
|
3268
3504
|
exports.generateCredentialId = generateCredentialId;
|
|
3505
|
+
exports.generateIdentityAsync = generateIdentityAsync;
|
|
3269
3506
|
exports.generatePasskeyPairAsync = generatePasskeyPairAsync;
|
|
3270
3507
|
exports.generateSpaceKey = generateSpaceKey;
|
|
3271
3508
|
exports.generateUserKeypairAsync = generateUserKeypairAsync;
|
|
@@ -3288,11 +3525,14 @@ exports.isExternalClientConnected = isExternalClientConnected;
|
|
|
3288
3525
|
exports.isPermissionDeniedError = isPermissionDeniedError;
|
|
3289
3526
|
exports.isPermissionError = isPermissionError;
|
|
3290
3527
|
exports.isPermissionPromptError = isPermissionPromptError;
|
|
3528
|
+
exports.publicKeyToDidKeyAsync = publicKeyToDidKeyAsync;
|
|
3529
|
+
exports.signClaimPresentationAsync = signClaimPresentationAsync;
|
|
3291
3530
|
exports.signRecordAsync = signRecordAsync;
|
|
3292
3531
|
exports.signSpaceChallengeAsync = signSpaceChallengeAsync;
|
|
3293
3532
|
exports.signWithPasskeyAsync = signWithPasskeyAsync;
|
|
3294
3533
|
exports.sortObjectKeysRecursively = sortObjectKeysRecursively;
|
|
3295
3534
|
exports.unwrapKey = unwrapKey;
|
|
3535
|
+
exports.verifyClaimPresentationAsync = verifyClaimPresentationAsync;
|
|
3296
3536
|
exports.verifyExtensionSignature = verifyExtensionSignature;
|
|
3297
3537
|
exports.verifyRecordSignatureAsync = verifyRecordSignatureAsync;
|
|
3298
3538
|
exports.verifySpaceChallengeAsync = verifySpaceChallengeAsync;
|