fix(bitcore-lib): normalize elliptic BN in ECDSA.sign#4144
fix(bitcore-lib): normalize elliptic BN in ECDSA.sign#4144wqy000wqy wants to merge 1 commit intobitpay:masterfrom
Conversation
|
The only failing check appears to be
The failure is Since this PR only changes |
|
@wqy000wqy Thanks for the PR. You'll need to sign your commits before this can be merged - see CONTRIBUTING.md |
06fced9 to
84cae99
Compare
|
I checked the existing issues before opening this PR. This appears to be related to #3883, which describes broader compatibility problems around bitcore's BN/Point abstractions and their interaction with underlying I reproduced the problem against the latest This PR is intended as a minimal, focused fix for the concrete failure in I have also updated the PR with a signed commit, and the latest commit is now marked as |
MichaelAJay
left a comment
There was a problem hiding this comment.
Nice catch on the cross-BN issue. I left one small comment on the implementation: I think we can use the existing Point#getX() normalization boundary and avoid the extra round trip.
| // elliptic points may carry coordinates backed by a different bn.js instance | ||
| // than bitcore's BN wrapper when bundled by tools like webpack. Normalize | ||
| // through bytes before doing BN arithmetic to avoid cross-instance asserts. | ||
| r = BN.fromBuffer(Buffer.from(Q.getX().toArray('be', 32))).umod(N); |
There was a problem hiding this comment.
I think we can fix this more directly with Q.getX().umod(N). In bitcore, Point.getX() already returns an internal BN instance, as does Point.getN(), so the stable boundary you're suggesting is maintained.
The only thing this is predicated upon is that getX() continues to return an instance of bitcore's BN. A test in packages/bitcore-lib/test/crypto/point.js would be good to ensure that invariant holds.
There was a problem hiding this comment.
Good point, thanks. I updated the implementation to use Q.getX().umod(N) and added a test in test/crypto/point.js to lock in the invariant that Point#getX() returns bitcore's BN type.
I re-ran:
npx mocha test/crypto/ecdsa.jsnpx mocha test/crypto/point.js
84cae99 to
ff6bc21
Compare
MichaelAJay
left a comment
There was a problem hiding this comment.
Thanks for the PR - nice work!
Summary
This fixes an assertion failure in
bitcore-libECDSA.sign()that can happen in bundled environments wherebitcore-libandellipticend up using differentbn.jsinstances.Root cause
ECDSA.sign()computes:In some bundled runtimes:
Q.xcomes fromellipticNcomes from bitcore's BN wrapperEven though both are BN-like values, they are not guaranteed to be compatible for direct arithmetic across instances, which can trigger internal assertions.
Fix
Normalize the elliptic coordinate through bytes before modular arithmetic:
Q.xis produced byelliptic, while the subsequent arithmetic uses bitcore's BN wrapper. Normalizing through bytes preserves the math while avoiding cross-instance BN operations.Validation
test/crypto/ecdsa.jsnpx mocha test/crypto/ecdsa.jsnpx mocha test/message.js