node.jscryptographywhatsapp-flows

WhatsApp FLows - Could not decrypt the response received from the server in node js. Getting error RangeError: Invalid key length


I am trying to decrypt to below json with node js code where i am getting invalid key length error crypto.createDecipheriv

{
"encrypted_flow_data": "EfdsCol+ZQMdkWYaa+cB247XRCfTbMkfdwR68ZwU1pQgby4P8tR2l7qDDjh/uLCkzutO0GuMQxoVfm/sluoj4OuMzsd9AttTerts4vcvaDWrbBcXpH5r3m4vu6iNwTQHV4kmL2sETB1g22VbEA==",
"encrypted_aes_key": "A01kXb7211vxwfZbSlxN9fxL/HUWBhxjVovJ6jirVzUYK7CYLnlcBoR4AwIWIiP3NSra8DRvVd9gulu+jdDJEbf+8HZHk1k5EllcSFV/r/x1PLwpQ6v8AeOhbfEp8qyjSxb3Ah6/CrY6oDWDLiyqpAWz3KK4UmWw9VxiJOHdLhvfa3lH22zwReboiJyUPFbjKlzKUudnS8EI5JU+ZUW3reEOB5JS8bMJ06asHYm723VUvC3cs8qv1/G02NPlOo3G9sknDSr3fo0uIm5drvq3flLW6Mvcx469Y97x3j44RjEIyXMIs8zUyOo5h9MrTuwruPsjhcBFIByDHH7wwTMPQw==",
"initial_vector": "oqVIt/A7/MWVY4hE9IHb6A=="
}
    const crypto = require('crypto');   
    const fs = require('fs');
    const util = require('util');
    const { TextEncoder } = require('util');
    const { TextDecoder } = require('util');
    const { promisify } = require('util');
    const readFile = promisify(fs.readFile);

    const dict_data = req.body; // Assuming request.body is already a JSON string

    const encrypted_flow_data_b64 = dict_data.encrypted_flow_data;
    const encrypted_aes_key_b64 = dict_data.encrypted_aes_key;
    const initial_vector_b64 = dict_data.initial_vector;

    const flipped_iv = flip_iv(Buffer.from(initial_vector_b64, 'base64'));

    const encrypted_aes_key = Buffer.from(encrypted_aes_key_b64, 'base64');

    
    const privateKeyPEM = readFile('****/private_key.pem', 'utf-8');
    crypto.createPrivateKey({ key: privateKeyPEM, format: 'pem'});
    

    //const privateKeyPem = fs.readFileSync('****/private_key.pem', 'utf-8');

    //const private_key = loadPrivateKey();
    //console.log(private_key);
    const aes_key = crypto.privateDecrypt(
        {
            key: privateKeyPem,
            oaepHash: 'sha256',
            padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
        },
        encrypted_aes_key
    );

    const aes_key_b64 = aes_key.toString('base64');
    const flow_data = Buffer.from(encrypted_flow_data_b64, 'base64');
    const key = Buffer.from(aes_key_b64, 'base64');
    const iv = Buffer.from(initial_vector_b64, 'base64');

    const encrypted_flow_data_body = flow_data.slice(0, flow_data.length - 16);
    const encrypted_flow_data_tag = flow_data.slice(flow_data.length - 16);

    const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
    decipher.setAuthTag(encrypted_flow_data_tag);

    let decrypted_data = decipher.update(encrypted_flow_data_body, 'binary', 'utf-8');
    decrypted_data += decipher.final('utf-8');

    const flow_data_request_raw = decrypted_data;
    console.log('flow_data_request_raw',flow_data_request_raw);

I want Request Decryption and Response Encryption for whatsapp flow end point whatsapp endpoint logic


Solution

  • I think you need to await the promise of the read file, like this

    const privateKeyPEM = await readFile('****/private_key.pem', 'utf-8');
    

    There's a full code example in the documentation for encryption/decryption which might be helpful https://developers.facebook.com/docs/whatsapp/flows/guides/implementingyourflowendpoint#nodejs-express-example