nostr-double-ratchet 0.0.25 → 0.0.27
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/Session.d.ts +1 -1
- package/dist/Session.d.ts.map +1 -1
- package/dist/nostr-double-ratchet.es.js +204 -193
- package/dist/nostr-double-ratchet.umd.js +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Session.ts +46 -16
- package/src/types.ts +3 -4
package/src/Session.ts
CHANGED
|
@@ -46,29 +46,54 @@ export class Session {
|
|
|
46
46
|
* @param name Optional name for the session (for debugging)
|
|
47
47
|
* @returns A new Session instance
|
|
48
48
|
*/
|
|
49
|
-
static init(
|
|
49
|
+
static init(
|
|
50
|
+
nostrSubscribe: NostrSubscribe,
|
|
51
|
+
theirEphemeralNostrPublicKey: string,
|
|
52
|
+
ourEphemeralNostrPrivateKey: Uint8Array,
|
|
53
|
+
isInitiator: boolean,
|
|
54
|
+
sharedSecret: Uint8Array,
|
|
55
|
+
name?: string
|
|
56
|
+
): Session {
|
|
50
57
|
const ourNextPrivateKey = generateSecretKey();
|
|
51
|
-
|
|
52
|
-
let
|
|
53
|
-
let
|
|
58
|
+
|
|
59
|
+
let rootKey: Uint8Array;
|
|
60
|
+
let sendingChainKey: Uint8Array | undefined;
|
|
61
|
+
let ourCurrentNostrKey: { publicKey: string, privateKey: Uint8Array } | undefined;
|
|
62
|
+
let ourNextNostrKey: { publicKey: string, privateKey: Uint8Array };
|
|
63
|
+
|
|
54
64
|
if (isInitiator) {
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
[rootKey, sendingChainKey] = kdf(sharedSecret, nip44.getConversationKey(ourNextPrivateKey, theirEphemeralNostrPublicKey), 2);
|
|
66
|
+
ourCurrentNostrKey = {
|
|
67
|
+
publicKey: getPublicKey(ourEphemeralNostrPrivateKey),
|
|
68
|
+
privateKey: ourEphemeralNostrPrivateKey
|
|
69
|
+
};
|
|
70
|
+
ourNextNostrKey = {
|
|
71
|
+
publicKey: getPublicKey(ourNextPrivateKey),
|
|
72
|
+
privateKey: ourNextPrivateKey
|
|
73
|
+
};
|
|
57
74
|
} else {
|
|
58
|
-
|
|
75
|
+
rootKey = sharedSecret;
|
|
76
|
+
sendingChainKey = undefined;
|
|
77
|
+
ourCurrentNostrKey = undefined;
|
|
78
|
+
ourNextNostrKey = {
|
|
79
|
+
publicKey: getPublicKey(ourEphemeralNostrPrivateKey),
|
|
80
|
+
privateKey: ourEphemeralNostrPrivateKey
|
|
81
|
+
};
|
|
59
82
|
}
|
|
83
|
+
|
|
60
84
|
const state: SessionState = {
|
|
61
|
-
rootKey
|
|
62
|
-
theirNextNostrPublicKey,
|
|
85
|
+
rootKey,
|
|
86
|
+
theirNextNostrPublicKey: theirEphemeralNostrPublicKey,
|
|
63
87
|
ourCurrentNostrKey,
|
|
64
88
|
ourNextNostrKey,
|
|
65
89
|
receivingChainKey: undefined,
|
|
66
|
-
sendingChainKey
|
|
90
|
+
sendingChainKey,
|
|
67
91
|
sendingChainMessageNumber: 0,
|
|
68
92
|
receivingChainMessageNumber: 0,
|
|
69
93
|
previousSendingChainMessageCount: 0,
|
|
70
94
|
skippedKeys: {},
|
|
71
95
|
};
|
|
96
|
+
|
|
72
97
|
const session = new Session(nostrSubscribe, state);
|
|
73
98
|
if (name) session.name = name;
|
|
74
99
|
return session;
|
|
@@ -193,11 +218,10 @@ export class Session {
|
|
|
193
218
|
}
|
|
194
219
|
}
|
|
195
220
|
|
|
196
|
-
private ratchetStep(
|
|
221
|
+
private ratchetStep() {
|
|
197
222
|
this.state.previousSendingChainMessageCount = this.state.sendingChainMessageNumber;
|
|
198
223
|
this.state.sendingChainMessageNumber = 0;
|
|
199
224
|
this.state.receivingChainMessageNumber = 0;
|
|
200
|
-
this.state.theirNextNostrPublicKey = theirNextNostrPublicKey;
|
|
201
225
|
|
|
202
226
|
const conversationKey1 = nip44.getConversationKey(this.state.ourNextNostrKey.privateKey, this.state.theirNextNostrPublicKey!);
|
|
203
227
|
const [theirRootKey, receivingChainKey] = kdf(this.state.rootKey, conversationKey1, 2);
|
|
@@ -219,7 +243,9 @@ export class Session {
|
|
|
219
243
|
|
|
220
244
|
// 3. MESSAGE KEY FUNCTIONS
|
|
221
245
|
private skipMessageKeys(until: number, nostrSender: string) {
|
|
222
|
-
if (this.state.receivingChainMessageNumber
|
|
246
|
+
if (until <= this.state.receivingChainMessageNumber) return
|
|
247
|
+
|
|
248
|
+
if (until > this.state.receivingChainMessageNumber + MAX_SKIP) {
|
|
223
249
|
throw new Error("Too many skipped messages");
|
|
224
250
|
}
|
|
225
251
|
|
|
@@ -232,10 +258,14 @@ export class Session {
|
|
|
232
258
|
// Store header keys
|
|
233
259
|
if (this.state.ourCurrentNostrKey) {
|
|
234
260
|
const currentSecret = nip44.getConversationKey(this.state.ourCurrentNostrKey.privateKey, nostrSender);
|
|
235
|
-
this.state.skippedKeys[nostrSender].headerKeys.
|
|
261
|
+
if (!this.state.skippedKeys[nostrSender].headerKeys.includes(currentSecret)) {
|
|
262
|
+
this.state.skippedKeys[nostrSender].headerKeys.push(currentSecret);
|
|
263
|
+
}
|
|
236
264
|
}
|
|
237
265
|
const nextSecret = nip44.getConversationKey(this.state.ourNextNostrKey.privateKey, nostrSender);
|
|
238
|
-
this.state.skippedKeys[nostrSender].headerKeys.
|
|
266
|
+
if (!this.state.skippedKeys[nostrSender].headerKeys.includes(nextSecret)) {
|
|
267
|
+
this.state.skippedKeys[nostrSender].headerKeys.push(nextSecret);
|
|
268
|
+
}
|
|
239
269
|
}
|
|
240
270
|
|
|
241
271
|
while (this.state.receivingChainMessageNumber < until) {
|
|
@@ -316,7 +346,7 @@ export class Session {
|
|
|
316
346
|
|
|
317
347
|
if (shouldRatchet) {
|
|
318
348
|
this.skipMessageKeys(header.previousChainLength, e.pubkey);
|
|
319
|
-
this.ratchetStep(
|
|
349
|
+
this.ratchetStep();
|
|
320
350
|
}
|
|
321
351
|
} else {
|
|
322
352
|
if (!this.state.skippedKeys[e.pubkey]?.messageKeys[header.number]) {
|
package/src/types.ts
CHANGED
|
@@ -66,6 +66,9 @@ export type Unsubscribe = () => void;
|
|
|
66
66
|
* Function that subscribes to Nostr events matching a filter and calls onEvent for each event.
|
|
67
67
|
*/
|
|
68
68
|
export type NostrSubscribe = (filter: Filter, onEvent: (e: VerifiedEvent) => void) => Unsubscribe;
|
|
69
|
+
export type EncryptFunction = (plaintext: string, pubkey: string) => Promise<string>;
|
|
70
|
+
export type DecryptFunction = (ciphertext: string, pubkey: string) => Promise<string>;
|
|
71
|
+
export type NostrPublish = (event: UnsignedEvent) => Promise<VerifiedEvent>;
|
|
69
72
|
|
|
70
73
|
export type Rumor = UnsignedEvent & { id: string }
|
|
71
74
|
|
|
@@ -100,7 +103,3 @@ export type NostrEvent = {
|
|
|
100
103
|
content: string;
|
|
101
104
|
sig: string;
|
|
102
105
|
}
|
|
103
|
-
|
|
104
|
-
export type EncryptFunction = (plaintext: string, pubkey: string) => Promise<string>;
|
|
105
|
-
export type DecryptFunction = (ciphertext: string, pubkey: string) => Promise<string>;
|
|
106
|
-
export type NostrPublish = (event: UnsignedEvent) => Promise<VerifiedEvent>;
|