|
16 | 16 | use Buzz\Client\MultiCurl;
|
17 | 17 | use Buzz\Exception\RequestException;
|
18 | 18 | use Buzz\Message\Response;
|
| 19 | +use Mdanter\Ecc\EccFactory; |
| 20 | +use Mdanter\Ecc\Message\MessageFactory; |
19 | 21 |
|
20 | 22 | class WebPush
|
21 | 23 | {
|
@@ -126,20 +128,88 @@ public function sendNotifications(array $endpoints, array $payloads = null, arra
|
126 | 128 | 'success' => true,
|
127 | 129 | );
|
128 | 130 | }
|
129 |
| - private function sendToStandardEndpoints(array $endpoints, array $payloads = null, array $userPublicKeys = null) |
| 131 | + |
| 132 | + /** |
| 133 | + * @param string $userPublicKey base 64 encoded |
| 134 | + * @param string $payload |
| 135 | + * |
| 136 | + * @return array |
| 137 | + * |
| 138 | + * @throws |
| 139 | + */ |
| 140 | + private function encrypt($userPublicKey, $payload) |
130 | 141 | {
|
131 |
| - $headers = array( |
132 |
| - 'Content-Length' => 0, |
133 |
| - ); |
| 142 | + throw new \ErrorException('Encryption does not work yet.'); |
134 | 143 |
|
135 |
| - $content = ''; |
| 144 | + // get local curve |
| 145 | + $localCurveGenerator = EccFactory::getNistCurves()->generator256(); |
| 146 | + $localPrivateKey = $localCurveGenerator->createPrivateKey(); |
| 147 | + $localPublicKey = $localPrivateKey->getPublicKey(); |
| 148 | + // var sharedSecret = localCurve.computeSecret(userPublicKey); |
136 | 149 |
|
137 |
| - if (isset($this->TTL)) { |
138 |
| - $headers['TTL'] = $this->TTL; |
139 |
| - } |
| 150 | + //var salt = crypto.randomBytes(16); |
| 151 | + |
| 152 | + //ece.saveKey('webpushKey', sharedSecret); |
140 | 153 |
|
| 154 | + /*var cipherText = ece.encrypt(payload, { |
| 155 | + keyid: 'webpushKey', |
| 156 | + salt: urlBase64.encode(salt), |
| 157 | + });*/ |
| 158 | + |
| 159 | + $messages = new MessageFactory(EccFactory::getAdapter()); |
| 160 | + $message = $messages->plaintext($payload, 'sha256'); |
| 161 | + |
| 162 | + $dh = $localPrivateKey->createExchange($messages, $userPublicKey); |
| 163 | + $salt = hash('sha256', $dh->calculateSharedKey(), true); |
| 164 | + |
| 165 | + $cipherText = $dh->encrypt($message)->getContent(); |
| 166 | + |
| 167 | + return array( |
| 168 | + 'localPublicKey' => base64_encode($localPublicKey), |
| 169 | + 'salt' => base64_encode($salt), |
| 170 | + 'cipherText' => base64_encode($cipherText), |
| 171 | + ); |
| 172 | + } |
| 173 | + |
| 174 | + /** |
| 175 | + * @param array $endpoints |
| 176 | + * @param array|null $payloads |
| 177 | + * @param array|null $userPublicKeys |
| 178 | + * |
| 179 | + * @return array |
| 180 | + * |
| 181 | + * @throws \ErrorException |
| 182 | + */ |
| 183 | + private function sendToStandardEndpoints(array $endpoints, array $payloads = null, array $userPublicKeys = null) |
| 184 | + { |
141 | 185 | $responses = array();
|
142 | 186 | foreach ($endpoints as $i => $endpoint) {
|
| 187 | + $payload = $payloads[$i]; |
| 188 | + |
| 189 | + if (isset($payload)) { |
| 190 | + $encrypted = $this->encrypt($userPublicKeys[$i], $payload); |
| 191 | + |
| 192 | + $headers = array( |
| 193 | + 'Content-Length' => strlen($encrypted['cipherText']), |
| 194 | + 'Content-Type' => 'application/octet-stream', |
| 195 | + 'Encryption-Key' => 'keyid=p256dh;dh='.$encrypted['localPublicKey'], |
| 196 | + 'Encryption' => 'keyid=p256dh;salt='.$encrypted['salt'], |
| 197 | + 'Content-Encoding' => 'aesgcm128', |
| 198 | + ); |
| 199 | + |
| 200 | + $content = $encrypted['cipherText']; |
| 201 | + } else { |
| 202 | + $headers = array( |
| 203 | + 'Content-Length' => 0, |
| 204 | + ); |
| 205 | + |
| 206 | + $content = ''; |
| 207 | + } |
| 208 | + |
| 209 | + if (isset($this->TTL)) { |
| 210 | + $headers['TTL'] = $this->TTL; |
| 211 | + } |
| 212 | + |
143 | 213 | $responses[] = $this->sendRequest($endpoint, $headers, $content);
|
144 | 214 | }
|
145 | 215 |
|
|
0 commit comments