@steemit/steem-js 1.0.10 → 1.0.11

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/index.umd.js CHANGED
@@ -16928,6 +16928,77 @@
16928
16928
  const finalS = s.gt(N_OVER_TWO) ? n.sub(s) : s;
16929
16929
  return new ECSignature(r, finalS);
16930
16930
  }
16931
+ /**
16932
+ * Recover a public key from a signature.
16933
+ *
16934
+ * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
16935
+ * Key Recovery Operation".
16936
+ *
16937
+ * http://www.secg.org/download/aid-780/sec1-v2.pdf
16938
+ */
16939
+ function recoverPubKey(curve, e, signature, i) {
16940
+ if ((i & 3) !== i) {
16941
+ throw new Error('Recovery param is more than two bits');
16942
+ }
16943
+ const n = new BN(curve.n.toString());
16944
+ const r = signature.r;
16945
+ const s = signature.s;
16946
+ if (r.isNeg() || r.isZero() || !r.lt(n))
16947
+ throw new Error('Invalid r value');
16948
+ if (s.isNeg() || s.isZero() || !s.lt(n))
16949
+ throw new Error('Invalid s value');
16950
+ // Try using elliptic's built-in recoverPubKey method
16951
+ // It expects: msg (Buffer), signature ({r: BN, s: BN}), j (recovery param)
16952
+ try {
16953
+ // Convert e (BN) to Buffer
16954
+ const msgBuffer = e.toArrayLike(buffer.Buffer, 'be', 32);
16955
+ // Create signature object compatible with elliptic's recoverPubKey
16956
+ // elliptic expects {r: BN, s: BN} format
16957
+ const sigObj = { r: r, s: s };
16958
+ // Use elliptic's built-in method
16959
+ const Q = curve.recoverPubKey(msgBuffer, sigObj, i);
16960
+ return Q;
16961
+ }
16962
+ catch (error) {
16963
+ // Fallback to manual implementation if elliptic's method fails
16964
+ const G = curve.g;
16965
+ // A set LSB signifies that the y-coordinate is odd
16966
+ const isYOdd = !!(i & 1);
16967
+ // The more significant bit specifies whether we should use the
16968
+ // first or second candidate key.
16969
+ const isSecondKey = i >> 1;
16970
+ // 1.1 Let x = r + jn
16971
+ const x = isSecondKey ? r.add(n) : r;
16972
+ // pointFromX expects a hex string (not BN object)
16973
+ // Convert BN to hex string and ensure proper padding
16974
+ const xHex = x.toString(16);
16975
+ // Ensure hex string is properly padded to 64 characters (32 bytes)
16976
+ const xHexPadded = xHex.padStart(64, '0');
16977
+ // pointFromX may also accept a Buffer, but hex string is more reliable
16978
+ let R;
16979
+ try {
16980
+ R = curve.curve.pointFromX(xHexPadded, isYOdd);
16981
+ }
16982
+ catch (error) {
16983
+ // If hex string fails, try with Buffer
16984
+ const xBuffer = x.toArrayLike(buffer.Buffer, 'be', 32);
16985
+ R = curve.curve.pointFromX(xBuffer, isYOdd);
16986
+ }
16987
+ // 1.4 Check that nR is at infinity
16988
+ const nR = R.mul(n);
16989
+ if (!nR.isInfinity())
16990
+ throw new Error('nR is not a valid curve point');
16991
+ // Compute -e from e
16992
+ const eNeg = e.neg().mod(n);
16993
+ // 1.6.1 Compute Q = r^-1 (sR - eG)
16994
+ // Q = r^-1 (sR + -eG)
16995
+ const rInv = r.invm(n);
16996
+ const sR = R.mul(s);
16997
+ const eGNeg = G.mul(eNeg);
16998
+ const Q = sR.add(eGNeg).mul(rInv);
16999
+ return Q;
17000
+ }
17001
+ }
16931
17002
  /**
16932
17003
  * Calculate pubkey extraction parameter.
16933
17004
  *
@@ -16942,11 +17013,15 @@
16942
17013
  function calcPubKeyRecoveryParam(curve, e, signature, Q) {
16943
17014
  for (let i = 0; i < 4; i++) {
16944
17015
  try {
16945
- // Use elliptic's built-in recovery method
16946
- const Qprime = curve.recoverPubKey(e, signature, i);
17016
+ // Use our own recoverPubKey function instead of curve.recoverPubKey
17017
+ const Qprime = recoverPubKey(curve, e, signature, i);
16947
17018
  // 1.6.2 Verify Q = Q'
16948
- // Compare points by checking if they are the same point
16949
- if (Qprime.eq(Q)) {
17019
+ // Compare points by checking coordinates (more reliable than eq method)
17020
+ const Qx = Q.getX().toString(16);
17021
+ const Qy = Q.getY().toString(16);
17022
+ const QprimeX = Qprime.getX().toString(16);
17023
+ const QprimeY = Qprime.getY().toString(16);
17024
+ if (Qx === QprimeX && Qy === QprimeY) {
16950
17025
  return i;
16951
17026
  }
16952
17027
  }
@@ -16980,7 +17055,13 @@
16980
17055
  throw new Error('Invalid signature length');
16981
17056
  }
16982
17057
  const i = buffer.readUInt8(0);
16983
- if ((i - 27) !== ((i - 27) & 7)) {
17058
+ // Support both formats: 27-30 (old/legacy) and 31-34 (dsteem compatible)
17059
+ // Check if it's in the old format (27-30) or new format (31-34)
17060
+ const recoveryOld = i - 27;
17061
+ const recoveryNew = i - 31;
17062
+ const isValidOld = recoveryOld >= 0 && recoveryOld <= 3 && (recoveryOld === (recoveryOld & 7));
17063
+ const isValidNew = recoveryNew >= 0 && recoveryNew <= 3 && (recoveryNew === (recoveryNew & 7));
17064
+ if (!isValidOld && !isValidNew) {
16984
17065
  throw new Error('Invalid signature parameter');
16985
17066
  }
16986
17067
  const r = new BN(buffer.slice(1, 33));
@@ -17029,7 +17110,9 @@
17029
17110
  }
17030
17111
  }
17031
17112
  const i = calcPubKeyRecoveryParam(secp256k1, new BN(buf_sha256), ecsignature, privKey.toPublic().Q);
17032
- return new Signature(ecsignature.r, ecsignature.s, i + 27);
17113
+ // Use recovery byte 31-34 (instead of 27-30) to be compatible with dsteem
17114
+ // dsteem expects: recovery = byte - 31, so byte = recovery + 31
17115
+ return new Signature(ecsignature.r, ecsignature.s, i + 31);
17033
17116
  }
17034
17117
  static isCanonical(r, s) {
17035
17118
  // See libraries/fc/src/crypto/elliptic_common.cpp is_fc_canonical
@@ -28761,7 +28844,7 @@
28761
28844
  serializer,
28762
28845
  utils: utils$n,
28763
28846
  ...crypto$1,
28764
- version: '1.0.10',
28847
+ version: '1.0.11',
28765
28848
  config: {
28766
28849
  set: (options) => {
28767
28850
  // If nodes is provided, extract the first node as url for API