@haex-space/vault-sdk 2.3.1 → 2.3.4
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/index.d.mts +57 -3
- package/dist/index.d.ts +57 -3
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +93 -1
- package/dist/index.mjs.map +1 -1
- package/dist/react.js.map +1 -1
- package/dist/react.mjs.map +1 -1
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs.map +1 -1
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { H as HaexVaultClient } from './client-BIiJwbdW.mjs';
|
|
2
2
|
export { D as DatabaseAPI, F as FilesystemAPI, P as PermissionsAPI, W as WebAPI } from './client-BIiJwbdW.mjs';
|
|
3
|
-
import { H as HaexHubConfig } from './types-FE9ewl3r.mjs';
|
|
4
|
-
export { A as ApplicationContext, C as ContextChangedEvent, r as DEFAULT_TIMEOUT, m as DatabaseColumnInfo, k as DatabaseExecuteParams, i as DatabasePermission, d as DatabasePermissionRequest, j as DatabaseQueryParams, D as DatabaseQueryResult, l as DatabaseTableInfo, q as ErrorCode, e as EventCallback, a as ExtensionInfo,
|
|
3
|
+
import { E as ExtensionManifest, H as HaexHubConfig } from './types-FE9ewl3r.mjs';
|
|
4
|
+
export { A as ApplicationContext, C as ContextChangedEvent, r as DEFAULT_TIMEOUT, m as DatabaseColumnInfo, k as DatabaseExecuteParams, i as DatabasePermission, d as DatabasePermissionRequest, j as DatabaseQueryParams, D as DatabaseQueryResult, l as DatabaseTableInfo, q as ErrorCode, e as EventCallback, a as ExtensionInfo, u as HAEXTENSION_EVENTS, t as HaexHubError, h as HaexHubEvent, f as HaexHubRequest, g as HaexHubResponse, v as HaextensionEvent, P as PermissionResponse, p as PermissionStatus, n as SearchQuery, o as SearchRequestEvent, S as SearchResult, T as TABLE_SEPARATOR, W as WebRequestOptions, c as WebResponse, s as getTableName } from './types-FE9ewl3r.mjs';
|
|
5
5
|
export { H as HaextensionConfig } from './config-D_HXjsEV.mjs';
|
|
6
6
|
import 'drizzle-orm/sqlite-proxy';
|
|
7
7
|
|
|
@@ -136,6 +136,60 @@ declare const HAEXSPACE_MESSAGE_TYPES: {
|
|
|
136
136
|
};
|
|
137
137
|
type HaexspaceMessageType = (typeof HAEXSPACE_MESSAGE_TYPES)[keyof typeof HAEXSPACE_MESSAGE_TYPES];
|
|
138
138
|
|
|
139
|
+
interface VerifyResult {
|
|
140
|
+
valid: boolean;
|
|
141
|
+
error?: string;
|
|
142
|
+
}
|
|
143
|
+
interface ZipFileEntry {
|
|
144
|
+
path: string;
|
|
145
|
+
content: Uint8Array;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Sort object keys recursively for canonical JSON representation.
|
|
149
|
+
* Must match the signing implementation exactly.
|
|
150
|
+
*/
|
|
151
|
+
declare function sortObjectKeysRecursively(obj: unknown): unknown;
|
|
152
|
+
/**
|
|
153
|
+
* Convert hex string to ArrayBuffer
|
|
154
|
+
* Returns ArrayBuffer directly to avoid type issues with Uint8Array.buffer
|
|
155
|
+
*/
|
|
156
|
+
declare function hexToBytes(hex: string): ArrayBuffer;
|
|
157
|
+
/**
|
|
158
|
+
* Verify Ed25519 signature of an extension bundle.
|
|
159
|
+
*
|
|
160
|
+
* This function is browser-compatible and uses the Web Crypto API.
|
|
161
|
+
* It verifies that the extension bundle was signed with the private key
|
|
162
|
+
* corresponding to the public key in the manifest.
|
|
163
|
+
*
|
|
164
|
+
* @param files - Array of file entries from the ZIP archive
|
|
165
|
+
* @param manifest - The extension manifest (parsed from manifest.json)
|
|
166
|
+
* @returns Promise resolving to verification result
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```typescript
|
|
170
|
+
* import JSZip from 'jszip';
|
|
171
|
+
* import { verifyExtensionSignature } from '@haex-space/vault-sdk';
|
|
172
|
+
*
|
|
173
|
+
* const zip = await JSZip.loadAsync(bundleFile);
|
|
174
|
+
* const manifestContent = await zip.file('haextension/manifest.json')?.async('string');
|
|
175
|
+
* const manifest = JSON.parse(manifestContent);
|
|
176
|
+
*
|
|
177
|
+
* // Collect all files from the ZIP
|
|
178
|
+
* const files = [];
|
|
179
|
+
* for (const [path, entry] of Object.entries(zip.files)) {
|
|
180
|
+
* if (!entry.dir) {
|
|
181
|
+
* files.push({ path, content: await entry.async('uint8array') });
|
|
182
|
+
* }
|
|
183
|
+
* }
|
|
184
|
+
*
|
|
185
|
+
* const result = await verifyExtensionSignature(files, manifest);
|
|
186
|
+
* if (!result.valid) {
|
|
187
|
+
* console.error('Signature verification failed:', result.error);
|
|
188
|
+
* }
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
declare function verifyExtensionSignature(files: ZipFileEntry[], manifest: ExtensionManifest): Promise<VerifyResult>;
|
|
192
|
+
|
|
139
193
|
declare function createHaexVaultClient(config?: HaexHubConfig): HaexVaultClient;
|
|
140
194
|
|
|
141
|
-
export { HAEXSPACE_MESSAGE_TYPES, HAEXTENSION_METHODS, HaexHubConfig, HaexVaultClient, type HaexspaceMessageType, type HaextensionMethod, createHaexVaultClient, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill };
|
|
195
|
+
export { ExtensionManifest, HAEXSPACE_MESSAGE_TYPES, HAEXTENSION_METHODS, HaexHubConfig, HaexVaultClient, type HaexspaceMessageType, type HaextensionMethod, type VerifyResult, type ZipFileEntry, createHaexVaultClient, hexToBytes, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill, sortObjectKeysRecursively, verifyExtensionSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { H as HaexVaultClient } from './client-D4hDL-PR.js';
|
|
2
2
|
export { D as DatabaseAPI, F as FilesystemAPI, P as PermissionsAPI, W as WebAPI } from './client-D4hDL-PR.js';
|
|
3
|
-
import { H as HaexHubConfig } from './types-FE9ewl3r.js';
|
|
4
|
-
export { A as ApplicationContext, C as ContextChangedEvent, r as DEFAULT_TIMEOUT, m as DatabaseColumnInfo, k as DatabaseExecuteParams, i as DatabasePermission, d as DatabasePermissionRequest, j as DatabaseQueryParams, D as DatabaseQueryResult, l as DatabaseTableInfo, q as ErrorCode, e as EventCallback, a as ExtensionInfo,
|
|
3
|
+
import { E as ExtensionManifest, H as HaexHubConfig } from './types-FE9ewl3r.js';
|
|
4
|
+
export { A as ApplicationContext, C as ContextChangedEvent, r as DEFAULT_TIMEOUT, m as DatabaseColumnInfo, k as DatabaseExecuteParams, i as DatabasePermission, d as DatabasePermissionRequest, j as DatabaseQueryParams, D as DatabaseQueryResult, l as DatabaseTableInfo, q as ErrorCode, e as EventCallback, a as ExtensionInfo, u as HAEXTENSION_EVENTS, t as HaexHubError, h as HaexHubEvent, f as HaexHubRequest, g as HaexHubResponse, v as HaextensionEvent, P as PermissionResponse, p as PermissionStatus, n as SearchQuery, o as SearchRequestEvent, S as SearchResult, T as TABLE_SEPARATOR, W as WebRequestOptions, c as WebResponse, s as getTableName } from './types-FE9ewl3r.js';
|
|
5
5
|
export { H as HaextensionConfig } from './config-D_HXjsEV.js';
|
|
6
6
|
import 'drizzle-orm/sqlite-proxy';
|
|
7
7
|
|
|
@@ -136,6 +136,60 @@ declare const HAEXSPACE_MESSAGE_TYPES: {
|
|
|
136
136
|
};
|
|
137
137
|
type HaexspaceMessageType = (typeof HAEXSPACE_MESSAGE_TYPES)[keyof typeof HAEXSPACE_MESSAGE_TYPES];
|
|
138
138
|
|
|
139
|
+
interface VerifyResult {
|
|
140
|
+
valid: boolean;
|
|
141
|
+
error?: string;
|
|
142
|
+
}
|
|
143
|
+
interface ZipFileEntry {
|
|
144
|
+
path: string;
|
|
145
|
+
content: Uint8Array;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Sort object keys recursively for canonical JSON representation.
|
|
149
|
+
* Must match the signing implementation exactly.
|
|
150
|
+
*/
|
|
151
|
+
declare function sortObjectKeysRecursively(obj: unknown): unknown;
|
|
152
|
+
/**
|
|
153
|
+
* Convert hex string to ArrayBuffer
|
|
154
|
+
* Returns ArrayBuffer directly to avoid type issues with Uint8Array.buffer
|
|
155
|
+
*/
|
|
156
|
+
declare function hexToBytes(hex: string): ArrayBuffer;
|
|
157
|
+
/**
|
|
158
|
+
* Verify Ed25519 signature of an extension bundle.
|
|
159
|
+
*
|
|
160
|
+
* This function is browser-compatible and uses the Web Crypto API.
|
|
161
|
+
* It verifies that the extension bundle was signed with the private key
|
|
162
|
+
* corresponding to the public key in the manifest.
|
|
163
|
+
*
|
|
164
|
+
* @param files - Array of file entries from the ZIP archive
|
|
165
|
+
* @param manifest - The extension manifest (parsed from manifest.json)
|
|
166
|
+
* @returns Promise resolving to verification result
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```typescript
|
|
170
|
+
* import JSZip from 'jszip';
|
|
171
|
+
* import { verifyExtensionSignature } from '@haex-space/vault-sdk';
|
|
172
|
+
*
|
|
173
|
+
* const zip = await JSZip.loadAsync(bundleFile);
|
|
174
|
+
* const manifestContent = await zip.file('haextension/manifest.json')?.async('string');
|
|
175
|
+
* const manifest = JSON.parse(manifestContent);
|
|
176
|
+
*
|
|
177
|
+
* // Collect all files from the ZIP
|
|
178
|
+
* const files = [];
|
|
179
|
+
* for (const [path, entry] of Object.entries(zip.files)) {
|
|
180
|
+
* if (!entry.dir) {
|
|
181
|
+
* files.push({ path, content: await entry.async('uint8array') });
|
|
182
|
+
* }
|
|
183
|
+
* }
|
|
184
|
+
*
|
|
185
|
+
* const result = await verifyExtensionSignature(files, manifest);
|
|
186
|
+
* if (!result.valid) {
|
|
187
|
+
* console.error('Signature verification failed:', result.error);
|
|
188
|
+
* }
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
declare function verifyExtensionSignature(files: ZipFileEntry[], manifest: ExtensionManifest): Promise<VerifyResult>;
|
|
192
|
+
|
|
139
193
|
declare function createHaexVaultClient(config?: HaexHubConfig): HaexVaultClient;
|
|
140
194
|
|
|
141
|
-
export { HAEXSPACE_MESSAGE_TYPES, HAEXTENSION_METHODS, HaexHubConfig, HaexVaultClient, type HaexspaceMessageType, type HaextensionMethod, createHaexVaultClient, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill };
|
|
195
|
+
export { ExtensionManifest, HAEXSPACE_MESSAGE_TYPES, HAEXTENSION_METHODS, HaexHubConfig, HaexVaultClient, type HaexspaceMessageType, type HaextensionMethod, type VerifyResult, type ZipFileEntry, createHaexVaultClient, hexToBytes, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill, sortObjectKeysRecursively, verifyExtensionSignature };
|
package/dist/index.js
CHANGED
|
@@ -1432,6 +1432,98 @@ postMessage error: ${e}`);
|
|
|
1432
1432
|
}
|
|
1433
1433
|
};
|
|
1434
1434
|
|
|
1435
|
+
// src/crypto/verify.ts
|
|
1436
|
+
function sortObjectKeysRecursively(obj) {
|
|
1437
|
+
if (typeof obj !== "object" || obj === null) {
|
|
1438
|
+
return obj;
|
|
1439
|
+
}
|
|
1440
|
+
if (Array.isArray(obj)) {
|
|
1441
|
+
return obj.map((item) => sortObjectKeysRecursively(item));
|
|
1442
|
+
}
|
|
1443
|
+
return Object.keys(obj).sort().reduce((result, key) => {
|
|
1444
|
+
result[key] = sortObjectKeysRecursively(obj[key]);
|
|
1445
|
+
return result;
|
|
1446
|
+
}, {});
|
|
1447
|
+
}
|
|
1448
|
+
function hexToBytes(hex) {
|
|
1449
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
1450
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
1451
|
+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
1452
|
+
}
|
|
1453
|
+
return bytes.buffer;
|
|
1454
|
+
}
|
|
1455
|
+
async function verifyExtensionSignature(files, manifest) {
|
|
1456
|
+
try {
|
|
1457
|
+
if (typeof crypto === "undefined" || !crypto.subtle) {
|
|
1458
|
+
return { valid: false, error: "WebCrypto API not available" };
|
|
1459
|
+
}
|
|
1460
|
+
const { publicKey: publicKeyHex, signature: signatureHex } = manifest;
|
|
1461
|
+
if (!publicKeyHex) {
|
|
1462
|
+
return { valid: false, error: "Missing publicKey in manifest" };
|
|
1463
|
+
}
|
|
1464
|
+
if (!signatureHex) {
|
|
1465
|
+
return { valid: false, error: "Missing signature in manifest" };
|
|
1466
|
+
}
|
|
1467
|
+
if (!/^[0-9a-fA-F]+$/.test(publicKeyHex)) {
|
|
1468
|
+
return { valid: false, error: "Invalid publicKey format (must be hex)" };
|
|
1469
|
+
}
|
|
1470
|
+
if (!/^[0-9a-fA-F]+$/.test(signatureHex)) {
|
|
1471
|
+
return { valid: false, error: "Invalid signature format (must be hex)" };
|
|
1472
|
+
}
|
|
1473
|
+
const publicKeyBuffer = hexToBytes(publicKeyHex);
|
|
1474
|
+
let publicKey;
|
|
1475
|
+
try {
|
|
1476
|
+
publicKey = await crypto.subtle.importKey(
|
|
1477
|
+
"raw",
|
|
1478
|
+
publicKeyBuffer,
|
|
1479
|
+
{ name: "Ed25519", namedCurve: "Ed25519" },
|
|
1480
|
+
false,
|
|
1481
|
+
["verify"]
|
|
1482
|
+
);
|
|
1483
|
+
} catch (err) {
|
|
1484
|
+
return {
|
|
1485
|
+
valid: false,
|
|
1486
|
+
error: `Failed to import public key: ${err instanceof Error ? err.message : "Ed25519 may not be supported in this browser"}`
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
const manifestForHashing = sortObjectKeysRecursively({
|
|
1490
|
+
...manifest,
|
|
1491
|
+
signature: ""
|
|
1492
|
+
});
|
|
1493
|
+
const manifestJson = JSON.stringify(manifestForHashing, null, 2);
|
|
1494
|
+
const manifestBytes = new TextEncoder().encode(manifestJson);
|
|
1495
|
+
const filesForHashing = files.map((file) => {
|
|
1496
|
+
if (file.path === "haextension/manifest.json") {
|
|
1497
|
+
return { path: file.path, content: manifestBytes };
|
|
1498
|
+
}
|
|
1499
|
+
return file;
|
|
1500
|
+
});
|
|
1501
|
+
filesForHashing.sort((a, b) => a.path.localeCompare(b.path));
|
|
1502
|
+
const totalLength = filesForHashing.reduce((sum, f) => sum + f.content.length, 0);
|
|
1503
|
+
const combined = new Uint8Array(totalLength);
|
|
1504
|
+
let offset = 0;
|
|
1505
|
+
for (const file of filesForHashing) {
|
|
1506
|
+
combined.set(file.content, offset);
|
|
1507
|
+
offset += file.content.length;
|
|
1508
|
+
}
|
|
1509
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", combined);
|
|
1510
|
+
const signatureBuffer = hexToBytes(signatureHex);
|
|
1511
|
+
const isValid = await crypto.subtle.verify(
|
|
1512
|
+
"Ed25519",
|
|
1513
|
+
publicKey,
|
|
1514
|
+
signatureBuffer,
|
|
1515
|
+
hashBuffer
|
|
1516
|
+
);
|
|
1517
|
+
return { valid: isValid };
|
|
1518
|
+
} catch (err) {
|
|
1519
|
+
console.error("Signature verification error:", err);
|
|
1520
|
+
return {
|
|
1521
|
+
valid: false,
|
|
1522
|
+
error: err instanceof Error ? err.message : "Unknown verification error"
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1435
1527
|
// src/index.ts
|
|
1436
1528
|
function createHaexVaultClient(config = {}) {
|
|
1437
1529
|
return new HaexVaultClient(config);
|
|
@@ -1452,11 +1544,14 @@ exports.TABLE_SEPARATOR = TABLE_SEPARATOR;
|
|
|
1452
1544
|
exports.WebAPI = WebAPI;
|
|
1453
1545
|
exports.createHaexVaultClient = createHaexVaultClient;
|
|
1454
1546
|
exports.getTableName = getTableName;
|
|
1547
|
+
exports.hexToBytes = hexToBytes;
|
|
1455
1548
|
exports.installBaseTag = installBaseTag;
|
|
1456
1549
|
exports.installCookiePolyfill = installCookiePolyfill;
|
|
1457
1550
|
exports.installHistoryPolyfill = installHistoryPolyfill;
|
|
1458
1551
|
exports.installLocalStoragePolyfill = installLocalStoragePolyfill;
|
|
1459
1552
|
exports.installPolyfills = installPolyfills;
|
|
1460
1553
|
exports.installSessionStoragePolyfill = installSessionStoragePolyfill;
|
|
1554
|
+
exports.sortObjectKeysRecursively = sortObjectKeysRecursively;
|
|
1555
|
+
exports.verifyExtensionSignature = verifyExtensionSignature;
|
|
1461
1556
|
//# sourceMappingURL=index.js.map
|
|
1462
1557
|
//# sourceMappingURL=index.js.map
|