WhatsApp FLows - Could not decrypt the response received from the server

327 views Asked by At

I'm trying to generate the response for the WhatsApp flow using the WhatsApp business API with the following code

The decryption part is functioning correctly, but when I attempt to send the response, I'm receiving the error: "Could not decrypt the response received from the server."

I've referred to the documentation here, but I'm still struggling to find the correct approach for generating and validating the response.

Is there anyone who has experience with this API or can provide guidance on how to properly format and send the response? Any examples or links to relevant resources would be greatly appreciated.

def post(self, request, *args, **kwargs):
        try:
            dict_data = json.loads(request.body.decode('utf-8'))
            encrypted_flow_data_b64 = dict_data['encrypted_flow_data']
            encrypted_aes_key_b64 = dict_data['encrypted_aes_key']
            initial_vector_b64 = dict_data['initial_vector']
            
            flipped_iv = self.flip_iv(initial_vector_b64.encode('utf-8'))
            
            encrypted_aes_key = b64decode(encrypted_aes_key_b64)
            key_private = open('*******.pem', 'rb').read().decode('utf-8')
            private_key = load_pem_private_key(key_private.encode('utf-8'), password="*************".encode('utf-8'))
            
            aes_key = private_key.decrypt(encrypted_aes_key, OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None))
            aes_key_b64 = b64encode(aes_key).decode('utf-8')
            
            flow_data  = b64decode(encrypted_flow_data_b64)
            key = b64decode(aes_key_b64)
            iv = b64decode(initial_vector_b64)
            
            encrypted_flow_data_body = flow_data[:-16]
            encrypted_flow_data_tag = flow_data[-16:]
            cipher = Cipher(algorithms.AES(key), modes.GCM(iv,encrypted_flow_data_tag))
            decryptor = cipher.decryptor()
            decrypted_data = decryptor.update(encrypted_flow_data_body) + decryptor.finalize()
            flow_data_request_raw = decrypted_data.decode("utf-8")
            
            hello_world_text = "HELLO WORLD"
            
            response_data = {
                "version": "3.0",
                "screen": "MY_FIRST_SCREEN",
                "data": {
                    "hello_world_text": hello_world_text
                }
            }

            response_json = json.dumps(response_data)
            
            # Obtendo a chave AES após descriptografar encrypted_aes_key
            fb_aes_key = private_key.decrypt(encrypted_aes_key, OAEP(mgf=MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None))

            # Usando a chave AES para criptografar a resposta
            response_cipher = Cipher(algorithms.AES(fb_aes_key), modes.GCM(iv))
            encryptor = response_cipher.encryptor()
            encrypted_response = (
                encryptor.update(response_json.encode("utf-8")) +
                encryptor.finalize() +
                encryptor.tag
            )
            encrypted_response_b64 = b64encode(encrypted_response).decode("utf-8")
            
            # Construct the final response
            final_response = {
                "encrypted_flow_data": encrypted_response_b64,
                "encrypted_aes_key": encrypted_aes_key_b64,
                "initial_vector": initial_vector_b64
            }
            
            return JsonResponse(final_response, status=200)
        except Exception as e:
            print(e)
            return HttpResponse(status=500, content='ok')

    
    def flip_iv(self, iv):
        flipped_bytes = []
        for byte in iv:
            flipped_byte = byte ^ 0xFF
            flipped_bytes.append(flipped_byte)
        return bytes(flipped_bytes)

The entire decoding part is working normally but when returning the response I receive the error "Could not decrypt the response received from the server. "I can't find how to send the correct answer or how to validate it. The documentation can be found at https://developers.facebook.com/docs/whatsapp/flows/reference/implementingyourflowendpoint#data_exchange_request

Can anyone help me or show me a link I can test?

1

There are 1 answers

0
gafi On BEST ANSWER

I found a few problems with your code

  1. You need to flip the iv after base64 decoding like this
iv = b64decode(initial_vector_b64)
flipped_iv = flip_iv(iv)
  1. Use flipped_iv and variable named key in encryption (not fb_aes_key)
response_cipher = Cipher(algorithms.AES(key), modes.GCM(flipped_iv))
encryptor = response_cipher.encryptor()
encrypted_response = (
    encryptor.update(response_json.encode("utf-8")) +
    encryptor.finalize() +
    encryptor.tag
)
  1. Return response as plain text in body
encrypted_response_b64 = b64encode(encrypted_response).decode("utf-8")
return HttpResponse(encrypted_response_b64, content_type='text/plain')