1414use Base64Url \Base64Url ;
1515use Jose \Factory \JWKFactory ;
1616use Jose \Factory \JWSFactory ;
17+ use Mdanter \Ecc \Crypto \Key \PrivateKeyInterface ;
1718use Mdanter \Ecc \EccFactory ;
1819use Mdanter \Ecc \Serializer \Point \UncompressedPointSerializer ;
1920use Mdanter \Ecc \Serializer \PrivateKey \DerPrivateKeySerializer ;
2021use Mdanter \Ecc \Serializer \PrivateKey \PemPrivateKeySerializer ;
2122
2223class VAPID
2324{
25+ const PUBLIC_KEY_LENGTH = 65 ;
26+ const PRIVATE_KEY_LENGTH = 32 ;
27+
2428 /**
2529 * @param array $vapid
2630 *
@@ -54,11 +58,9 @@ public static function validate(array $vapid)
5458 $ posStartKey += 30 ; // length of '-----BEGIN EC PRIVATE KEY-----'
5559
5660 $ pemSerializer = new PemPrivateKeySerializer (new DerPrivateKeySerializer ());
57- $ keys = $ pemSerializer ->parse (substr ($ pem , $ posStartKey , $ posEndKey - $ posStartKey ));
58-
59- $ pointSerializer = new UncompressedPointSerializer (EccFactory::getAdapter ());
60- $ vapid ['publicKey ' ] = base64_encode (hex2bin ($ pointSerializer ->serialize ($ keys ->getPublicKey ()->getPoint ())));
61- $ vapid ['privateKey ' ] = base64_encode (hex2bin (gmp_strval ($ keys ->getSecret (), 16 )));
61+ $ keys = self ::getUncompressedKeys ($ pemSerializer ->parse (substr ($ pem , $ posStartKey , $ posEndKey - $ posStartKey )));
62+ $ vapid ['publicKey ' ] = $ keys ['publicKey ' ];
63+ $ vapid ['privateKey ' ] = $ keys ['privateKey ' ];
6264 }
6365
6466 if (!array_key_exists ('publicKey ' , $ vapid )) {
@@ -67,7 +69,7 @@ public static function validate(array $vapid)
6769
6870 $ publicKey = Base64Url::decode ($ vapid ['publicKey ' ]);
6971
70- if (Utils::safeStrlen ($ publicKey ) !== 65 ) {
72+ if (Utils::safeStrlen ($ publicKey ) !== self :: PUBLIC_KEY_LENGTH ) {
7173 throw new \ErrorException ('[VAPID] Public key should be 65 bytes long when decoded. ' );
7274 }
7375
@@ -77,7 +79,7 @@ public static function validate(array $vapid)
7779
7880 $ privateKey = Base64Url::decode ($ vapid ['privateKey ' ]);
7981
80- if (Utils::safeStrlen ($ privateKey ) !== 32 ) {
82+ if (Utils::safeStrlen ($ privateKey ) !== self :: PRIVATE_KEY_LENGTH ) {
8183 throw new \ErrorException ('[VAPID] Private key should be 32 bytes long when decoded. ' );
8284 }
8385
@@ -127,8 +129,8 @@ public static function getVapidHeaders($audience, $subject, $publicKey, $private
127129 $ jws = JWSFactory::createJWSToCompactJSON ($ jwtPayload , $ jwk , $ header );
128130
129131 return array (
130- 'Authorization ' => 'WebPush ' .$ jws ,
131- 'Crypto-Key ' => 'p256ecdsa= ' .Base64Url::encode ($ publicKey ),
132+ 'Authorization ' => 'WebPush ' .$ jws ,
133+ 'Crypto-Key ' => 'p256ecdsa= ' .Base64Url::encode ($ publicKey ),
132134 );
133135 }
134136
@@ -142,9 +144,15 @@ public static function getVapidHeaders($audience, $subject, $publicKey, $private
142144 public static function createVapidKeys ()
143145 {
144146 $ privateKeyObject = EccFactory::getNistCurves ()->generator256 ()->createPrivateKey ();
147+
148+ return self ::getUncompressedKeys ($ privateKeyObject );
149+ }
150+
151+ private static function getUncompressedKeys (PrivateKeyInterface $ privateKeyObject )
152+ {
145153 $ pointSerializer = new UncompressedPointSerializer (EccFactory::getAdapter ());
146154 $ vapid ['publicKey ' ] = base64_encode (hex2bin ($ pointSerializer ->serialize ($ privateKeyObject ->getPublicKey ()->getPoint ())));
147- $ vapid ['privateKey ' ] = base64_encode (hex2bin (gmp_strval ($ privateKeyObject ->getSecret (), 16 )));
155+ $ vapid ['privateKey ' ] = base64_encode (hex2bin (str_pad ( gmp_strval ($ privateKeyObject ->getSecret (), 16 ), 2 * self :: PRIVATE_KEY_LENGTH , ' 0 ' , STR_PAD_LEFT )));
148156
149157 return $ vapid ;
150158 }
0 commit comments