2

Ok, so I am trying to generate a public and private key using crypto (https://nodejs.org/api/crypto.html#crypto_crypto_generatekeypair_type_options_callback)

The thing is, one of the parameters of the generateKeyPair is a callback function, and I can't get my code to wait for the callback to run. It runs eventually, but by then I already tried to use the data. The idea is to do something like this:

const _getKeyPair = (pwd: string): Object => {
    const { generateKeyPair }: any = require('crypto');

    const keyPair = { publicKey: '', privateKey: '' };
    generateKeyPair('rsa', {
        modulusLength: 4096,
        publicKeyEncoding: {
            type: 'spki',
            format: 'pem'
        },
        privateKeyEncoding: {
            type: 'pkcs8',
            format: 'pem',
            cipher: 'aes-256-cbc',
            passphrase: pwd
        }
    }, (err: Error, publicKey: string, privateKey: string) => {
        if (err) {
            throw err;
        }
        keyPair.publicKey = publicKey;
        keyPair.privateKey = privateKey;
    });

    return keyPair;
};

And call:

const keyPair = _getKeyPair('myPassword');
2
  • 1
    So, a Javascript function that retrieves a value asynchronously via a callback simply cannot return that value from the function. As you've already seen, the function returns BEFORE the callback is called and thus the value is not know when the function returns. Your options for communicating back the asynchronous value are a callback, a promise or an event. Details here How do I return the response from an asynchronous call. Commented Apr 28, 2020 at 22:53
  • 1
    You don't "wait on a callback" in Javascript before returning. Even if you move to all promises and use async/await, the function is still returning a promise at the point of your first await, it's just the resolving of the promise that gets delayed and the caller has to use the promise with await or .then() to get the value. Commented Apr 28, 2020 at 23:01

1 Answer 1

6

crypto has two methods to generate key pair, an asynchronous one generateKeyPair and a synchronous one generateKeyPairSync which you can use without having to worry about callbacks if that's what you want. Another way is to wrap the method with a promise and use await. Something like:

const _getKeyPair = async (pwd) => {
  const { generateKeyPair } = require('crypto');

  return new Promise((resolve, reject) => {
    generateKeyPair('rsa', {
      modulusLength: 4096,
      publicKeyEncoding: {
        type: 'spki',
        format: 'pem'
      },
      privateKeyEncoding: {
        type: 'pkcs8',
        format: 'pem',
        cipher: 'aes-256-cbc',
        passphrase: pwd
      }
    }, (err, publicKey, privateKey) => {
      if (err) return reject(err);
      resolve({publicKey, privateKey});
    });
  });
};

async function main() {
  const keyPair = await _getKeyPair('myPassword');
}

main();
Sign up to request clarification or add additional context in comments.

1 Comment

It should be noted that the reason the crypto module offers asynchronous (callback-based) operations is because some crypto operations are CPU-intensive and can block the event loop for an undesired amount of time. When you use the asynchronous versions, it passes the crypto operations off to the thread pool and the CPU intensive work is performed without blocking the event loop. So, it's not always the best choice to just skip over to the synchronous methods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.