Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify crypto usage #178

Merged
merged 3 commits into from
Apr 22, 2024
Merged

Simplify crypto usage #178

merged 3 commits into from
Apr 22, 2024

Conversation

jeluard
Copy link
Contributor

@jeluard jeluard commented Apr 18, 2024

Rely on noble-hashes to simplify crypto usage and make sure no polyfills are required.

@jeluard jeluard requested a review from a team as a code owner April 18, 2024 14:10
@jeluard jeluard force-pushed the jeluard/use-noble-hashes branch from 55fd0f5 to e35f879 Compare April 18, 2024 14:20
Copy link
Member

@wemeetagain wemeetagain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need all of @noble/hashes, rather, I think we can just use webcrypto directly.

eg:

export function randomBytes(length: number): Uint8Array {
  const getRandomValues = globalThis.crypto.getRandomValues;
  if (getRandomValues) {
    return getRandomValues(new Uint8Array(length));
  } else {
    throw new Error("no supported WebCrypto#getRandomValues found");
  }
}

@jeluard
Copy link
Contributor Author

jeluard commented Apr 18, 2024

I don't think we need all of @noble/hashes, rather, I think we can just use webcrypto directly.

That's the approach I started with in #159 but unfortunately webcrypto has been supported in nodejs starting version 20 (and we want to support 18). So there's a need to have some import crypto somewhere to leverage the old nodejs crypto. noble handles that with some exports and global checks.
Also bls already depends on @noble/hashes indirectly via @chainsafe/bls-keygen.

package.json Outdated Show resolved Hide resolved
src/blst-native/secretKey.ts Outdated Show resolved Hide resolved
@matthewkeil
Copy link
Member

@jeluard I went to close #66 and noticed that it is attempting to do something similar to what you are here. Please take a look at that and tell me if its a good idea or not. Feel free to move that code over to here if you think it'll help towards our goal of isomorphism

Copy link
Member

@matthewkeil matthewkeil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the question about moving from dep to devDep. Also a small conflict in webpack config. Otherwise LGTM! 🚀

package.json Outdated Show resolved Hide resolved
@jeluard jeluard force-pushed the jeluard/use-noble-hashes branch from 10b6b33 to 889e1ec Compare April 22, 2024 09:56
@jeluard jeluard force-pushed the jeluard/use-noble-hashes branch from 889e1ec to e36077f Compare April 22, 2024 10:00
@jeluard jeluard requested a review from matthewkeil April 22, 2024 10:03
Copy link
Member

@matthewkeil matthewkeil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!!! 🎸

@matthewkeil matthewkeil merged commit 1e29a6c into master Apr 22, 2024
5 checks passed
@matthewkeil matthewkeil deleted the jeluard/use-noble-hashes branch April 22, 2024 10:21
@wemeetagain
Copy link
Member

unfortunately webcrypto has been supported in nodejs starting version 20 (and we want to support 18).

Doesn't seem to be the case for the latest 18 (the ones supported via LTS)

$ nvm run 18
Running node v18.16.0 (npm v9.5.1)
Welcome to Node.js v18.16.0.
Type ".help" for more information.
> crypto.getRandomValues(new Uint8Array(4))
Uint8Array(4) [ 191, 254, 240, 7 ]

@matthewkeil
Copy link
Member

unfortunately webcrypto has been supported in nodejs starting version 20 (and we want to support 18).

Doesn't seem to be the case for the latest 18 (the ones supported via LTS)

$ nvm run 18
Running node v18.16.0 (npm v9.5.1)
Welcome to Node.js v18.16.0.
Type ".help" for more information.
> crypto.getRandomValues(new Uint8Array(4))
Uint8Array(4) [ 191, 254, 240, 7 ]

It is in 18+ for sure...

@jeluard
Copy link
Contributor Author

jeluard commented Apr 22, 2024

I remember some issues when running benchmarks, so would need to investigate that.
Switching to webcrypto would definitely be a win, and allow us to migrate to latest bls-eth-wasm.

@jeluard
Copy link
Contributor Author

jeluard commented Apr 22, 2024

@matthewkeil @wemeetagain It is only available by default starting 19, before that it was behind an experimental flag --experimental-global-webcrypto. See https://nodejs.org/api/globals.html#crypto , in the history section.
Not sure why it works in the repl as is.

@wemeetagain
Copy link
Member

wemeetagain commented Apr 25, 2024

So nodejs crypto global has been available since at least 16, and crypto.getRandomValues has beein available since 17.4. It just hasn't been fully webcrypto compatible.
It used to be that globalThis.crypto === require("node:crypto") rather than globalThis.crypto === require("node:crypto").webcrypto.

The docs mention This implementation is not compliant with the Web Crypto spec, to write web-compatible code use [crypto.webcrypto.getRandomValues()](https://nodejs.org/docs/latest-v18.x/api/webcrypto.html#cryptogetrandomvaluestypedarray) instead.
This is only "non-compliant" because the Web Crypto spec is very specific about the this when the function is called. The Web Crypto spec says it can't be called with a this other than WebCrypto. But this isn't a problem when using the function like so: crypto.getRandomValues(...).

@jeluard
Copy link
Contributor Author

jeluard commented Apr 25, 2024

As seen in benchmarks it fails due to undefined crypto on node18. It's pretty much raw js running on node, but there might be something else triggering the error.

A quick test though:

❯ cat crypto.js
console.log(crypto.getRandomValues(new Uint32Array(10)));

❯ nvm use 18
Now using node v18.20.2 (npm v10.5.0)

❯ node crypto.js
console.log(crypto.getRandomValues(new Uint32Array(10)));
            ^

ReferenceError: crypto is not defined
    at Object.<anonymous> (/Users/julien/Documents/Projects/chainsafe/lodestar/crypto.js:1:13)
    at Module._compile (node:internal/modules/cjs/loader:1364:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1422:10)
    at Module.load (node:internal/modules/cjs/loader:1203:32)
    at Module._load (node:internal/modules/cjs/loader:1019:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:128:12)
    at node:internal/main/run_main_module:28:49

Node.js v18.20.2

❯ nvm use 20
Now using node v20.10.0 (npm v10.2.3)

❯ node crypto.js
Uint32Array(10) [
   571407740,  599494301,
  2559257699, 2926223660,
  1819057593, 1184599816,
  1069392847, 2779221017,
  3060504880, 2988982603
]

So there's probably something else to it.

@wemeetagain
Copy link
Member

Ok, yeah I see that now. So strange that the repl is different than running a script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants