@sip-protocol/sdk 0.10.0 → 0.11.1

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.
@@ -173,11 +173,17 @@ export function generateSecp256k1StealthAddress(
173
173
  // Hash the shared secret for use as a scalar
174
174
  const sharedSecretHash = sha256(sharedSecretPoint)
175
175
 
176
- // Compute stealth address: A = K_spend + hash(S)*G
177
- const hashTimesG = secp256k1.getPublicKey(sharedSecretHash, true)
176
+ // Compute stealth address: A = K_spend + hash(S)*G.
177
+ // Reduce hash(S) to a scalar in [1, n-1] before deriving the point: secp256k1.getPublicKey
178
+ // throws for a scalar >= n or == 0 (~3.7e-39 for a random SHA-256 digest). Reducing mod n
179
+ // mirrors the ed25519 path and keeps generate symmetric with derive (k_spend + hash(S) mod n).
180
+ const hashScalar = bytesToBigInt(sharedSecretHash) % secp256k1.CURVE.n
181
+ if (hashScalar === 0n) {
182
+ throw new Error('CRITICAL: zero hash scalar after reduction - investigate hash computation')
183
+ }
178
184
 
179
185
  const spendingKeyPoint = secp256k1.ProjectivePoint.fromHex(spendingKeyBytes)
180
- const hashTimesGPoint = secp256k1.ProjectivePoint.fromHex(hashTimesG)
186
+ const hashTimesGPoint = secp256k1.ProjectivePoint.BASE.multiply(hashScalar)
181
187
  const stealthPoint = spendingKeyPoint.add(hashTimesGPoint)
182
188
  const stealthAddressBytes = stealthPoint.toRawBytes(true)
183
189
 
@@ -378,10 +384,15 @@ export function checkSecp256k1StealthAddress(
378
384
  return false
379
385
  }
380
386
 
381
- // Expected address: A = K_spend + hash(S)*G (no spending private key needed)
382
- const hashTimesG = secp256k1.getPublicKey(sharedSecretHash, true)
387
+ // Expected address: A = K_spend + hash(S)*G (no spending private key needed).
388
+ // Reduce hash(S) mod n (symmetric with generate); a zero scalar can't correspond to a
389
+ // real stealth payment, so treat it as a non-match.
390
+ const hashScalar = bytesToBigInt(sharedSecretHash) % secp256k1.CURVE.n
391
+ if (hashScalar === 0n) {
392
+ return false
393
+ }
383
394
  const expectedPoint = secp256k1.ProjectivePoint.fromHex(spendingPubBytes).add(
384
- secp256k1.ProjectivePoint.fromHex(hashTimesG),
395
+ secp256k1.ProjectivePoint.BASE.multiply(hashScalar),
385
396
  )
386
397
 
387
398
  // Compare with provided stealth address