StableLib / stablelib

A stable library of useful TypeScript/JavaScript code
https://www.stablelib.com
Other
173 stars 35 forks source link

[random] fails when ran in modern NodeJS environment #53

Closed xzilja closed 2 years ago

xzilja commented 2 years ago

When NodeJS is used in a modern way "es modules", random package errors with following output

throw new Error("System random byte generator is not available.");

After digging a bit through the source, I believe it is due to this check, as require is not available in this case https://github.com/StableLib/stablelib/blob/master/packages/random/source/node.ts#L16

dchest commented 2 years ago

How can I reproduce this? What are the flags to use Node in ES modules only mode?

xzilja commented 2 years ago

How can I reproduce this? What are the flags to use Node in ES modules only mode?

All thats required is to add "type": "module" in package.json file (or use any other alternative method described in https://nodejs.org/api/esm.html "Enabling" section) as well as use node version that supports this (LTS for example). Then just calling randomBytes should throw the error because browser and node check won't be satisfied.

dchest commented 2 years ago

Hmm, so any CommonJS module can't be used from ES Node module? This is strange. I can't reproduce this:

package.json

{
  "name": "bla",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@stablelib/random": "^1.0.1"
  }
}

index.js

import random from '@stablelib/random';

console.log(random.randomString(10));

Output:

$ node index.js
ZtIk3GIjVP

Node v18.4.0.

dchest commented 2 years ago

In any case, if you need a quick workaround, all functions that need RandomSource accept a custom one as an optional parameter, so instead of using the default one, you can write your own — just copy https://github.com/StableLib/stablelib/blob/master/packages/random/source/node.ts and replace its constructor with something like this:

...
import crypto from 'crypto';

export class MyRandomSource implements RandomSource {
...
    constructor() {
        this._crypto = crypto;
        this.isAvailable = true;
        this.isInstantiated = true;
    }
...

(remove TypeScript types if you don't use it, of course).

Then instantiate it somewhere:

const myRandom = new MyRandomSource()

it and pass it to functions that require randomness, for example, ed25519.generateKeyPair() will become ed25519. generateKeyPair(myRandom) or even random.randomString(10, "abcdef", myRandom).

PS I'm interested in the steps to reproduce this error.

beautyfree commented 9 months ago

has same issue