-1
export const upgradeBase64crypto = (password) => {
    crypto.randomBytes(64, (err, buf) => {
        const salt = buf.toString("base64");
      
        crypto.pbkdf2(password, salt, 100, 64, "sha512", (err, key) => {
            return key.toString("base64");
        });
    });
};

import { upgradeBase64crypto } from "../../../utils/pwCrypto";

export default {
    Mutation: {
        signUpUser: async (_, args, { request, query }) => {
            try {
                const param = args.param;
                let pw = upgradeBase64crypto(param.pw);
              
                console.log(pw);
            } 
          catch (err) {}
        },
    },
};

When running console.log(key.toString('base64')) in upgradeBase64crypto, the normally encrypted string appears in the log. However, running return key.toString('base64') returns undefined. What's the problem?

zhulien
  • 5,145
  • 3
  • 22
  • 36
LEE.SANG.MIN
  • 141
  • 2
  • 2
  • 9
  • What's the value of 'args.param'? Did you debug it? – zhulien Dec 31 '20 at 10:29
  • It is certain that there is a password string. I checked. It will encrypt properly when running console.log instead of return. However, if you run a return, the value is not returned. – LEE.SANG.MIN Dec 31 '20 at 10:33
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – jonrsharpe Dec 31 '20 at 10:44

1 Answers1

4

You're not returning any value from the upgradeBase64crypto function. Try:

export const upgradeBase64crypto = (password) => {
    let passwordHash;

    crypto.randomBytes(64, (err, buf) => {
        const salt = buf.toString('base64');
        
        passwordHash = crypto.pbkdf2(password, salt, 100, 64, 'sha512', (err, key) => {
            return key.toString('base64');
        });
    });

    return passwordHash;
}

EDIT:

Sorry, missed the callback wrapping. This will solve your problem:

const upgradeBase64crypto = (password) => {
    return new Promise((resolve, reject) => {        
        crypto.randomBytes(64, (err, buf) => {
            const salt = buf.toString('base64');

            crypto.pbkdf2(password, salt, 100, 64, 'sha512', (err, key) => {
                resolve(key.toString('base64'));
            });
        })
    });
}

Previously you were trying to access the value before the callback's had the opportunity to set it as you're using the async versions of the crypto methods. Now it returns a promise. You'll need to .then or await the operation in your signUpUser method:

signUpUser: async (_, args, { request, query }) => {
    try {
        const param = args.param;
        let pw = await upgradeBase64crypto(param.pw);

        console.log(pw);
    }
    catch(error) { }
}
zhulien
  • 5,145
  • 3
  • 22
  • 36