Home > Software design >  ECMAScript 8, async await, syntactical errors javascript
ECMAScript 8, async await, syntactical errors javascript

Time:11-27

using more then one async() in a chain in the function breaks my function. Is there a way i can include Key2pkcs8() inside generateKey() ?

async function generateKey() {
  let getKeyPair = await crypto.subtle.generateKey(
    {
      name: "ECDH",
      namedCurve: "P-384"
    },
    false,
    ["deriveKey"]
  );

  let PriKey = async() => {
    let PriKey = await getKeyPair.privateKey;
    console.log("pri = "   PriKey);
    return PriKey;
  };
  let PubKey = async() => {
    let PubKey = await getKeyPair.publicKey;
    console.log("pub = "   PubKey);
  };

  let Key2pkcs8 = async(PriKey, PubKey) => {
    let Key2pkcs8Pub = await crypto.subtle.exportKey("pkcs8", PubKey);
    let Key2pkcs8Pri = await crypto.subtle.exportKey("pkcs8", PriKey);
    return pkcs8keyarray = [Key2pkcs8Pub, Key2pkcs8Pri];
  
  return Keyarray = [PriKey(), PubKey()];  // i want to put <return pkcs8keyarray()> here  
};

generateKey().then(Key2pkcs8 => console.log(Key2pkcs8[0], Key2pkcs8[1])); works as expected and returns pri = [object CryptoKey] Promise { <state>: "fulfilled", <value>: undefined } Promise { <state>: "fulfilled", <value>: CryptoKey }

but when using return pkcs8keyarray() instead of return Keyarray = [PriKey(), PubKey()]; it breaks and returns undefined

i had intended to have key2pkcs2 take a key as a variable (public or private key) and then return both in a array at the end similar to the example

CodePudding user response:

Your program demonstrates a misunderstanding of promises, async/await, the crypto module, and javascript as a whole.

  • Use let only when you want to reassign values to a binding
  • Don't reassign functions to values, especially where it's easily avoidable
  • Statements like return Keyarray = ... are leaking global variables and do not behave like you are probably expecting
  • You do not need to create a new async function every time you want to await another asynchronous value
  • You cannot simply console.log the private or public keys. Per the exportKey docs, it returns a promise that resolves to an ArrayBuffer which is raw byte data and does not have a string representation.
async function generateKey() {
  const {privateKey, publicKey} =        // <- get privateKey, publicKey
    await crypto.subtle.generateKey(
      {
        name: "ECDH",
        namedCurve: "P-384"
      },
      true,
      ["deriveKey"]
    )

  return [
    await crypto.subtle.exportKey("pkcs8", privateKey), // <- export private
    await crypto.subtle.exportKey("pkcs8", publicKey),  // <- export public
  ]
}

Since generateKey is returning an array pair of [private, public], we can easily use these in the other async functions you write -

async function myfunction() {
  const [private, public] = await generateKey() // <- resolves pair
  // do something
}

Move all side effects downstream in .then handlers. Caller is responsible for catching errors. Always handle errors -

myfunction().then(console.log).catch(console.error)

Do not try to implement cryptographic solutions if you do not understand these simple things. You will 100% get something wrong and you will introduce a vulnerability and you and your users will suffer the consequences.

Code in this answer is unttested and only here to highlight the mistakes I can readily see. Do not use the code verbatim and do not expect it to copy/paste it directly into your project. I do not understand what your requirements or intentions are and therefore cannot possibly make recommendations or offer other advice.

For more info on misuse of async and await, see this related Q&A.

CodePudding user response:

async function generateKey() {
  let keyPair = await crypto.subtle.generateKey(
    {
      name: "ECDH",
      namedCurve: "P-384"
    },
    false,
    ["deriveKey"]
  );

  let PriKey = (keyPair) => {
    let PriKey = keyPair.privateKey;
    console.log("pri = "   PriKey);
    return keyPair;
  };
  let PubKey = (keyPair) => {
    let PubKey = keyPair.publicKey;
    console.log("pub = "   PubKey);
    return keyPair;
  };

  let Key2pkcs8 = async(keyPair) => {
    console.log("key = "   keyPair);
    let Key2pkcs8 = await crypto.subtle.exportKey("pkcs8", keyPair);
    return Key2pkcs8;
  };

  let printme = async() => {
    let printme = await Key2pkcs8(PubKey());
    console.log(printme);
    return printme;
  };

  return printme();
}

Usage:

generateKey().then(Key2pkcs8 => console.log(Key2pkcs8 ));

If your outer iife is async, await will already convert async flow to sync, meaning getKeyPair (or keyPair in my snippet) will already be available by the time you call other functions.

PubKey and PriKey need not to be async, and in both cases you are not returning anything. Key2pkcs8 is not returning anything either, so what exactly do you want await Key2pkcs8(PubKey());to return? Ideally all these functions should return something if you want the resulting Promise to resolve to something other than undefined. Give the above snippet a go, I did not test it.

  • Related