shogun-core 3.2.3 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +12 -0
  2. package/dist/browser/shogun-core.js +108102 -43579
  3. package/dist/browser/shogun-core.js.map +1 -1
  4. package/dist/ship/examples/messenger-cli.js +171 -55
  5. package/dist/ship/examples/wallet-cli.js +767 -0
  6. package/dist/ship/implementation/SHIP_00.js +478 -0
  7. package/dist/ship/implementation/SHIP_01.js +275 -492
  8. package/dist/ship/implementation/SHIP_02.js +1366 -0
  9. package/dist/ship/implementation/SHIP_03.js +855 -0
  10. package/dist/ship/interfaces/ISHIP_00.js +135 -0
  11. package/dist/ship/interfaces/ISHIP_01.js +81 -24
  12. package/dist/ship/interfaces/ISHIP_02.js +57 -0
  13. package/dist/ship/interfaces/ISHIP_03.js +61 -0
  14. package/dist/src/gundb/db.js +55 -11
  15. package/dist/src/index.js +10 -2
  16. package/dist/src/managers/CoreInitializer.js +41 -13
  17. package/dist/src/storage/storage.js +22 -9
  18. package/dist/types/ship/examples/messenger-cli.d.ts +7 -1
  19. package/dist/types/ship/examples/wallet-cli.d.ts +131 -0
  20. package/dist/types/ship/implementation/SHIP_00.d.ts +113 -0
  21. package/dist/types/ship/implementation/SHIP_01.d.ts +44 -77
  22. package/dist/types/ship/implementation/SHIP_02.d.ts +297 -0
  23. package/dist/types/ship/implementation/SHIP_03.d.ts +127 -0
  24. package/dist/types/ship/interfaces/ISHIP_00.d.ts +410 -0
  25. package/dist/types/ship/interfaces/ISHIP_01.d.ts +157 -119
  26. package/dist/types/ship/interfaces/ISHIP_02.d.ts +470 -0
  27. package/dist/types/ship/interfaces/ISHIP_03.d.ts +295 -0
  28. package/dist/types/src/gundb/db.d.ts +10 -3
  29. package/dist/types/src/index.d.ts +7 -0
  30. package/dist/types/src/interfaces/shogun.d.ts +2 -0
  31. package/dist/types/src/storage/storage.d.ts +2 -1
  32. package/package.json +22 -9
@@ -3,51 +3,30 @@
3
3
  *
4
4
  * @title ISHIP_01 - Decentralized Encrypted Messaging
5
5
  * @notice Interface for decentralized encrypted messaging on GunDB
6
+ * @dev This interface depends on ISHIP_00 for identity and authentication
6
7
  *
7
8
  * ## Abstract
8
9
  *
9
10
  * This standard defines an interface for decentralized messaging that allows:
10
- * - Username/password authentication
11
- * - Public key publication on GunDB
12
11
  * - End-to-end encrypted message sending (ECDH)
13
12
  * - Real-time message reception
14
13
  * - Decentralized message history
15
14
  *
15
+ * ## Dependencies
16
+ *
17
+ * - ISHIP_00: Identity and authentication layer
18
+ * - GunDB: P2P storage
19
+ * - SEA: Cryptography (ECDH + AES-GCM)
20
+ *
16
21
  * ## Specification
17
22
  *
18
23
  * Based on:
24
+ * - SHIP-00 for identity management
19
25
  * - GunDB for P2P storage
20
26
  * - SEA (Security, Encryption, Authorization) for cryptography
21
27
  * - ECDH (Elliptic Curve Diffie-Hellman) for key agreement
22
28
  */
23
- /**
24
- * @notice Authentication result
25
- */
26
- export interface AuthResult {
27
- success: boolean;
28
- userPub?: string;
29
- derivedAddress?: string;
30
- error?: string;
31
- }
32
- /**
33
- * @notice Signup result
34
- */
35
- export interface SignupResult {
36
- success: boolean;
37
- userPub?: string;
38
- derivedAddress?: string;
39
- error?: string;
40
- }
41
- /**
42
- * @notice Message structure
43
- */
44
- export interface Message {
45
- from: string;
46
- to: string;
47
- content: string;
48
- timestamp: string;
49
- messageId: string;
50
- }
29
+ import type { ISHIP_00 } from "./ISHIP_00";
51
30
  /**
52
31
  * @notice Decrypted message structure (for UI)
53
32
  */
