sendgrid / sendgrid-java

The Official Twilio SendGrid Led, Community Driven Java API Library
https://sendgrid.com
MIT License
485 stars 409 forks source link

Webhook signature verification is not working (java 8) #681

Closed rothenbuhlerm-dnb closed 3 years ago

rothenbuhlerm-dnb commented 3 years ago

Issue Summary

Webhook signature verification is not working

Steps to Reproduce

Run the code below, test fails but it should succeed. All values are directly from real test data, directly from the test site https://webhook.site/. I suspect this is because there is some issue coming through for the json formatting.

When I fire up an api and hit it with the exact same values, it also just fails. I cannot get this to work.

import java.security.Security;
import java.security.interfaces.ECPublicKey;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.testng.Assert;
import org.testng.annotations.Test;

import com.sendgrid.helpers.eventwebhook.EventWebhook;

public class WebhookCryptographyTester {
    private static final String TEST_MASTER_KEY =
            "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6SXwY3dSk070Z1JHAWXEaYJ25fmcOAOp/Xq+QJR//1dqdebJ8cWZroZAjzwnwQca1vf6l2KwJK6+Ao6H9P66aA==";

    private static final String TEST_PUBLIC_KEY =
            "MEYCIQDOt4+CDrZEt6e12EZGu9Bg2WqkHO681pmAyXZia3XYeAIhAK6CpxQi1uGLqioeYwuieDK4MPJPVdpRt7prjV2AcBbg";
    private static final String TEST_TIMESTAMP = "1619821428";
    private static final String TEST_BODY = "[{\"email\":\"lmejia@presidio.com\",\"event\":\"click\",\"ip\":\"54.71.187.124\",\"sg_event_id\":\"ndITrzI2S16OmvKxEsNT_g\",\"sg_message_id\":\"E6SO3lvdSTO3n5kxtnN4gw.filterdrecv-5d58f8bcff-szfhb-1-608C8363-4F.0\",\"timestamp\":1619821415,\"url\":\"https://app.lattice-engines.com\",\"url_offset\":{\"index\":0,\"type\":\"html\"},\"useragent\":\"Mozilla/5.0 (compatible; pycurl)\"}]";

    @Test
    public void testWebhookCryptography() throws Exception {
        ECPublicKey masterKey;
        EventWebhook verifier;
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            BouncyCastleProvider provider = new BouncyCastleProvider();
            Security.addProvider(provider);
        }
        verifier = new EventWebhook();
        masterKey = verifier.ConvertPublicKeyToECDSA(TEST_MASTER_KEY);

        Assert.assertTrue(verifier.VerifySignature(masterKey, TEST_BODY, TEST_PUBLIC_KEY, TEST_TIMESTAMP));
    }
}
rothenbuhlerm-dnb commented 3 years ago

OK finally solved--note this library is EXTREMELY TEMPERAMENTAL.

There is no documentation for these rules anywhere, but they must be followed to the letter:

  1. JSON format must be completely compact, no whitespace characters allowed between keys values etc
  2. The order of fields is mandatory--I don't know what the order is, but it's mandatory
  3. The string, after the final JSON closing bracket or brace, must have the exact characters \r\n in order to work.