paulmillr / noble-secp256k1

Fastest 4KB JS implementation of secp256k1 signatures and ECDH
https://paulmillr.com/noble
MIT License
757 stars 114 forks source link

Consider using subtle from global object instead of crypto module #84

Closed webmaster128 closed 1 year ago

webmaster128 commented 1 year ago

Importing the "crypto" nodejs module is constantly causing trouble for us at CosmJS. E.g. in Webpack 5 you need to set a crypto: false, fallback but our Create React App users do not have access to a Webpack config as it is hidden by the framework. Recently a user reported issues around import("crypto") using the Metro bundler (React Native).

Now I see https://github.com/paulmillr/noble-secp256k1/blob/1.7.0/index.ts#L5 which implies there are two builds of this library, one for browsers. But when I use this library in a library, does this still work? How does noble-secp256k1 know where it will run eventually?

I wonder if the Node.js specific import is really needed. In all versions of Node 15+, subtle is available in globalThis?.crypto?.webcrypto?.subtle. From Node.js onwards it is avalable in globalThis?.crypto?.subtle, i.e. the same location as for browsers. This is how we now search subtle in CosmJS: https://github.com/cosmos/cosmjs/commit/7b32660d0832fce3bc3fb0789504ef66153810b5.

Using this method would remove support for Node.js 14 and lower.

paulmillr commented 1 year ago

In NPM, we publish common.js code and ESM code. They both have import statements.

In GitHub releases, we publish UMD build, which you could use on a web-page as-is.

If you're using NPM package, your bundler should auto-replace the import. We specify crypto: false in package.json. We do very extensive tests of building browser files in js-ethereum-cryptography.

Folks from Solana have been using their web3js recently with noble/ed25519 also without hassle. They are using react native.

I wonder if the Node.js specific import is really needed

~dev ❯ cat a.js 
console.log(globalThis?.crypto?.subtle);
console.log(globalThis?.crypto?.webcrypto?.subtle);
~dev ❯ node --version
v18.10.0
~dev ❯ node a.js 
undefined
undefined

Global crypto doesn't work in node. There's also Deno to consider, which we support.

webmaster128 commented 1 year ago

Thank you for all the details. I'll do a bit more digging to figure out if we see any issues.

Global crypto doesn't work in node.

Fascinating. It works in the Node REPL (tested Node 15, 16, 17, 18) but not when executing the same code in a .js file. In this case most of what I wrote becomes invalid.

paulmillr commented 1 year ago

Repl pre-loads some code, which is why it's less reliable than could have been.