@@ -57,61 +36,50 @@ export interface DecryptedMessage {
57
36
  timestamp: number;
58
37
  }
59
38
  /**
60
- * @notice User public key
39
+ * @notice Message history entry
61
40
  */
62
- export interface UserPublicKey {
63
- pub: string;
64
- epub: string;
65
- algorithm: string;
66
- timestamp: string;
41
+ export interface MessageHistoryEntry {
42
+ from: string;
43
+ to: string;
44
+ content: string;
45
+ timestamp: number;
67
46
  }
68
47
  /**
69
- * @notice Operation result
48
+ * @notice Send message result
70
49
  */
71
- export interface OperationResult {
50
+ export interface SendMessageResult {
72
51
  success: boolean;
52
+ messageId?: string;
73
53
  error?: string;
74
54
  }
75
55
  /**
76
- * @notice Send message result
56
+ * @notice Token-encrypted message (for channels/groups)
77
57
  */
78
- export interface SendMessageResult extends OperationResult {
79
- messageId?: string;
58
+ export interface TokenMessage {
59
+ content: string;
60
+ from: string;
61
+ channel?: string;
62
+ timestamp: number;
80
63
  }
81
64
  /**
82
65
  * @title ISHIP_01 - Decentralized Messaging
83
66
  * @notice Main interface for the messaging system
67
+ * @dev Depends on ISHIP_00 for all identity operations
68
+ *
69
+ * Constructor pattern:
70
+ * ```typescript
71
+ * class MessagingApp implements ISHIP_01 {
72
+ * constructor(private identity: ISHIP_00) {}
73
+ * }
74
+ * ```
84
75
  */
85
76
  export interface ISHIP_01 {
86
77
  /**
87
- * @notice Register a new user
88
- * @param username Desired username
89
- * @param password Password
90
- * @return Result with userPub and derivedAddress
91
- */
92
- signup(username: string, password: string): Promise<SignupResult>;
93
- /**
94
- * @notice Login with username and password
95
- * @param username Username
96
- * @param password Password
97
- * @return Result with userPub and derivedAddress
98
- */
99
- login(username: string, password: string): Promise<AuthResult>;
100
- /**
101
- * @notice Logout current user
78
+ * @notice Get the identity provider
79
+ * @dev Returns the ISHIP_00 instance used for identity operations
80
+ * @return Identity provider instance
102
81
  */
103
- logout(): void;
104
- /**
105
- * @notice Check if user is authenticated
106
- * @return True if authenticated
107
- */
108
- isLoggedIn(): boolean;
109
- /**
110
- * @notice Publish public key on GunDB
111
- * @dev Allows others to find your key to encrypt messages
112
- * @return Operation result
113
- */
114
- publishPublicKey(): Promise<OperationResult>;
82
+ getIdentity(): ISHIP_00;
115
83
  /**
116
84
  * @notice Send encrypted message
117
85
  * @dev Uses ECDH to derive shared secret, then AES-GCM for encryption
@@ -119,8 +87,12 @@ export interface ISHIP_01 {
119
87
  * @param message Plain text message content
120
88
  * @return Result with messageId
121
89
  *
90
+ * Prerequisites:
91
+ * - User must be authenticated (via ISHIP_00)
92
+ * - Recipient must have published their public key
93
+ *
122
94
  * Flow:
123
- * 1. Retrieve recipient's epub from GunDB
95
+ * 1. Get recipient's epub from identity provider
124
96
  * 2. SEA.secret(recipient.epub, sender.pair) → shared_secret
125
97
  * 3. SEA.encrypt(message, shared_secret) → encrypted
126
98
  * 4. Save encrypted on GunDB
@@ -131,9 +103,12 @@ export interface ISHIP_01 {
131
103
  * @dev Automatically decrypts received messages
132
104
  * @param onMessage Callback called for each message
133
105
  *
106
+ * Prerequisites:
107
+ * - User must be authenticated (via ISHIP_00)
108
+ *
134
109
  * Decryption flow:
135
110
  * 1. Receive encrypted message from GunDB
136
- * 2. Retrieve sender's epub
111
+ * 2. Retrieve sender's epub from identity provider
137
112
  * 3. SEA.secret(sender.epub, receiver.pair) → shared_secret
138
113
  * 4. SEA.decrypt(encrypted, shared_secret) → message
139
114
  * 5. Call callback with decrypted message
@@ -144,44 +119,56 @@ export interface ISHIP_01 {
144
119
  * @dev Decrypts all messages in history
145
120
  * @param withUsername Username of the other user
146
121
  * @return Array of decrypted messages sorted by timestamp
122
+ *
123
+ * Prerequisites:
124
+ * - User must be authenticated (via ISHIP_00)
147
125
  */
148
- getMessageHistory(withUsername: string): Promise<Array<{
149
- from: string;
150
- to: string;
151
- content: string;
152
- timestamp: number;
153
- }>>;
154
- }
155
- /**
156
- * @notice Interface for GunDB → Ethereum identity conversion
157
- */
158
- export interface IAddressDerivation {
126
+ getMessageHistory(withUsername: string): Promise<MessageHistoryEntry[]>;
159
127
  /**
160
- * @notice Convert GunDB public key to Ethereum address
161
- * @param publicKey Public key in base64 format (GunDB)
162
- * @return Ethereum address with checksum
128
+ * @notice Send message encrypted with a shared token/password
129
+ * @dev Uses symmetric encryption with provided token
130
+ * @param token Shared secret/password for encryption
131
+ * @param message Plain text message content
132
+ * @param channel Optional channel name for organization
133
+ * @return Result with messageId
134
+ *
135
+ * Use cases:
136
+ * - Group chats with shared password
137
+ * - Broadcast channels
138
+ * - Private communities
139
+ *
140
+ * Flow:
141
+ * 1. Hash token for key derivation
142
+ * 2. SEA.encrypt(message, hashedToken) → encrypted
143
+ * 3. Save encrypted on GunDB with channel tag
144
+ */
145
+ sendMessageWithToken(token: string, message: string, channel?: string): Promise<SendMessageResult>;
146
+ /**
147
+ * @notice Listen for token-encrypted messages
148
+ * @dev Automatically decrypts received messages with provided token
149
+ * @param token Shared secret/password for decryption
150
+ * @param onMessage Callback called for each message
151
+ * @param channel Optional channel filter
163
152
  *
164
- * Process:
165
- * 1. Decode from base64 (GunDB format)
166
- * 2. Convert to bytes
167
- * 3. keccak256(bytes)
168
- * 4. Take last 20 bytes
169
- * 5. Apply EIP-55 checksum
153
+ * Prerequisites:
154
+ * - User must be authenticated (via ISHIP_00)
155
+ *
156
+ * Decryption flow:
157
+ * 1. Receive encrypted message from GunDB
158
+ * 2. Hash token
159
+ * 3. SEA.decrypt(encrypted, hashedToken) → message
160
+ * 4. Call callback with decrypted message
170
161
  */
171
- pubKeyToAddress(publicKey: string): string;
162
+ listenForTokenMessages(token: string, onMessage: (message: TokenMessage) => void, channel?: string): Promise<void>;
172
163
  }
173
164
  /**
174
165
  * @notice Messaging system configuration
175
166
  */
176
167
  export interface MessagingConfig {
177
168
  /**
178
- * @notice GunDB peers
179
- */
180
- peers: string[];
181
- /**
182
- * @notice Application scope
169
+ * @notice Identity provider (SHIP-00 instance)
183
170
  */
184
- scope: string;
171
+ identity: ISHIP_00;
185
172
  /**
186
173
  * @notice Operation timeout (ms)
187
174
  */
@@ -260,46 +247,97 @@ export interface ISEACrypto {
260
247
  hashText(text: string): Promise<string>;
261
248
  }
262
249
  /**
263
- * Example of how to implement ISHIP_01
250
+ * Example of how to implement ISHIP_01 with ISHIP_00 dependency
264
251
  *
265
252
  * ```typescript
266
- * class SecureMessagingApp implements ISHIP_01 {
267
- * private shogun: ShogunCore;
253
+ * import { ISHIP_00 } from './ISHIP_00';
254
+ * import { ISHIP_01, DecryptedMessage, SendMessageResult } from './ISHIP_01';
268
255
  *
269
- * constructor(config: MessagingConfig) {
270
- * this.shogun = new ShogunCore(config);
256
+ * class SecureMessagingApp implements ISHIP_01 {
257
+ * constructor(private identity: ISHIP_00) {
258
+ * // Verify identity is authenticated
259
+ * if (!identity.isLoggedIn()) {
260
+ * throw new Error('User must be authenticated');
261
+ * }
271
262
  * }
272
263
  *
273
- * async signup(username: string, password: string): Promise<SignupResult> {
274
- * const result = await this.shogun.signUp(username, password);
275
- * return {
276
- * success: result.success,
277
- * userPub: result.pub,
278
- * derivedAddress: this.pubKeyToAddress(result.pub || "")
279
- * };
264
+ * getIdentity(): ISHIP_00 {
265
+ * return this.identity;
280
266
  * }
281
267
  *
282
268
  * async sendMessage(recipientUsername: string, message: string): Promise<SendMessageResult> {
283
- * // 1. Get recipient's epub
284
- * const recipientKey = await this.getRecipientPublicKey(recipientUsername);
269
+ * // 1. Get recipient's public key from identity provider
270
+ * const recipientKey = await this.identity.getPublicKey(recipientUsername);
271
+ * if (!recipientKey) {
272
+ * return { success: false, error: 'Recipient not found' };
273
+ * }
285
274
  *
286
- * // 2. Encrypt with ECDH
287
- * const encrypted = await this.shogun.db.crypto.encFor(
275
+ * // 2. Get sender's key pair from identity provider
276
+ * const senderPair = this.identity.getKeyPair();
277
+ * if (!senderPair) {
278
+ * return { success: false, error: 'Not authenticated' };
279
+ * }
280
+ *
281
+ * // 3. Encrypt with ECDH
282
+ * const encrypted = await crypto.encFor(
288
283
  * message,
289
- * this.shogun.db.user.is, // sender
290
- * { epub: recipientKey.epub } // receiver
284
+ * senderPair,
285
+ * { epub: recipientKey.epub }
291
286
  * );
292
287
  *
293
- * // 3. Save to GunDB
294
- * await this.shogun.db.user.get('messages/...').put({
288
+ * // 4. Save to GunDB
289
+ * const messageId = generateId();
290
+ * await gun.get('messages').get(messageId).put({
295
291
  * content: encrypted,
296
- * from: this.shogun.db.user.is.pub,
292
+ * from: senderPair.pub,
297
293
  * to: recipientUsername,
298
294
  * timestamp: Date.now().toString()
299
295
  * });
300
296
  *
301
- * return { success: true, messageId: '...' };
297
+ * return { success: true, messageId };
298
+ * }
299
+ *
300
+ * async listenForMessages(onMessage: (message: DecryptedMessage) => void): Promise<void> {
301
+ * const currentUser = this.identity.getCurrentUser();
302
+ * if (!currentUser) {
303
+ * throw new Error('Not authenticated');
304
+ * }
305
+ *
306
+ * gun.get('messages').map().on(async (data, key) => {
307
+ * if (data && data.to === currentUser.alias) {
308
+ * // Decrypt message
309
+ * const senderKey = await this.identity.getPublicKey(data.from);
310
+ * const receiverPair = this.identity.getKeyPair();
311
+ *
312
+ * if (senderKey && receiverPair) {
313
+ * const decrypted = await crypto.decFrom(
314
+ * data.content,
315
+ * { epub: senderKey.epub },
316
+ * receiverPair
317
+ * );
318
+ *
319
+ * onMessage({
320
+ * from: data.from,
321
+ * content: decrypted,
322
+ * timestamp: parseInt(data.timestamp)
323
+ * });
324
+ * }
325
+ * }
326
+ * });
327
+ * }
328
+ *
329
+ * async getMessageHistory(withUsername: string): Promise<MessageHistoryEntry[]> {
330
+ * // Implementation here
331
+ * return [];
302
332
  * }
303
333
  * }
334
+ *
335
+ * // Usage
336
+ * const identity = new SHIP_00(config);
337
+ * await identity.login('alice', 'password123');
338
+ * await identity.publishPublicKey();
339
+ *
340
+ * const messaging = new SecureMessagingApp(identity);
341
+ * await messaging.sendMessage('bob', 'Hello Bob!');
304
342
  * ```
305
343
  */