/** * {@inheritdoc} */ public function getAgreementKey($encryption_key_length, $algorithm, JWKInterface $recipient_key, array $complete_header = [], array &$additional_header_values = []) { if ($recipient_key->has('d')) { $this->checkKey($recipient_key, true); $private_key = $recipient_key; $public_key = $this->getPublicKey($complete_header); } else { $this->checkKey($recipient_key, false); $public_key = $recipient_key; switch ($public_key->get('crv')) { case 'P-256': case 'P-384': case 'P-521': $private_key = JWKFactory::createECKey(['crv' => $public_key->get('crv')]); break; case 'X25519': $private_key = JWKFactory::createOKPKey(['crv' => 'X25519']); break; default: throw new \InvalidArgumentException(sprintf('The curve "%s" is not supported', $public_key->get('crv'))); } $epk = $private_key->toPublic()->getAll(); $additional_header_values = array_merge($additional_header_values, ['epk' => $epk]); } Assertion::eq($private_key->get('crv'), $public_key->get('crv'), 'Curves are different'); $agreed_key = $this->calculateAgreementKey($private_key, $public_key); $apu = array_key_exists('apu', $complete_header) ? $complete_header['apu'] : ''; $apv = array_key_exists('apv', $complete_header) ? $complete_header['apv'] : ''; return ConcatKDF::generate($agreed_key, $algorithm, $encryption_key_length, $apu, $apv); }
/** * @return \Jose\Object\JWKInterface */ protected function createJWK() { $data = JWKFactory::createKey($this->parameters)->getAll(); $data['kid'] = Base64Url::encode(random_bytes(64)); return JWKFactory::createFromValues($data); }
/** * This method takes the required VAPID parameters and returns the required * header to be added to a Web Push Protocol Request. * * @param string $audience This must be the origin of the push service * @param string $subject This should be a URL or a 'mailto:' email address * @param string $publicKey The decoded VAPID public key * @param string $privateKey The decoded VAPID private key * @param int $expiration The expiration of the VAPID JWT. (UNIX timestamp) * * @return array Returns an array with the 'Authorization' and 'Crypto-Key' values to be used as headers */ public static function getVapidHeaders($audience, $subject, $publicKey, $privateKey, $expiration = null) { $expirationLimit = time() + 43200; // equal margin of error between 0 and 24h if (!isset($expiration) || $expiration > $expirationLimit) { $expiration = $expirationLimit; } $header = array('typ' => 'JWT', 'alg' => 'ES256'); $jwtPayload = json_encode(array('aud' => $audience, 'exp' => $expiration, 'sub' => $subject), JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK); $generator = EccFactory::getNistCurves()->generator256(); $privateKeyObject = $generator->getPrivateKeyFrom(gmp_init(bin2hex($privateKey), 16)); $pemSerialize = new PemPrivateKeySerializer(new DerPrivateKeySerializer()); $pem = $pemSerialize->serialize($privateKeyObject); $jwk = JWKFactory::createFromKey($pem, null); $jws = JWSFactory::createJWSToCompactJSON($jwtPayload, $jwk, $header); return array('Authorization' => 'WebPush ' . $jws, 'Crypto-Key' => 'p256ecdsa=' . Base64Url::encode($publicKey)); }
/** * Build encryption key * * @param $secret * @param $algo * @return JWKInterface|\Jose\Object\JWKSetInterface */ private function buildEncryptionKey($secret, $algo) { return JWKFactory::createFromValues(['kty' => 'oct', 'k' => $secret, 'alg' => $algo]); }
/** * {@inheritdoc} */ public function checkClientConfiguration(array $client_configuration, ClientInterface $client) { if ('client_secret_jwt' === $client_configuration['token_endpoint_auth_method']) { $client->set('client_secret', $this->createClientSecret()); $client->set('client_secret_expires_at', 0 === $this->secret_lifetime ? 0 : time() + $this->secret_lifetime); } elseif ('private_key_jwt' === $client_configuration['token_endpoint_auth_method']) { Assertion::true(array_key_exists('jwks', $client_configuration) xor array_key_exists('jwks_uri', $client_configuration), 'The parameter "jwks" or "jwks_uri" must be set.'); if (array_key_exists('jwks', $client_configuration)) { $jwks = new JWKSet($client_configuration['jwks']); Assertion::isInstanceOf($jwks, JWKSetInterface::class, 'The parameter "jwks" must be a valid JWKSet object.'); $client->set('jwks', $client_configuration['jwks']); } else { $jwks = JWKFactory::createFromJKU($client_configuration['jwks_uri']); Assertion::isInstanceOf($jwks, JWKSetInterface::class, 'The parameter "jwks_uri" must be a valid uri that provide a valid JWKSet.'); $client->set('jwks_uri', $client_configuration['jwks_uri']); } } else { throw new \InvalidArgumentException('Unsupported token endpoint authentication method.'); } }
/** * @return null|\Jose\Object\JWKSetInterface */ public function getPublicKeySet() { Assertion::true($this->hasPublicKeySet(), 'The client has no public key set'); if ($this->hasJwks()) { return new JWKSet($this->getJwks()); } if ($this->hasJwksUri()) { return JWKFactory::createFromJKU($this->getJwksUri()); } if ($this->hasClientSecret()) { $jwk_set = new JWKSet(); $jwk_set->addKey(new JWK(['kty' => 'oct', 'use' => 'sig', 'k' => $this->getClientSecret()])); return $jwk_set; } }