Skip to content

Commit d914e9b

Browse files
committed
fix a bug when users used a PEM file or created the VAPID keys using PHP, close #56
1 parent 9f0ddc9 commit d914e9b

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

src/VAPID.php

+18-10
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
use Base64Url\Base64Url;
1515
use Jose\Factory\JWKFactory;
1616
use Jose\Factory\JWSFactory;
17+
use Mdanter\Ecc\Crypto\Key\PrivateKeyInterface;
1718
use Mdanter\Ecc\EccFactory;
1819
use Mdanter\Ecc\Serializer\Point\UncompressedPointSerializer;
1920
use Mdanter\Ecc\Serializer\PrivateKey\DerPrivateKeySerializer;
2021
use Mdanter\Ecc\Serializer\PrivateKey\PemPrivateKeySerializer;
2122

2223
class 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

Comments
 (0)