1- <?php
2-
3- declare (strict_types=1 );
1+ <?php declare (strict_types=1 );
42
53/*
64 * This file is part of the WebPush library.
@@ -27,35 +25,35 @@ class Encryption
2725 * @return string padded payload (plaintext)
2826 * @throws \ErrorException
2927 */
30- public static function padPayload (string $ payload , int $ maxLengthToPad , string $ contentEncoding ): string
28+ public static function padPayload (string $ payload , int $ maxLengthToPad , ContentEncoding $ contentEncoding ): string
3129 {
3230 $ payloadLen = Utils::safeStrlen ($ payload );
3331 $ padLen = $ maxLengthToPad ? $ maxLengthToPad - $ payloadLen : 0 ;
3432
35- if ($ contentEncoding === " aesgcm " ) {
33+ if ($ contentEncoding === ContentEncoding:: aesgcm) {
3634 return pack ('n* ' , $ padLen ).str_pad ($ payload , $ padLen + $ payloadLen , chr (0 ), STR_PAD_LEFT );
3735 }
38- if ($ contentEncoding === " aes128gcm " ) {
36+ if ($ contentEncoding === ContentEncoding:: aes128gcm) {
3937 return str_pad ($ payload .chr (2 ), $ padLen + $ payloadLen , chr (0 ), STR_PAD_RIGHT );
4038 }
4139
42- throw new \ErrorException ("This content encoding is not supported " );
40+ // @phpstan-ignore deadCode.unreachable
41+ throw new \ErrorException ("This content encoding is not implemented. " );
4342 }
4443
4544 /**
4645 * @param string $payload With padding
4746 * @param string $userPublicKey Base 64 encoded (MIME or URL-safe)
4847 * @param string $userAuthToken Base 64 encoded (MIME or URL-safe)
4948 *
50- * @throws \ErrorException Thrown on php 8.1
5149 * @throws \Random\RandomException Thrown on php 8.2 and higher
5250 */
5351 public static function encrypt (
5452 string $ payload ,
5553 string $ userPublicKey ,
5654 #[\SensitiveParameter]
5755 string $ userAuthToken ,
58- string $ contentEncoding ,
56+ ContentEncoding $ contentEncoding ,
5957 ): array {
6058 return self ::deterministicEncrypt (
6159 $ payload ,
@@ -68,14 +66,14 @@ public static function encrypt(
6866 }
6967
7068 /**
71- * @throws \RuntimeException
69+ * @throws \RuntimeException|\ErrorException
7270 */
7371 public static function deterministicEncrypt (
7472 string $ payload ,
7573 string $ userPublicKey ,
7674 #[\SensitiveParameter]
7775 string $ userAuthToken ,
78- string $ contentEncoding ,
76+ ContentEncoding $ contentEncoding ,
7977 array $ localKeyObject ,
8078 string $ salt
8179 ): array {
@@ -125,7 +123,7 @@ public static function deterministicEncrypt(
125123 $ context = self ::createContext ($ userPublicKey , $ localPublicKey , $ contentEncoding );
126124
127125 // derive the Content Encryption Key
128- $ contentEncryptionKeyInfo = self ::createInfo ($ contentEncoding , $ context , $ contentEncoding );
126+ $ contentEncryptionKeyInfo = self ::createInfo ($ contentEncoding-> value , $ context , $ contentEncoding );
129127 $ contentEncryptionKey = self ::hkdf ($ salt , $ ikm , $ contentEncryptionKeyInfo , 16 );
130128
131129 // section 3.3, derive the nonce
@@ -145,16 +143,20 @@ public static function deterministicEncrypt(
145143 ];
146144 }
147145
148- public static function getContentCodingHeader (string $ salt , string $ localPublicKey , string $ contentEncoding ): string
146+ public static function getContentCodingHeader (string $ salt , string $ localPublicKey , ContentEncoding $ contentEncoding ): string
149147 {
150- if ($ contentEncoding === "aes128gcm " ) {
148+ if ($ contentEncoding === ContentEncoding::aesgcm) {
149+ return "" ;
150+ }
151+ if ($ contentEncoding === ContentEncoding::aes128gcm) {
151152 return $ salt
152153 .pack ('N* ' , 4096 )
153154 .pack ('C* ' , Utils::safeStrlen ($ localPublicKey ))
154155 .$ localPublicKey ;
155156 }
156157
157- return "" ;
158+ // @phpstan-ignore deadCode.unreachable
159+ throw new \ValueError ("This content encoding is not implemented. " );
158160 }
159161
160162 /**
@@ -195,19 +197,19 @@ private static function hkdf(string $salt, string $ikm, string $info, int $lengt
195197 *
196198 * @throws \ErrorException
197199 */
198- private static function createContext (string $ clientPublicKey , string $ serverPublicKey , string $ contentEncoding ): ?string
200+ private static function createContext (string $ clientPublicKey , string $ serverPublicKey , ContentEncoding $ contentEncoding ): ?string
199201 {
200- if ($ contentEncoding === " aes128gcm " ) {
202+ if ($ contentEncoding === ContentEncoding:: aes128gcm) {
201203 return null ;
202204 }
203205
204206 if (Utils::safeStrlen ($ clientPublicKey ) !== 65 ) {
205- throw new \ErrorException ('Invalid client public key length ' );
207+ throw new \ErrorException ('Invalid client public key length. ' );
206208 }
207209
208210 // This one should never happen, because it's our code that generates the key
209211 if (Utils::safeStrlen ($ serverPublicKey ) !== 65 ) {
210- throw new \ErrorException ('Invalid server public key length ' );
212+ throw new \ErrorException ('Invalid server public key length. ' );
211213 }
212214
213215 $ len = chr (0 ).'A ' ; // 65 as Uint16BE
@@ -225,25 +227,26 @@ private static function createContext(string $clientPublicKey, string $serverPub
225227 *
226228 * @throws \ErrorException
227229 */
228- private static function createInfo (string $ type , ?string $ context , string $ contentEncoding ): string
230+ private static function createInfo (string $ type , ?string $ context , ContentEncoding $ contentEncoding ): string
229231 {
230- if ($ contentEncoding === " aesgcm " ) {
232+ if ($ contentEncoding === ContentEncoding:: aesgcm) {
231233 if (!$ context ) {
232- throw new \ErrorException ('Context must exist ' );
234+ throw new \ValueError ('Context must exist. ' );
233235 }
234236
235237 if (Utils::safeStrlen ($ context ) !== 135 ) {
236- throw new \ErrorException ('Context argument has invalid size ' );
238+ throw new \ValueError ('Context argument has invalid size. ' );
237239 }
238240
239241 return 'Content-Encoding: ' .$ type .chr (0 ).'P-256 ' .$ context ;
240242 }
241243
242- if ($ contentEncoding === " aes128gcm " ) {
244+ if ($ contentEncoding === ContentEncoding:: aes128gcm) {
243245 return 'Content-Encoding: ' .$ type .chr (0 );
244246 }
245247
246- throw new \ErrorException ('This content encoding is not supported. ' );
248+ // @phpstan-ignore deadCode.unreachable
249+ throw new \ErrorException ('This content encoding is not implemented. ' );
247250 }
248251
249252 private static function createLocalKeyObject (): array
@@ -275,17 +278,17 @@ private static function createLocalKeyObject(): array
275278 /**
276279 * @throws \ValueError
277280 */
278- private static function getIKM (string $ userAuthToken , string $ userPublicKey , string $ localPublicKey , string $ sharedSecret , string $ contentEncoding ): string
281+ private static function getIKM (string $ userAuthToken , string $ userPublicKey , string $ localPublicKey , string $ sharedSecret , ContentEncoding $ contentEncoding ): string
279282 {
280283 if (empty ($ userAuthToken )) {
281284 return $ sharedSecret ;
282285 }
283- if ($ contentEncoding === " aesgcm " ) {
286+ if ($ contentEncoding === ContentEncoding:: aesgcm) {
284287 $ info = 'Content-Encoding: auth ' .chr (0 );
285- } elseif ($ contentEncoding === " aes128gcm " ) {
288+ } elseif ($ contentEncoding === ContentEncoding:: aes128gcm) {
286289 $ info = "WebPush: info " .chr (0 ).$ userPublicKey .$ localPublicKey ;
287290 } else {
288- throw new \ValueError ("This content encoding is not supported . " );
291+ throw new \ValueError ("This content encoding is not implemented . " );
289292 }
290293
291294 return self ::hkdf ($ userAuthToken , $ sharedSecret , $ info , 32 );
0 commit comments