shogun-core 6.2.2 → 6.2.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.
@@ -125,6 +125,11 @@ const performDHRatchetStep = async (state, newRemotePublicKey) => {
125
125
  // Generate our sending key pair for future messages
126
126
  console.log("🔑 Generating DH key pair for responder's future sending");
127
127
  state.sendingDHKeyPair = await (0, signal_protocol_1.generateSignalKeyPair)();
128
+ // For responder's first receive, we don't derive a sending chain yet
129
+ // because we haven't sent anything. The sending chain will be derived
130
+ // when we send our first message.
131
+ console.log("✓ DH ratchet step completed (responder first receive)");
132
+ return;
128
133
  }
129
134
  else if (state.sendingDHKeyPair) {
130
135
  console.log("🔄 Deriving receiving chain from: DH(our_current_private, their_public)");
@@ -136,6 +141,7 @@ const performDHRatchetStep = async (state, newRemotePublicKey) => {
136
141
  console.log("🔄 DH ratchet step - receiving chain established");
137
142
  }
138
143
  // Step 2: Generate NEW DH key pair and derive sending chain
144
+ // This only executes for subsequent ratchet steps (not responder's first receive)
139
145
  console.log("🔑 Generating NEW DH key pair for ratchet step");
140
146
  state.sendingDHKeyPair = await (0, signal_protocol_1.generateSignalKeyPair)();
141
147
  state.sendingMessageNumber = 0;
@@ -172,8 +178,24 @@ const skipMessageKeys = async (state, until) => {
172
178
  // Encrypt message using Double Ratchet
173
179
  const doubleRatchetEncrypt = async (state, plaintext) => {
174
180
  console.log(`🔒 Encrypting message #${state.sendingMessageNumber} with Double Ratchet`);
181
+ // If responder is sending first message, derive sending chain
175
182
  if (!state.sendingChainKey) {
176
- throw new Error("No sending chain key available - cannot encrypt");
183
+ if (!state.isInitiator &&
184
+ state.receivingDHPublicKey &&
185
+ state.sendingDHKeyPair) {
186
+ console.log("🔄 Responder's first send: Deriving sending chain");
187
+ // Derive sending chain from our sending DH key pair and their receiving DH public key
188
+ const sendingDHOutput = await (0, signal_protocol_1.performSignalDH)(state.sendingDHKeyPair.privateKey, state.receivingDHPublicKey);
189
+ const hkdfSending = await doubleRatchetHKDF(new Uint8Array(state.rootKey), sendingDHOutput, DOUBLE_RATCHET_INFO_CHAIN_KEY, 64);
190
+ state.rootKey = hkdfSending.slice(0, 32);
191
+ state.sendingChainKey = hkdfSending.slice(32, 64);
192
+ state.sendingMessageNumber = 0;
193
+ state.previousChainLength = state.receivingMessageNumber;
194
+ console.log("✅ Sending chain derived for responder's first message");
195
+ }
196
+ else {
197
+ throw new Error("No sending chain key available - cannot encrypt");
198
+ }
177
199
  }
178
200
  // Derive message key
179
201
  const messageKey = await deriveMessageKey(state.sendingChainKey);
@@ -149,7 +149,8 @@ exports.importSignalPublicKey = importSignalPublicKey;
149
149
  const importSignalSigningPublicKey = async (keyBytes) => {
150
150
  return await crypto.subtle.importKey("raw", keyBytes, {
151
151
  name: "Ed25519",
152
- }, false, ["verify"]);
152
+ }, true, // Make public keys extractable for re-export in bundles
153
+ ["verify"]);
153
154
  };
154
155
  exports.importSignalSigningPublicKey = importSignalSigningPublicKey;
155
156
  const performSignalDH = async (privateKey, publicKey) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shogun-core",
3
- "version": "6.2.2",
3
+ "version": "6.2.4",
4
4
  "description": "SHOGUN CORE - Core library for Shogun Ecosystem",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",