I am using C# to decrypt a request from data_exchange in Whatsapp flows successfully using BouncyCastle 2.3.1,
however I am having issues on decryption whatsApp playground says it cannot decrypt the response that I am providing(from the server).
Below is my code.
var aesKey = DecryptUsingRsa(privateKey, encryptedAesKey); //Decrypting the aes_key from the request and its working on decryption.
Working Decryption method
public static byte[] Encrypt(byte[] plaintext, byte[] key, byte[] iv)
{
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(new KeyParameter(key), 128, iv);
cipher.Init(true, parameters);
var ciphertext = new byte[cipher.GetOutputSize(plaintext.Length)];
var len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, ciphertext, 0);
cipher.DoFinal(ciphertext, len);
var authenticationTag = cipher.GetMac();
var combinedCiphertext = new byte[ciphertext.Length + authenticationTag.Length];
Array.Copy(ciphertext, 0, combinedCiphertext, 0, ciphertext.Length);
Array.Copy(authenticationTag, 0, combinedCiphertext, ciphertext.Length, authenticationTag.Length);
return combinedCiphertext;
}//Working decryption method
The WAExchangeResponse is the response to be sent to WhatsApp according to the expected structure
public class WAExchangeResponse
{
public string version { get; set; }
public string screen { get; set; }
public Dictionary<string, string> data { get; set; }
}
byte[] responsePayload = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(wAExchangeResponse));// convert the response object to byte array after I serialize it.
byte[] flippedIV = FlipIv(initialVector);// byte array with inverted bits from the initialization vector received in the request.
private static byte[] FlipIv(byte[] iv)
{
for (int i = 0; i < iv.Length; i++)
{
iv[i] ^= 0xFF; // Invert all bits
}
return iv;
}// the method
var encryptedPayload = Encrypt(responsePayload, aesKey, responseIV);//encrypting the payload
private static byte[] Encrypt(byte[] plaintext, byte[] key, byte[] iv)
{
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(new KeyParameter(key), 128, iv);
cipher.Init(true, parameters);
var ciphertext = new byte[cipher.GetOutputSize(plaintext.Length)];
var len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, ciphertext, 0);
cipher.DoFinal(ciphertext, len);
var authenticationTag = cipher.GetMac();
var combinedCiphertext = new byte[ciphertext.Length + authenticationTag.Length];
Array.Copy(ciphertext, 0, combinedCiphertext, 0, ciphertext.Length);
Array.Copy(authenticationTag, 0, combinedCiphertext, ciphertext.Length, authenticationTag.Length);//appending authentication tag generated during encryption to the end of the encryption result;
return combinedCiphertext;
}
string base64String = Convert.ToBase64String(encryptedPayload);//encoding the whole output as base64 string
Then in the controller I call the servic that return the above base64String as below
[HttpPost("")]
public IActionResult Create(WAEndpointRequest wAEndpointRequest)
{
var base64String = _processor.Create(wAEndpointRequest);
Response.ContentType = "text/plain";
Response.ContentLength = base64String.Length;
Response.StatusCode = 200;
return Content(base64String, "text/plain", Encoding.UTF8);
}
This is according to the documentation here https://developers.secure.facebook.com/docs/whatsapp/flows/guides/implementingyourflowendpoint#request-decryption-and-encryption
I was expecting Whatsapp playground to be able to decrypt the response I am providing since the decryption is working well and I am following the documentaion.