digitalbazaar / forge

A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps
https://digitalbazaar.com/
Other
5.01k stars 767 forks source link

Inconsistent Key Generation using seed value #1076

Open briancorbin opened 3 months ago

briancorbin commented 3 months ago

I have an issue where depending on whether I use a callback or not, the keyPair that is generated is different. Any idea what may be causing this? I would expect the keyPair to be the same regardless, no?

export async function getAsymmetricKeyPair(
  ctx: Ctx,
  seedValue?: string
): Promise<forge.pki.rsa.KeyPair> {
  const prng = forge.random.createInstance();
  if (seedValue) {
    prng.seedFileSync = (_n: number) => seedValue;
    prng.seedFile = (_n: number, cb: forge.random.CB) => {
      cb(null, seedValue);
    };
  }

  const options: forge.pki.rsa.GenerateKeyPairOptions = {
    bits: 2048,
    e: 65537,
    prng,
  };
  if (!ctx.disableWorkers) {
    options.workLoad = 100;
    // only using 1 web worker as more makes the call non-deterministic
    // -1 uses optimal amount of web workers
    options.workers = seedValue ? 1 : -1;

    const workerRes = await fetch(`${getPortalBaseURL(ctx)}/static/js/prime.worker.min.js`);
    const workerBlob = new Blob([await workerRes.text()], { type: 'application/javascript' });
    options.workerScript = URL.createObjectURL(workerBlob);
  }

  console.log('generating key pair...');
  // const keyPair = rsa.generateKeyPair(options);
  const keyPair = await new Promise<forge.pki.rsa.KeyPair>((resolve, reject) => {
    rsa.generateKeyPair(options, (err, keyPair) => {
      if (err) {
        reject(err);
      } else {
        resolve(keyPair);
      }
    });
  }
  );
  console.log('public key:', keyPair.publicKey.n.data);
  console.log('key pair generated');
  return keyPair;
}
davidlehn commented 2 months ago

We haven't had much time to look at this. Which callback do you mean? Are calling in a way that ensures only one worker is in use? As the comment notes, it's non-deterministic with more than 1 worker. Is there an easy way to run this to show the issue?

briancorbin commented 2 months ago

Yeah I am sure it's setting workers to 1 when given a seed value. I've also recreated this outside of the project it's coming from

briancorbin commented 2 months ago

But I will double check again for sanity!

briancorbin commented 2 months ago

And I mean the callback that you can optionally include in the rsa.generateKeyPair function

davidlehn commented 2 months ago

Do you have a repo or gist or something that can be easily run?

briancorbin commented 2 months ago

Yeah, lemme get that for you, gotta look through my projects again