14
14
use Base64Url \Base64Url ;
15
15
use Jose \Factory \JWKFactory ;
16
16
use Jose \Factory \JWSFactory ;
17
+ use Mdanter \Ecc \Crypto \Key \PrivateKeyInterface ;
17
18
use Mdanter \Ecc \EccFactory ;
18
19
use Mdanter \Ecc \Serializer \Point \UncompressedPointSerializer ;
19
20
use Mdanter \Ecc \Serializer \PrivateKey \DerPrivateKeySerializer ;
20
21
use Mdanter \Ecc \Serializer \PrivateKey \PemPrivateKeySerializer ;
21
22
22
23
class VAPID
23
24
{
25
+ const PUBLIC_KEY_LENGTH = 65 ;
26
+ const PRIVATE_KEY_LENGTH = 32 ;
27
+
24
28
/**
25
29
* @param array $vapid
26
30
*
@@ -54,11 +58,9 @@ public static function validate(array $vapid)
54
58
$ posStartKey += 30 ; // length of '-----BEGIN EC PRIVATE KEY-----'
55
59
56
60
$ 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 ' ];
62
64
}
63
65
64
66
if (!array_key_exists ('publicKey ' , $ vapid )) {
@@ -67,7 +69,7 @@ public static function validate(array $vapid)
67
69
68
70
$ publicKey = Base64Url::decode ($ vapid ['publicKey ' ]);
69
71
70
- if (Utils::safeStrlen ($ publicKey ) !== 65 ) {
72
+ if (Utils::safeStrlen ($ publicKey ) !== self :: PUBLIC_KEY_LENGTH ) {
71
73
throw new \ErrorException ('[VAPID] Public key should be 65 bytes long when decoded. ' );
72
74
}
73
75
@@ -77,7 +79,7 @@ public static function validate(array $vapid)
77
79
78
80
$ privateKey = Base64Url::decode ($ vapid ['privateKey ' ]);
79
81
80
- if (Utils::safeStrlen ($ privateKey ) !== 32 ) {
82
+ if (Utils::safeStrlen ($ privateKey ) !== self :: PRIVATE_KEY_LENGTH ) {
81
83
throw new \ErrorException ('[VAPID] Private key should be 32 bytes long when decoded. ' );
82
84
}
83
85
@@ -127,8 +129,8 @@ public static function getVapidHeaders($audience, $subject, $publicKey, $private
127
129
$ jws = JWSFactory::createJWSToCompactJSON ($ jwtPayload , $ jwk , $ header );
128
130
129
131
return array (
130
- 'Authorization ' => 'WebPush ' .$ jws ,
131
- 'Crypto-Key ' => 'p256ecdsa= ' .Base64Url::encode ($ publicKey ),
132
+ 'Authorization ' => 'WebPush ' .$ jws ,
133
+ 'Crypto-Key ' => 'p256ecdsa= ' .Base64Url::encode ($ publicKey ),
132
134
);
133
135
}
134
136
@@ -142,9 +144,15 @@ public static function getVapidHeaders($audience, $subject, $publicKey, $private
142
144
public static function createVapidKeys ()
143
145
{
144
146
$ privateKeyObject = EccFactory::getNistCurves ()->generator256 ()->createPrivateKey ();
147
+
148
+ return self ::getUncompressedKeys ($ privateKeyObject );
149
+ }
150
+
151
+ private static function getUncompressedKeys (PrivateKeyInterface $ privateKeyObject )
152
+ {
145
153
$ pointSerializer = new UncompressedPointSerializer (EccFactory::getAdapter ());
146
154
$ 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 )));
148
156
149
157
return $ vapid ;
150
158
}
0 commit comments