异步功能错误处理未按预期工作

因此,我一直在弄乱node.js中的crypto模块,并且正在测试函数的错误处理。其中之一看起来像这样:

/**
 * Encrypts data. Class method
 * @param {string} data The data to be encrypted
 * @param {Function} cb Callback
 */
async encryptData(data, cb) {
   let err;
   let encryptedData = "";
   try {
      //Cipher config
      const cipherSalt = this.cipherSalt
      const cipherPword = this.cipherPword;
      const cipherIV = this.cipherIV;

      //The next line throws an error
      crypto.scrypt(cipherPword, cipherSalt, 12/*Must be 32*/, (er, derivedKey) => {
         if(er) {
            err = er;
            cb(err, null);
         }
         const cipher = crypto.createCipheriv(this.algorithm, derivedKey, cipherIV);
         let encrypted = cipher.update(data, "utf8", "hex");
         encrypted += cipher.final("hex");
         encryptedData = encrypted;
         return cb(null, encryptedData);
      });         
   } catch (error) {
      err = error;
      return cb(err, null);
   }
}

There is intentionally an error in there(I don't know why that is an error), to test the error handling of this function. The idea is, if there is an error, pass the error to the callback to be dealt with accordingly. If there isn't, then pass the results. But for some reason, when I run this program, it throws the Error from a file called cipher.js. Here:

Error: Invalid key length                                                                       cipher.js
    at Cipheriv.createCipherBase (internal/crypto/cipher.js:103:19)
    at Cipheriv.createCipherWithIV (internal/crypto/cipher.js:121:20)
    at new Cipheriv (internal/crypto/cipher.js:225:22)
    at Object.createCipheriv (crypto.js:117:10)
    at AsyncWrap.<anonymous> (c:\Users\Howti\Desktop\Coding\Programs\tests\crypto--https test\Lib\api.js:120:29)
    at AsyncWrap.wrap.ondone (internal/crypto/scrypt.js:43:48)

我希望从这样的回调中记录错误:

const cipherSalt = crypto.randomBytes(16).toString("hex");
const cipherPword = "do_NOT_breakthispassword1251342514540&&&*349-lf''@gmil";
const cipherIV = crypto.randomBytes(16);

let encrypter = new Encrypter(cipherSalt, cipherPword, cipherIV, algorithm);

encrypter.encryptData("HI, I'm Bluey", function(err, encryptedData) {
   //this doesn't work
   if(err){ 
      console.error(err);
      console.log("This will execute");//this won't execute
   }
   console.log(encryptedData);
});

But it doesn't. I tried other things, like promises and even synchronous functions; the synchronous function works, but I want it to be asynchronous. I tried sticking the async keyword in front of the function declaration, but it doesn't affect it.

承诺功能:

//This returns the same error as the one listed above
const encryptDataAsync = (data, cb) => new Promise((resolve, reject) => {
   let err;
   let encryptedData = "";
   //Cipher config
   const cipherSalt = crypto.randomBytes(16).toString("hex");
   const cipherPword = "do_NOT_breakthispassword1251342514540&&&*349-lf''@gmil";
   const cipherIV = crypto.randomBytes(16);

   //The next line throws an error
   crypto.scrypt(cipherPword, cipherSalt, 12/*Must be 32*/, (er, derivedKey) => {
      if(er) {
         err = er;
         reject(err);
      }
      const cipher = crypto.createCipheriv(algorithm, derivedKey, cipherIV);
      let encrypted = cipher.update(data, "utf8", "hex");
      encrypted += cipher.final("hex");
      encryptedData = encrypted;
      resolve(encryptedData);
   });
}).then((data) => {
   return cb(null, data);
}).catch((err) => {
   return cb(err, null);
});

同步功能

function encryptData(data, cb) {
   let err;
   let encryptedData = "";
   try {
      //Cipher config
      const cipherSalt = crypto.randomBytes(16).toString("hex");
      const cipherPword = "do_NOT_breakthispassword1251342514540&&&*349-lf''@gmil";
      const cipherIV = crypto.randomBytes(16);
      try {
         let key = crypto.scryptSync(cipherPword, cipherSalt, 12);
         let cipher = crypto.createCipheriv(algorithm, key, cipherIV);
         let encrypted = cipher.update(data, "utf8", "hex");
         encrypted += cipher.final("hex");
         encryptedData = encrypted;
         return cb(null, encryptedData);             
      } catch(error) {
         err = error;
         return cb(err, null)
      }
   } catch(error) {
      err = error;
      return cb(err, null);
   }
}

encryptData("HI, I'm Bruce", function(err, encryptedData) {
   if(err){ 
      console.error(err);
      console.log("This will execute");
   }
   console.log(encryptedData);
});

console.log("This will execute first");//Doesn't execute first

//Output:
//    Error: Invalid key length   ->From the console.error
//    This will execute           ->From the if(err) handler
//    null                        ->From the console.log
//    This will execute first     ->From the console.log at the end

So, my question: could I declare an asynchronous function and be able to handle this error in a callback? I like the idea of a asynchronous function and a callback, but if it just isn't possible, I won't do it. And also, if anyone could answer this, why does specifying(for me) a keylength of any number other than 32 throws an error in the crypto.scrypt() method?

评论