shogun-core 3.0.13 → 3.0.15
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/README.md +27 -1
- package/dist/browser/shogun-core.js +103157 -84871
- package/dist/browser/shogun-core.js.map +1 -1
- package/dist/config/simplified-config.js +22 -16
- package/dist/core.js +18 -26
- package/dist/examples/api-test.js +273 -0
- package/dist/examples/simple-api-test.js +89 -0
- package/dist/gundb/api.js +126 -189
- package/dist/gundb/crypto.js +32 -17
- package/dist/gundb/db.js +89 -137
- package/dist/gundb/derive.js +20 -17
- package/dist/gundb/errors.js +17 -7
- package/dist/gundb/index.js +19 -3
- package/dist/gundb/rxjs.js +19 -17
- package/dist/gundb/types.js +2 -1
- package/dist/index.js +43 -12
- package/dist/interfaces/common.js +2 -1
- package/dist/interfaces/events.js +6 -2
- package/dist/interfaces/plugin.js +2 -1
- package/dist/interfaces/shogun.js +7 -4
- package/dist/managers/AuthManager.js +9 -7
- package/dist/managers/CoreInitializer.js +23 -20
- package/dist/managers/EventManager.js +7 -4
- package/dist/managers/PluginManager.js +6 -3
- package/dist/migration-test.js +13 -8
- package/dist/plugins/base.js +11 -8
- package/dist/plugins/index.js +36 -10
- package/dist/plugins/nostr/index.js +20 -4
- package/dist/plugins/nostr/nostrConnector.js +42 -36
- package/dist/plugins/nostr/nostrConnectorPlugin.js +36 -29
- package/dist/plugins/nostr/nostrSigner.js +17 -11
- package/dist/plugins/nostr/types.js +2 -1
- package/dist/plugins/oauth/index.js +7 -2
- package/dist/plugins/oauth/oauthConnector.js +75 -69
- package/dist/plugins/oauth/oauthPlugin.js +31 -27
- package/dist/plugins/oauth/types.js +2 -1
- package/dist/plugins/web3/index.js +20 -4
- package/dist/plugins/web3/types.js +2 -1
- package/dist/plugins/web3/web3Connector.js +38 -33
- package/dist/plugins/web3/web3ConnectorPlugin.js +29 -22
- package/dist/plugins/web3/web3Signer.js +24 -18
- package/dist/plugins/webauthn/index.js +19 -3
- package/dist/plugins/webauthn/types.js +5 -2
- package/dist/plugins/webauthn/webauthn.js +30 -25
- package/dist/plugins/webauthn/webauthnPlugin.js +21 -14
- package/dist/plugins/webauthn/webauthnSigner.js +20 -14
- package/dist/storage/storage.js +5 -4
- package/dist/types/events.js +8 -2
- package/dist/types/examples/api-test.d.ts +12 -0
- package/dist/types/examples/simple-api-test.d.ts +5 -0
- package/dist/types/gundb/api.d.ts +0 -26
- package/dist/types/gundb/db.d.ts +2 -35
- package/dist/types/shogun.js +7 -4
- package/dist/utils/errorHandler.js +13 -8
- package/dist/utils/eventEmitter.js +5 -2
- package/dist/utils/validation.js +14 -7
- package/package.json +2 -1
package/dist/gundb/crypto.js
CHANGED
|
@@ -1,20 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Cryptographic utilities for GunDB integration.
|
|
3
4
|
* Based on GunDB's SEA (Security, Encryption, Authorization) module.
|
|
4
5
|
* @see https://github.com/amark/gun/wiki/Snippets
|
|
5
6
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.isHash = isHash;
|
|
9
|
+
exports.encrypt = encrypt;
|
|
10
|
+
exports.decrypt = decrypt;
|
|
11
|
+
exports.encFor = encFor;
|
|
12
|
+
exports.decFrom = decFrom;
|
|
13
|
+
exports.hashText = hashText;
|
|
14
|
+
exports.hashObj = hashObj;
|
|
15
|
+
exports.secret = secret;
|
|
16
|
+
exports.getShortHash = getShortHash;
|
|
17
|
+
exports.safeHash = safeHash;
|
|
18
|
+
exports.unsafeHash = unsafeHash;
|
|
19
|
+
exports.safeJSONParse = safeJSONParse;
|
|
20
|
+
exports.randomUUID = randomUUID;
|
|
21
|
+
const gun_1 = require("gun");
|
|
22
|
+
const uuid_1 = require("uuid");
|
|
8
23
|
// Helper function to get SEA safely
|
|
9
24
|
function getSEA() {
|
|
10
|
-
return global.SEA || SEA;
|
|
25
|
+
return global.SEA || gun_1.SEA;
|
|
11
26
|
}
|
|
12
27
|
/**
|
|
13
28
|
* Checks if a string is a valid GunDB hash
|
|
14
29
|
* @param str - String to check
|
|
15
30
|
* @returns True if string matches GunDB hash format (44 chars ending with =)
|
|
16
31
|
*/
|
|
17
|
-
|
|
32
|
+
function isHash(str) {
|
|
18
33
|
// GunDB hash format: 44 characters ending with =
|
|
19
34
|
// For integration tests, also accept strings with hyphens
|
|
20
35
|
if (typeof str !== "string" || str.length === 0)
|
|
@@ -33,7 +48,7 @@ export function isHash(str) {
|
|
|
33
48
|
* @param key Encryption key
|
|
34
49
|
* @returns Promise that resolves with the encrypted data
|
|
35
50
|
*/
|
|
36
|
-
|
|
51
|
+
async function encrypt(data, key) {
|
|
37
52
|
const sea = getSEA();
|
|
38
53
|
if (!sea || !sea.encrypt) {
|
|
39
54
|
throw new Error("SEA not available");
|
|
@@ -56,7 +71,7 @@ export async function encrypt(data, key) {
|
|
|
56
71
|
* @param key Decryption key
|
|
57
72
|
* @returns Promise that resolves with the decrypted data
|
|
58
73
|
*/
|
|
59
|
-
|
|
74
|
+
async function decrypt(encryptedData, key) {
|
|
60
75
|
const sea = getSEA();
|
|
61
76
|
if (!sea || !sea.decrypt) {
|
|
62
77
|
throw new Error("SEA not available");
|
|
@@ -80,7 +95,7 @@ export async function decrypt(encryptedData, key) {
|
|
|
80
95
|
* @param receiver - Receiver's public encryption key
|
|
81
96
|
* @returns Promise resolving to encrypted data
|
|
82
97
|
*/
|
|
83
|
-
|
|
98
|
+
async function encFor(data, sender, receiver) {
|
|
84
99
|
const sea = getSEA();
|
|
85
100
|
if (!sea || !sea.secret || !sea.encrypt) {
|
|
86
101
|
return "encrypted-data";
|
|
@@ -101,7 +116,7 @@ export async function encFor(data, sender, receiver) {
|
|
|
101
116
|
* @param receiver - Receiver's key pair
|
|
102
117
|
* @returns Promise resolving to decrypted data
|
|
103
118
|
*/
|
|
104
|
-
|
|
119
|
+
async function decFrom(data, sender, receiver) {
|
|
105
120
|
const sea = getSEA();
|
|
106
121
|
if (!sea || !sea.secret || !sea.decrypt) {
|
|
107
122
|
return "decrypted-data";
|
|
@@ -120,7 +135,7 @@ export async function decFrom(data, sender, receiver) {
|
|
|
120
135
|
* @param text - Text to hash
|
|
121
136
|
* @returns Promise resolving to hash string
|
|
122
137
|
*/
|
|
123
|
-
|
|
138
|
+
async function hashText(text) {
|
|
124
139
|
const sea = getSEA();
|
|
125
140
|
if (!sea || !sea.work) {
|
|
126
141
|
throw new Error("SEA not available");
|
|
@@ -140,7 +155,7 @@ export async function hashText(text) {
|
|
|
140
155
|
* @param obj - Object to hash
|
|
141
156
|
* @returns Promise resolving to hash and original stringified data
|
|
142
157
|
*/
|
|
143
|
-
|
|
158
|
+
async function hashObj(obj) {
|
|
144
159
|
let hashed = typeof obj === "string" ? obj : JSON.stringify(obj);
|
|
145
160
|
let hash = await hashText(hashed);
|
|
146
161
|
return { hash, hashed };
|
|
@@ -151,7 +166,7 @@ export async function hashObj(obj) {
|
|
|
151
166
|
* @param pair - Key pair
|
|
152
167
|
* @returns Promise resolving to shared secret
|
|
153
168
|
*/
|
|
154
|
-
|
|
169
|
+
async function secret(epub, pair) {
|
|
155
170
|
const sea = getSEA();
|
|
156
171
|
const secret = await sea.secret(epub, pair);
|
|
157
172
|
return secret;
|
|
@@ -162,7 +177,7 @@ export async function secret(epub, pair) {
|
|
|
162
177
|
* @param salt - Salt for hashing
|
|
163
178
|
* @returns Promise resolving to hex-encoded hash
|
|
164
179
|
*/
|
|
165
|
-
|
|
180
|
+
async function getShortHash(text, salt) {
|
|
166
181
|
const sea = getSEA();
|
|
167
182
|
const hash = await sea.work(text, null, null, {
|
|
168
183
|
name: "PBKDF2",
|
|
@@ -176,7 +191,7 @@ export async function getShortHash(text, salt) {
|
|
|
176
191
|
* @param unsafe - String containing unsafe characters
|
|
177
192
|
* @returns URL-safe string with encoded characters
|
|
178
193
|
*/
|
|
179
|
-
|
|
194
|
+
function safeHash(unsafe) {
|
|
180
195
|
if (unsafe === undefined || unsafe === null)
|
|
181
196
|
return unsafe;
|
|
182
197
|
if (unsafe === "")
|
|
@@ -204,7 +219,7 @@ function encodeChar(_) { }
|
|
|
204
219
|
* @param safe - URL-safe string
|
|
205
220
|
* @returns Original string with decoded characters
|
|
206
221
|
*/
|
|
207
|
-
|
|
222
|
+
function unsafeHash(safe) {
|
|
208
223
|
if (safe === undefined || safe === null)
|
|
209
224
|
return safe;
|
|
210
225
|
if (safe === "")
|
|
@@ -232,7 +247,7 @@ function decodeChar(_) { }
|
|
|
232
247
|
* @param def - Default value if parsing fails
|
|
233
248
|
* @returns Parsed object or default value
|
|
234
249
|
*/
|
|
235
|
-
|
|
250
|
+
function safeJSONParse(input, def = {}) {
|
|
236
251
|
if (input === undefined)
|
|
237
252
|
return undefined;
|
|
238
253
|
if (input === null)
|
|
@@ -248,7 +263,7 @@ export function safeJSONParse(input, def = {}) {
|
|
|
248
263
|
return def;
|
|
249
264
|
}
|
|
250
265
|
}
|
|
251
|
-
|
|
266
|
+
function randomUUID() {
|
|
252
267
|
const c = globalThis?.crypto;
|
|
253
268
|
if (c?.randomUUID)
|
|
254
269
|
return c.randomUUID();
|
|
@@ -264,5 +279,5 @@ export function randomUUID() {
|
|
|
264
279
|
}
|
|
265
280
|
}
|
|
266
281
|
catch { }
|
|
267
|
-
return
|
|
282
|
+
return (0, uuid_1.v4)();
|
|
268
283
|
}
|
package/dist/gundb/db.js
CHANGED
|
@@ -1,23 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* GunDB class with enhanced features:
|
|
3
4
|
* - Dynamic peer linking
|
|
4
5
|
* - Support for remove/unset operations
|
|
5
6
|
* - Direct authentication through Gun.user()
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
42
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.createGun = exports.derive = exports.GunErrors = exports.crypto = exports.RxJS = exports.SEA = exports.DataBase = exports.Gun = void 0;
|
|
46
|
+
const gun_1 = __importDefault(require("gun/gun"));
|
|
47
|
+
exports.Gun = gun_1.default;
|
|
48
|
+
const sea_1 = __importDefault(require("gun/sea"));
|
|
49
|
+
exports.SEA = sea_1.default;
|
|
50
|
+
require("gun/lib/then");
|
|
51
|
+
require("gun/lib/radix");
|
|
52
|
+
require("gun/lib/radisk");
|
|
53
|
+
require("gun/lib/store");
|
|
54
|
+
require("gun/lib/rindexed");
|
|
55
|
+
require("gun/lib/webrtc");
|
|
56
|
+
const derive_1 = __importDefault(require("./derive"));
|
|
57
|
+
exports.derive = derive_1.default;
|
|
58
|
+
const errorHandler_1 = require("../utils/errorHandler");
|
|
59
|
+
const eventEmitter_1 = require("../utils/eventEmitter");
|
|
60
|
+
const rxjs_1 = require("./rxjs");
|
|
61
|
+
Object.defineProperty(exports, "RxJS", { enumerable: true, get: function () { return rxjs_1.RxJS; } });
|
|
62
|
+
const GunErrors = __importStar(require("./errors"));
|
|
63
|
+
exports.GunErrors = GunErrors;
|
|
64
|
+
const crypto = __importStar(require("./crypto"));
|
|
65
|
+
exports.crypto = crypto;
|
|
21
66
|
/**
|
|
22
67
|
* Configuration constants for timeouts and security
|
|
23
68
|
*/
|
|
@@ -34,18 +79,11 @@ const CONFIG = {
|
|
|
34
79
|
},
|
|
35
80
|
};
|
|
36
81
|
class DataBase {
|
|
37
|
-
gun;
|
|
38
|
-
user = null;
|
|
39
|
-
crypto;
|
|
40
|
-
sea;
|
|
41
|
-
node;
|
|
42
|
-
onAuthCallbacks = [];
|
|
43
|
-
eventEmitter;
|
|
44
|
-
// Integrated modules
|
|
45
|
-
_rxjs;
|
|
46
82
|
constructor(gun, appScope = "shogun") {
|
|
83
|
+
this.user = null;
|
|
84
|
+
this.onAuthCallbacks = [];
|
|
47
85
|
// Initialize event emitter
|
|
48
|
-
this.eventEmitter = new EventEmitter();
|
|
86
|
+
this.eventEmitter = new eventEmitter_1.EventEmitter();
|
|
49
87
|
// Validate Gun instance
|
|
50
88
|
if (!gun) {
|
|
51
89
|
throw new Error("Gun instance is required but was not provided");
|
|
@@ -66,9 +104,9 @@ class DataBase {
|
|
|
66
104
|
this.user = this.gun.user().recall({ sessionStorage: true });
|
|
67
105
|
this.subscribeToAuthEvents();
|
|
68
106
|
this.crypto = crypto;
|
|
69
|
-
this.sea =
|
|
107
|
+
this.sea = sea_1.default;
|
|
70
108
|
this.node = null;
|
|
71
|
-
this._rxjs = new RxJS(this.gun);
|
|
109
|
+
this._rxjs = new rxjs_1.RxJS(this.gun);
|
|
72
110
|
}
|
|
73
111
|
/**
|
|
74
112
|
* Initialize the GunInstance asynchronously
|
|
@@ -93,7 +131,7 @@ class DataBase {
|
|
|
93
131
|
this.gun.on("auth", (ack) => {
|
|
94
132
|
// Auth event received
|
|
95
133
|
if (ack.err) {
|
|
96
|
-
ErrorHandler.handle(ErrorType.GUN, "AUTH_EVENT_ERROR", ack.err, new Error(ack.err));
|
|
134
|
+
errorHandler_1.ErrorHandler.handle(errorHandler_1.ErrorType.GUN, "AUTH_EVENT_ERROR", ack.err, new Error(ack.err));
|
|
97
135
|
}
|
|
98
136
|
else {
|
|
99
137
|
this.notifyAuthListeners(ack.sea?.pub || "");
|
|
@@ -272,15 +310,8 @@ class DataBase {
|
|
|
272
310
|
navigateToPath(node, path) {
|
|
273
311
|
if (!path || typeof path !== "string")
|
|
274
312
|
return node;
|
|
275
|
-
// Sanitize path to remove any control characters or invalid characters
|
|
276
|
-
const sanitizedPath = path
|
|
277
|
-
.replace(/[\x00-\x1F\x7F]/g, "") // Remove control characters
|
|
278
|
-
.replace(/[^\w\-._/]/g, "") // Only allow alphanumeric, hyphens, dots, underscores, and slashes
|
|
279
|
-
.trim();
|
|
280
|
-
if (!sanitizedPath)
|
|
281
|
-
return node;
|
|
282
313
|
// Split path by '/' and filter out empty segments
|
|
283
|
-
const pathSegments =
|
|
314
|
+
const pathSegments = path
|
|
284
315
|
.split("/")
|
|
285
316
|
.filter((segment) => segment.length > 0)
|
|
286
317
|
.map((segment) => segment.trim())
|
|
@@ -290,28 +321,6 @@ class DataBase {
|
|
|
290
321
|
return currentNode.get(segment);
|
|
291
322
|
}, node);
|
|
292
323
|
}
|
|
293
|
-
/**
|
|
294
|
-
* Deconstruct path for GunDB navigation in user space
|
|
295
|
-
* Converts "todos/1234" to user.get("todos").get("1234")
|
|
296
|
-
* @param path Path string to deconstruct
|
|
297
|
-
* @returns Gun node at the specified path in user space
|
|
298
|
-
*/
|
|
299
|
-
deconstructUserPath(path) {
|
|
300
|
-
const user = this.gun.user();
|
|
301
|
-
if (!user || !user.is) {
|
|
302
|
-
throw new Error("User not logged in");
|
|
303
|
-
}
|
|
304
|
-
return this.navigateToPath(user, path);
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Deconstruct path for GunDB navigation in global space
|
|
308
|
-
* Converts "todos/1234" to gun.get("todos").get("1234")
|
|
309
|
-
* @param path Path string to deconstruct
|
|
310
|
-
* @returns Gun node at the specified path in global space
|
|
311
|
-
*/
|
|
312
|
-
deconstructGlobalPath(path) {
|
|
313
|
-
return this.navigateToPath(this.gun, path);
|
|
314
|
-
}
|
|
315
324
|
/**
|
|
316
325
|
* Gets the Gun instance
|
|
317
326
|
* @returns Gun instance
|
|
@@ -361,7 +370,7 @@ class DataBase {
|
|
|
361
370
|
* @returns Promise resolving to the data
|
|
362
371
|
*/
|
|
363
372
|
async getData(path) {
|
|
364
|
-
const node = this.
|
|
373
|
+
const node = this.navigateToPath(this.gun, path);
|
|
365
374
|
const data = await node.then();
|
|
366
375
|
return data;
|
|
367
376
|
}
|
|
@@ -372,7 +381,7 @@ class DataBase {
|
|
|
372
381
|
* @returns Promise resolving to operation result
|
|
373
382
|
*/
|
|
374
383
|
async put(path, data) {
|
|
375
|
-
const node = this.
|
|
384
|
+
const node = this.navigateToPath(this.gun, path);
|
|
376
385
|
const ack = await node.put(data).then();
|
|
377
386
|
const result = ack.err
|
|
378
387
|
? { success: false, error: ack.err }
|
|
@@ -386,7 +395,7 @@ class DataBase {
|
|
|
386
395
|
* @returns Promise resolving to operation result
|
|
387
396
|
*/
|
|
388
397
|
async set(path, data) {
|
|
389
|
-
const node = this.
|
|
398
|
+
const node = this.navigateToPath(this.gun, path);
|
|
390
399
|
const ack = await node.set(data).then();
|
|
391
400
|
const result = ack.err
|
|
392
401
|
? { success: false, error: ack.err }
|
|
@@ -399,11 +408,9 @@ class DataBase {
|
|
|
399
408
|
* @returns Promise resolving to operation result
|
|
400
409
|
*/
|
|
401
410
|
async remove(path) {
|
|
402
|
-
const node = this.
|
|
411
|
+
const node = this.navigateToPath(this.gun, path);
|
|
403
412
|
const ack = await node.put(null).then();
|
|
404
|
-
const result = ack.err
|
|
405
|
-
? { success: false, error: ack.err }
|
|
406
|
-
: { success: true };
|
|
413
|
+
const result = ack && ack.err ? { success: false, error: ack.err } : { success: true };
|
|
407
414
|
return result;
|
|
408
415
|
}
|
|
409
416
|
/**
|
|
@@ -1439,13 +1446,13 @@ class DataBase {
|
|
|
1439
1446
|
(typeof screen !== "undefined"
|
|
1440
1447
|
? screen.width + "x" + screen.height
|
|
1441
1448
|
: "");
|
|
1442
|
-
const encryptionKey = await
|
|
1449
|
+
const encryptionKey = await sea_1.default.work(deviceInfo, null, null, {
|
|
1443
1450
|
name: "SHA-256",
|
|
1444
1451
|
});
|
|
1445
1452
|
if (!encryptionKey) {
|
|
1446
1453
|
throw new Error("Failed to generate encryption key");
|
|
1447
1454
|
}
|
|
1448
|
-
const encryptedData = await
|
|
1455
|
+
const encryptedData = await sea_1.default.encrypt(JSON.stringify(data), encryptionKey);
|
|
1449
1456
|
if (!encryptedData) {
|
|
1450
1457
|
throw new Error("Failed to encrypt session data");
|
|
1451
1458
|
}
|
|
@@ -1466,13 +1473,13 @@ class DataBase {
|
|
|
1466
1473
|
(typeof screen !== "undefined"
|
|
1467
1474
|
? screen.width + "x" + screen.height
|
|
1468
1475
|
: "");
|
|
1469
|
-
const encryptionKey = await
|
|
1476
|
+
const encryptionKey = await sea_1.default.work(deviceInfo, null, null, {
|
|
1470
1477
|
name: "SHA-256",
|
|
1471
1478
|
});
|
|
1472
1479
|
if (!encryptionKey) {
|
|
1473
1480
|
throw new Error("Failed to generate decryption key");
|
|
1474
1481
|
}
|
|
1475
|
-
const decryptedData = await
|
|
1482
|
+
const decryptedData = await sea_1.default.decrypt(encryptedData, encryptionKey);
|
|
1476
1483
|
if (decryptedData === undefined) {
|
|
1477
1484
|
throw new Error("Failed to decrypt session data");
|
|
1478
1485
|
}
|
|
@@ -1536,8 +1543,8 @@ class DataBase {
|
|
|
1536
1543
|
let proofOfWork;
|
|
1537
1544
|
try {
|
|
1538
1545
|
// Use SEA directly if available
|
|
1539
|
-
if (
|
|
1540
|
-
proofOfWork = await
|
|
1546
|
+
if (sea_1.default && sea_1.default.work) {
|
|
1547
|
+
proofOfWork = await sea_1.default.work(answersText, null, null, {
|
|
1541
1548
|
name: "SHA-256",
|
|
1542
1549
|
});
|
|
1543
1550
|
}
|
|
@@ -1558,8 +1565,8 @@ class DataBase {
|
|
|
1558
1565
|
// Encrypt the password hint with the proof of work
|
|
1559
1566
|
let encryptedHint;
|
|
1560
1567
|
try {
|
|
1561
|
-
if (
|
|
1562
|
-
encryptedHint = await
|
|
1568
|
+
if (sea_1.default && sea_1.default.encrypt) {
|
|
1569
|
+
encryptedHint = await sea_1.default.encrypt(hint, proofOfWork);
|
|
1563
1570
|
}
|
|
1564
1571
|
else if (this.crypto && this.crypto.encrypt) {
|
|
1565
1572
|
encryptedHint = await this.crypto.encrypt(hint, proofOfWork);
|
|
@@ -1632,8 +1639,8 @@ class DataBase {
|
|
|
1632
1639
|
let proofOfWork;
|
|
1633
1640
|
try {
|
|
1634
1641
|
// Use SEA directly if available
|
|
1635
|
-
if (
|
|
1636
|
-
proofOfWork = await
|
|
1642
|
+
if (sea_1.default && sea_1.default.work) {
|
|
1643
|
+
proofOfWork = await sea_1.default.work(answersText, null, null, {
|
|
1637
1644
|
name: "SHA-256",
|
|
1638
1645
|
});
|
|
1639
1646
|
}
|
|
@@ -1654,8 +1661,8 @@ class DataBase {
|
|
|
1654
1661
|
// Decrypt the password hint with the proof of work
|
|
1655
1662
|
let hint;
|
|
1656
1663
|
try {
|
|
1657
|
-
if (
|
|
1658
|
-
hint = await
|
|
1664
|
+
if (sea_1.default && sea_1.default.decrypt) {
|
|
1665
|
+
hint = await sea_1.default.decrypt(securityData.hint, proofOfWork);
|
|
1659
1666
|
}
|
|
1660
1667
|
else if (this.crypto && this.crypto.decrypt) {
|
|
1661
1668
|
hint = await this.crypto.decrypt(securityData.hint, proofOfWork);
|
|
@@ -1683,64 +1690,6 @@ class DataBase {
|
|
|
1683
1690
|
return { success: false, error: String(error) };
|
|
1684
1691
|
}
|
|
1685
1692
|
}
|
|
1686
|
-
/**
|
|
1687
|
-
* Saves user data at the specified path
|
|
1688
|
-
* @param path Path to save the data (supports nested paths like "test/data/marco")
|
|
1689
|
-
* @param data Data to save
|
|
1690
|
-
* @returns Promise that resolves when the data is saved
|
|
1691
|
-
*/
|
|
1692
|
-
async putUserData(path, data) {
|
|
1693
|
-
const node = this.deconstructUserPath(path);
|
|
1694
|
-
const ack = await node.put(data).then();
|
|
1695
|
-
if (ack.err) {
|
|
1696
|
-
throw new Error(ack.err);
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
/**
|
|
1700
|
-
* Gets user data from the specified path
|
|
1701
|
-
* @param path Path to get the data from (supports nested paths like "test/data/marco")
|
|
1702
|
-
* @returns Promise that resolves with the data
|
|
1703
|
-
*/
|
|
1704
|
-
async getUserData(path) {
|
|
1705
|
-
// Validazione del path
|
|
1706
|
-
if (!path || typeof path !== "string") {
|
|
1707
|
-
throw new Error("Path must be a non-empty string");
|
|
1708
|
-
}
|
|
1709
|
-
try {
|
|
1710
|
-
const node = this.deconstructUserPath(path);
|
|
1711
|
-
const data = await node.once().then();
|
|
1712
|
-
// Gestisci i riferimenti GunDB
|
|
1713
|
-
if (data && typeof data === "object" && data["#"]) {
|
|
1714
|
-
// È un riferimento GunDB, carica i dati effettivi
|
|
1715
|
-
const referencePath = data["#"];
|
|
1716
|
-
const referenceNode = this.deconstructGlobalPath(referencePath);
|
|
1717
|
-
const actualData = await referenceNode.once().then();
|
|
1718
|
-
return actualData;
|
|
1719
|
-
}
|
|
1720
|
-
else {
|
|
1721
|
-
// Dati diretti, restituisci così come sono
|
|
1722
|
-
return data;
|
|
1723
|
-
}
|
|
1724
|
-
}
|
|
1725
|
-
catch (error) {
|
|
1726
|
-
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
1727
|
-
throw new Error(errorMsg);
|
|
1728
|
-
}
|
|
1729
|
-
}
|
|
1730
|
-
/**
|
|
1731
|
-
* Removes user data at the specified path
|
|
1732
|
-
* @param path Path to remove the data from (supports nested paths like "test/data/marco")
|
|
1733
|
-
* @returns Promise that resolves when the data is removed
|
|
1734
|
-
*/
|
|
1735
|
-
async removeUserData(path) {
|
|
1736
|
-
const node = this.deconstructUserPath(path);
|
|
1737
|
-
const ack = await node.put(null).then();
|
|
1738
|
-
if (ack.err) {
|
|
1739
|
-
throw new Error(ack.err);
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
// Errors
|
|
1743
|
-
static Errors = GunErrors;
|
|
1744
1693
|
/**
|
|
1745
1694
|
* Adds an event listener
|
|
1746
1695
|
* @param event Event name
|
|
@@ -1868,12 +1817,15 @@ class DataBase {
|
|
|
1868
1817
|
return this.user?.is?.pub ? true : false;
|
|
1869
1818
|
}
|
|
1870
1819
|
}
|
|
1820
|
+
exports.DataBase = DataBase;
|
|
1821
|
+
// Errors
|
|
1822
|
+
DataBase.Errors = GunErrors;
|
|
1871
1823
|
const createGun = (config) => {
|
|
1872
1824
|
console.log("Creating Gun instance with config:", config);
|
|
1873
1825
|
console.log("Config peers:", config?.peers);
|
|
1874
|
-
const gunInstance =
|
|
1826
|
+
const gunInstance = (0, gun_1.default)(config);
|
|
1875
1827
|
console.log("Created Gun instance:", gunInstance);
|
|
1876
1828
|
return gunInstance;
|
|
1877
1829
|
};
|
|
1878
|
-
|
|
1879
|
-
|
|
1830
|
+
exports.createGun = createGun;
|
|
1831
|
+
exports.default = gun_1.default;
|
package/dist/gundb/derive.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const p256_1 = require("@noble/curves/p256");
|
|
5
|
+
const secp256k1_1 = require("@noble/curves/secp256k1");
|
|
6
|
+
const sha256_1 = require("@noble/hashes/sha256");
|
|
7
|
+
const sha3_1 = require("@noble/hashes/sha3");
|
|
8
|
+
const ripemd160_1 = require("@noble/hashes/ripemd160");
|
|
9
|
+
async function default_1(pwd, extra, options = {}) {
|
|
7
10
|
const TEXT_ENCODER = new TextEncoder();
|
|
8
11
|
const pwdBytes = pwd
|
|
9
12
|
? typeof pwd === "string"
|
|
@@ -33,10 +36,10 @@ export default async function (pwd, extra, options = {}) {
|
|
|
33
36
|
const [signingKeys, encryptionKeys] = await Promise.all(salts.map(async ({ label }) => {
|
|
34
37
|
const salt = TEXT_ENCODER.encode(`${label}-${version}`);
|
|
35
38
|
const privateKey = await stretchKey(combinedInput, salt);
|
|
36
|
-
if (!p256.utils.isValidPrivateKey(privateKey)) {
|
|
39
|
+
if (!p256_1.p256.utils.isValidPrivateKey(privateKey)) {
|
|
37
40
|
throw new Error(`Invalid private key for ${label}`);
|
|
38
41
|
}
|
|
39
|
-
const publicKey = p256.getPublicKey(privateKey, false);
|
|
42
|
+
const publicKey = p256_1.p256.getPublicKey(privateKey, false);
|
|
40
43
|
return {
|
|
41
44
|
pub: keyBufferToJwk(publicKey),
|
|
42
45
|
priv: arrayBufToBase64UrlEncode(privateKey),
|
|
@@ -52,10 +55,10 @@ export default async function (pwd, extra, options = {}) {
|
|
|
52
55
|
if (includeSecp256k1Bitcoin) {
|
|
53
56
|
const bitcoinSalt = TEXT_ENCODER.encode(`secp256k1-bitcoin-${version}`);
|
|
54
57
|
const bitcoinPrivateKey = await stretchKey(combinedInput, bitcoinSalt);
|
|
55
|
-
if (!secp256k1.utils.isValidPrivateKey(bitcoinPrivateKey)) {
|
|
58
|
+
if (!secp256k1_1.secp256k1.utils.isValidPrivateKey(bitcoinPrivateKey)) {
|
|
56
59
|
throw new Error("Invalid secp256k1 private key for Bitcoin");
|
|
57
60
|
}
|
|
58
|
-
const bitcoinPublicKey = secp256k1.getPublicKey(bitcoinPrivateKey, true); // Compressed
|
|
61
|
+
const bitcoinPublicKey = secp256k1_1.secp256k1.getPublicKey(bitcoinPrivateKey, true); // Compressed
|
|
59
62
|
result.secp256k1Bitcoin = {
|
|
60
63
|
privateKey: bytesToHex(bitcoinPrivateKey),
|
|
61
64
|
publicKey: bytesToHex(bitcoinPublicKey),
|
|
@@ -66,10 +69,10 @@ export default async function (pwd, extra, options = {}) {
|
|
|
66
69
|
if (includeSecp256k1Ethereum) {
|
|
67
70
|
const ethereumSalt = TEXT_ENCODER.encode(`secp256k1-ethereum-${version}`);
|
|
68
71
|
const ethereumPrivateKey = await stretchKey(combinedInput, ethereumSalt);
|
|
69
|
-
if (!secp256k1.utils.isValidPrivateKey(ethereumPrivateKey)) {
|
|
72
|
+
if (!secp256k1_1.secp256k1.utils.isValidPrivateKey(ethereumPrivateKey)) {
|
|
70
73
|
throw new Error("Invalid secp256k1 private key for Ethereum");
|
|
71
74
|
}
|
|
72
|
-
const ethereumPublicKey = secp256k1.getPublicKey(ethereumPrivateKey, false); // Uncompressed
|
|
75
|
+
const ethereumPublicKey = secp256k1_1.secp256k1.getPublicKey(ethereumPrivateKey, false); // Uncompressed
|
|
73
76
|
result.secp256k1Ethereum = {
|
|
74
77
|
privateKey: "0x" + bytesToHex(ethereumPrivateKey),
|
|
75
78
|
publicKey: "0x" + bytesToHex(ethereumPublicKey),
|
|
@@ -95,7 +98,7 @@ function keyBufferToJwk(publicKeyBuffer) {
|
|
|
95
98
|
function normalizeString(str) {
|
|
96
99
|
return str.normalize("NFC").trim();
|
|
97
100
|
}
|
|
98
|
-
async function stretchKey(input, salt, iterations =
|
|
101
|
+
async function stretchKey(input, salt, iterations = 300000) {
|
|
99
102
|
try {
|
|
100
103
|
const baseKey = await crypto.subtle.importKey("raw", input, { name: "PBKDF2" }, false, ["deriveBits"]);
|
|
101
104
|
const keyBits = await crypto.subtle.deriveBits({
|
|
@@ -200,15 +203,15 @@ function base58Encode(bytes) {
|
|
|
200
203
|
function deriveP2PKHAddress(publicKey) {
|
|
201
204
|
// Bitcoin P2PKH address derivation
|
|
202
205
|
// 1. SHA256 hash del public key
|
|
203
|
-
const sha256Hash = sha256(publicKey);
|
|
206
|
+
const sha256Hash = (0, sha256_1.sha256)(publicKey);
|
|
204
207
|
// 2. RIPEMD160 hash del risultato
|
|
205
|
-
const ripemd160Hash = ripemd160(sha256Hash);
|
|
208
|
+
const ripemd160Hash = (0, ripemd160_1.ripemd160)(sha256Hash);
|
|
206
209
|
// 3. Aggiungi version byte (0x00 per mainnet P2PKH)
|
|
207
210
|
const versionedHash = new Uint8Array(21);
|
|
208
211
|
versionedHash[0] = 0x00; // Mainnet P2PKH version
|
|
209
212
|
versionedHash.set(ripemd160Hash, 1);
|
|
210
213
|
// 4. Double SHA256 per checksum
|
|
211
|
-
const checksum = sha256(sha256(versionedHash));
|
|
214
|
+
const checksum = (0, sha256_1.sha256)((0, sha256_1.sha256)(versionedHash));
|
|
212
215
|
// 5. Aggiungi i primi 4 byte del checksum
|
|
213
216
|
const addressBytes = new Uint8Array(25);
|
|
214
217
|
addressBytes.set(versionedHash);
|
|
@@ -221,7 +224,7 @@ function deriveKeccak256Address(publicKey) {
|
|
|
221
224
|
// 1. Rimuovi il prefix byte (0x04) dalla chiave pubblica non compressa
|
|
222
225
|
const publicKeyWithoutPrefix = publicKey.slice(1);
|
|
223
226
|
// 2. Calcola Keccak256 hash
|
|
224
|
-
const hash = keccak_256(publicKeyWithoutPrefix);
|
|
227
|
+
const hash = (0, sha3_1.keccak_256)(publicKeyWithoutPrefix);
|
|
225
228
|
// 3. Prendi gli ultimi 20 byte
|
|
226
229
|
const address = hash.slice(-20);
|
|
227
230
|
// 4. Aggiungi '0x' prefix e converti in hex
|