Search code examples
node.jscryptojs

node.js crypto pbkdf2 return undefined


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?


Solution

  • 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) { }
    }