lkorth / php-gcm

An easy to use gcm library for PHP
Apache License 2.0
180 stars 47 forks source link

Support for Web Push Payload Encryption #22

Open delitestudio opened 8 years ago

delitestudio commented 8 years ago

Hello, as you know Google Chrome Push Notifications use GCM. But there is a downside:

A downside to the current implementation of the Push API in Chrome is that you can’t send any data with a push message. Nope, nothing. The reason for this is that in a future implementation, payload data will have to be encrypted on your server before it’s sent to a push messaging endpoint. This way the endpoint, whatever push provider it is, will not be able to easily view the content of the push message. This also protects against other vulnerabilities like poor validation of HTTPS certificates and man-in-the-middle attacks between your server and the push provider. However, this encryption isn’t supported yet, so in the meantime you’ll need to perform a fetch to get information needed to populate a notification.

In those months Google has implemented a solution that will be available in the new version Chrome 50 at the end of April 2016.

Do you think this kind of encrypted payload can be implemented into your library?

lkorth commented 8 years ago

Yes, it should be pretty easy to encrypt the payload before it is sent based on some optional parameters.

If you'd like to take a stab at implementing it, I'd be happy to review and provide some feedback for a pull request.

delitestudio commented 7 years ago

Hello @lkorth, we have implemented some properties on the Message class (publicKey, salt, rawData) with getters and setters.

We have then modified the Sender to intercept those properties (only if set) and add appropriate headers:

Encryption: salt=<SALT>
Crypto-Key: dh=<PUBLICKEY>
Content-Encoding: aesgcm

and body field for the notification request (as explained here):

{
    "registration_ids": [ "…" ],
    "raw_data": "BIXzEKOFquzVlr/1tS1bhmobZ…"
}

This way your library can be used to send encrypted messages without having to encrypt them: is up to the user to give a correct rawData content.

Here an example:

$message = new Message();
$message->publicKey($publicKey);
$message->salt($salt);
$message->rawData(base64_encode($encryptedPayload));

If you are interested we'll make a pull request. At the moment we have implemented it above your latest stable release but it's not hard to port it to the developer one.

lkorth commented 7 years ago

If you'd like to make a PR with those changes, that would be awesome! If you're already encrypting the data, would you consider adding a method to the Message class for encrypting data? When it builds the message, if the public key and salt are present it could just encrypt it for you.

A few things have moved around in the Sender class, but it should be trivial to update to include the headers. The only other change that I see off hand is just making the functions on Message chainable.

Let me know if I can clarify anything, otherwise I look forward to reviewing the PR.

delitestudio commented 7 years ago

We will create the PR as soon as possible. Unfortunately the encryption stuff is really complex and we are using code from an external library (WebPush) that depends from many other libraries.

So we have decided to decouple the payload handling stuff from the encryption tasks to ease the PR. Please take a look at their code, maybe you can use it to implement the same stuff in your library in future.