-
Notifications
You must be signed in to change notification settings - Fork 51
@noble/ed25519 and BigInts #212
Comments
Worth getting expert crypto advice on the topic too |
They do mention this in the readme:
Some of which may be even true, but the level of benchmark variance of this specific library still gives me significant pause. |
As an alternative, the wasm version benchmarked in #211 looks very promising, though it'll obviously have an impact on the bundle size. |
I also have a problem with noble/ed25519 and BigInts. In my project i use libp2p in the browser with react (create-react-app). My page isn't even loading anymore, and I get the error: This only happens when i create a production build of my react app ( |
@sneaker1 your problem is unrelated to this one, please open a separate issue. In brief you need to disable the |
IMO its ok to use the noble secp uses bigints also and has been audited https://github.com/paulmillr/noble-secp256k1#security refs: @paulmillr if you could give us some feedback here we would be grateful. |
The second point
Is defeatable since most consumers of this library are open source and can figure out the context. Also you assume that everyone is running latest Chrome / Firefox since they auto-update so you can also predict the JIT optimizations that each engine will apply. But agree with the assessment afterwards that it's not the highest impact risk consumers will be facing |
Noble specifically benchmarks inputs of different bit length to ensure there is no difference in algorithmic complexity. See benchmark file. So, not sure why you're having this variance. Native bigints are no more insecure than bn.js, or other non-native stuff. Try making node-force run first, and noble ed last and see what happens. As for "using wasm": since wasm binaries are unsigned, you cannot be sure you aren't running a malware. The npm has been allowing anyone to upload update to any package for 2+ years, including the unlogged period. This has been fixed 2 weeks ago. Anyone could have uploaded malware to any wasm package. Or they could upload it any any moment in the future by hacking someone's npm account. |
The variance is the same on my machine, macos with M1, node v16.13.0:
|
I removed all other non- $ node index.js
@noble/ed25519 x 116 ops/sec ±27.86% (76 runs sampled)
fastest is @noble/ed25519 node v16.13.0
Your machine is definitely faster than mine, maybe I should upgrade 😆
To be fair, this is not a vulnerability exclusive to wasm, it applies to every single package on npm, |
Any npm package could get malwared, but for noble, you could do a diff with its GitHub release that is signed by PGP key and see if there are any differences. |
As for requires, make noble the second or third. I've seen performance issues in benchmarks that only happen on first tests. This is because of JIT. |
Even as the last require and the last benchmark to run, the result is still the same: $ node index.js
@stablelib/ed25519 x 57.89 ops/sec ±2.50% (69 runs sampled)
node-forge/ed25519 x 56.69 ops/sec ±1.54% (68 runs sampled)
supercop.wasm x 3,425 ops/sec ±1.64% (82 runs sampled)
ed25519-wasm-pro x 3,583 ops/sec ±0.88% (83 runs sampled)
ed25519 (native module) x 4,608 ops/sec ±0.93% (84 runs sampled)
node.js web-crypto x 3,223 ops/sec ±4.73% (78 runs sampled)
@noble/ed25519 x 204 ops/sec ±25.72% (83 runs sampled)
fastest is ed25519 (native module) |
Can you change benchmark to only test for one thing? This will allow to understand which action is doing the variance on your machine. Sign/verify/getPublicKey etc Also, can you do the Buffer.from(math random) before the tests? The code could look like this:
|
Investigating this by myself now, using an Intel VPS. |
On a first invocation of
If you execute the code above before tests, everything would be fine. And the number is not |
As for the real difference between invocations, i'm using my micro-bmark to test it. This simple commit in noble-secp256k1 removes array-destructing assignments which removes quite a few OPcodes, which reduces GC time by a huge amount. See 1.3.0 and post-commit results between the fastest and slowest invocations:
@dapplion this is just one example of GC
|
Aha! $ node index.js
@noble/ed25519 x 240 ops/sec ±2.14% (80 runs sampled)
@stablelib/ed25519 x 58.51 ops/sec ±2.66% (69 runs sampled)
node-forge/ed25519 x 52.87 ops/sec ±7.09% (64 runs sampled)
supercop.wasm x 3,656 ops/sec ±1.41% (85 runs sampled)
ed25519-wasm-pro x 3,709 ops/sec ±1.63% (84 runs sampled)
ed25519 (native module) x 4,739 ops/sec ±1.57% (83 runs sampled)
node.js web-crypto x 3,506 ops/sec ±3.24% (80 runs sampled)
fastest is ed25519 (native module) I've fixed up the benchmark in #217 |
Uh oh!
There was an error while loading. Please reload this page.
#202 switched this library over from using
node-forge
for Ed25519 key operations to@noble/ed25519
.The benchmarks introduced in #213 show
@noble/ed25519
is faster thannode-forge
, but it's got an order of magnitude more variance in the time taken to run each iteration of the benchmark:Looking into the code,
@noble/ed25519
uses the native BigInt type in it's calculations instead of bn.js or long.js or similar - this is not recommended:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#cryptography
If operations are not constant-time, this could explain why the variance is so large, as the time taken to run an iteration will depend on the input, which means you can derive information about the input from the runtime behaviour of the system.
What do you think @hugomrdias @vasco-santos @dignifiedquire? Is this something to be concerned about and should we consider reverting #202?
The text was updated successfully, but these errors were encountered: