diff options
Diffstat (limited to 'vendor/web-token/jwt-core/JWKSet.php')
-rw-r--r-- | vendor/web-token/jwt-core/JWKSet.php | 642 |
1 files changed, 321 insertions, 321 deletions
diff --git a/vendor/web-token/jwt-core/JWKSet.php b/vendor/web-token/jwt-core/JWKSet.php index efcd417..149f484 100644 --- a/vendor/web-token/jwt-core/JWKSet.php +++ b/vendor/web-token/jwt-core/JWKSet.php @@ -1,321 +1,321 @@ -<?php - -declare(strict_types=1); - -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2018 Spomky-Labs - * - * This software may be modified and distributed under the terms - * of the MIT license. See the LICENSE file for details. - */ - -namespace Jose\Component\Core; - -use InvalidArgumentException; - -class JWKSet implements \Countable, \IteratorAggregate, \JsonSerializable -{ - /** - * @var array - */ - private $keys = []; - - /** - * JWKSet constructor. - * - * @param JWK[] $keys - */ - public function __construct(array $keys) - { - foreach ($keys as $k => $key) { - if (!$key instanceof JWK) { - throw new InvalidArgumentException('Invalid list. Should only contains JWK objects'); - } - if ($key->has('kid')) { - unset($keys[$k]); - $this->keys[$key->get('kid')] = $key; - } else { - $this->keys[] = $key; - } - } - } - - /** - * Creates a JWKSet object using the given values. - * - * @return JWKSet - */ - public static function createFromKeyData(array $data): self - { - if (!isset($data['keys'])) { - throw new InvalidArgumentException('Invalid data.'); - } - if (!\is_array($data['keys'])) { - throw new InvalidArgumentException('Invalid data.'); - } - $jwkset = new self([]); - foreach ($data['keys'] as $key) { - $jwk = new JWK($key); - if ($jwk->has('kid')) { - $jwkset->keys[$jwk->get('kid')] = $jwk; - } else { - $jwkset->keys[] = $jwk; - } - } - - return $jwkset; - } - - /** - * Creates a JWKSet object using the given JWK objects. - * - * @deprecated Will be removed in v2.0. Please use constructor instead. - * - * @param JWK[] $keys - * - * @return JWKSet - */ - public static function createFromKeys(array $keys): self - { - return new self($keys); - } - - /** - * Creates a JWKSet object using the given Json string. - * - * @return JWKSet - */ - public static function createFromJson(string $json): self - { - $data = \json_decode($json, true); - if (!\is_array($data)) { - throw new InvalidArgumentException('Invalid argument.'); - } - - return self::createFromKeyData($data); - } - - /** - * Returns an array of keys stored in the key set. - * - * @return JWK[] - */ - public function all(): array - { - return $this->keys; - } - - /** - * Add key to store in the key set. - * This method is immutable and will return a new object. - * - * @return JWKSet - */ - public function with(JWK $jwk): self - { - $clone = clone $this; - - if ($jwk->has('kid')) { - $clone->keys[$jwk->get('kid')] = $jwk; - } else { - $clone->keys[] = $jwk; - } - - return $clone; - } - - /** - * Remove key from the key set. - * This method is immutable and will return a new object. - * - * @param int|string $key Key to remove from the key set - * - * @return JWKSet - */ - public function without($key): self - { - if (!$this->has($key)) { - return $this; - } - - $clone = clone $this; - unset($clone->keys[$key]); - - return $clone; - } - - /** - * Returns true if the key set contains a key with the given index. - * - * @param int|string $index - */ - public function has($index): bool - { - return \array_key_exists($index, $this->keys); - } - - /** - * Returns the key with the given index. Throws an exception if the index is not present in the key store. - * - * @param int|string $index - */ - public function get($index): JWK - { - if (!$this->has($index)) { - throw new InvalidArgumentException('Undefined index.'); - } - - return $this->keys[$index]; - } - - /** - * Returns the values to be serialized. - */ - public function jsonSerialize(): array - { - return ['keys' => \array_values($this->keys)]; - } - - /** - * Returns the number of keys in the key set. - * - * @param int $mode - */ - public function count($mode = COUNT_NORMAL): int - { - return \count($this->keys, $mode); - } - - /** - * Try to find a key that fits on the selected requirements. - * Returns null if not found. - * - * @param string $type Must be 'sig' (signature) or 'enc' (encryption) - * @param Algorithm|null $algorithm Specifies the algorithm to be used - * @param array $restrictions More restrictions such as 'kid' or 'kty' - */ - public function selectKey(string $type, ?Algorithm $algorithm = null, array $restrictions = []): ?JWK - { - if (!\in_array($type, ['enc', 'sig'], true)) { - throw new InvalidArgumentException('Allowed key types are "sig" or "enc".'); - } - - $result = []; - foreach ($this->keys as $key) { - $ind = 0; - - $can_use = $this->canKeyBeUsedFor($type, $key); - if (false === $can_use) { - continue; - } - $ind += $can_use; - - $alg = $this->canKeyBeUsedWithAlgorithm($algorithm, $key); - if (false === $alg) { - continue; - } - $ind += $alg; - - if (false === $this->doesKeySatisfyRestrictions($restrictions, $key)) { - continue; - } - - $result[] = ['key' => $key, 'ind' => $ind]; - } - - if (empty($result)) { - return null; - } - - \usort($result, [$this, 'sortKeys']); - - return $result[0]['key']; - } - - /** - * @return bool|int - */ - private function canKeyBeUsedFor(string $type, JWK $key) - { - if ($key->has('use')) { - return $type === $key->get('use') ? 1 : false; - } - if ($key->has('key_ops')) { - return $type === self::convertKeyOpsToKeyUse($key->get('use')) ? 1 : false; - } - - return 0; - } - - /** - * @return bool|int - */ - private function canKeyBeUsedWithAlgorithm(?Algorithm $algorithm, JWK $key) - { - if (null === $algorithm) { - return 0; - } - if (!\in_array($key->get('kty'), $algorithm->allowedKeyTypes(), true)) { - return false; - } - if ($key->has('alg')) { - return $algorithm->name() === $key->get('alg') ? 2 : false; - } - - return 1; - } - - private function doesKeySatisfyRestrictions(array $restrictions, JWK $key): bool - { - foreach ($restrictions as $k => $v) { - if (!$key->has($k) || $v !== $key->get($k)) { - return false; - } - } - - return true; - } - - private static function convertKeyOpsToKeyUse(string $key_ops): string - { - switch ($key_ops) { - case 'verify': - case 'sign': - return 'sig'; - case 'encrypt': - case 'decrypt': - case 'wrapKey': - case 'unwrapKey': - return 'enc'; - default: - throw new InvalidArgumentException(\sprintf('Unsupported key operation value "%s"', $key_ops)); - } - } - - /** - * Internal method only. Should not be used. - * - * @internal - * @internal - */ - public static function sortKeys(array $a, array $b): int - { - if ($a['ind'] === $b['ind']) { - return 0; - } - - return ($a['ind'] > $b['ind']) ? -1 : 1; - } - - /** - * Internal method only. Should not be used. - * - * @internal - */ - public function getIterator() - { - return new \ArrayIterator($this->keys); - } -} +<?php
+
+declare(strict_types=1);
+
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2018 Spomky-Labs
+ *
+ * This software may be modified and distributed under the terms
+ * of the MIT license. See the LICENSE file for details.
+ */
+
+namespace Jose\Component\Core;
+
+use InvalidArgumentException;
+
+class JWKSet implements \Countable, \IteratorAggregate, \JsonSerializable
+{
+ /**
+ * @var array
+ */
+ private $keys = [];
+
+ /**
+ * JWKSet constructor.
+ *
+ * @param JWK[] $keys
+ */
+ public function __construct(array $keys)
+ {
+ foreach ($keys as $k => $key) {
+ if (!$key instanceof JWK) {
+ throw new InvalidArgumentException('Invalid list. Should only contains JWK objects');
+ }
+ if ($key->has('kid')) {
+ unset($keys[$k]);
+ $this->keys[$key->get('kid')] = $key;
+ } else {
+ $this->keys[] = $key;
+ }
+ }
+ }
+
+ /**
+ * Creates a JWKSet object using the given values.
+ *
+ * @return JWKSet
+ */
+ public static function createFromKeyData(array $data): self
+ {
+ if (!isset($data['keys'])) {
+ throw new InvalidArgumentException('Invalid data.');
+ }
+ if (!\is_array($data['keys'])) {
+ throw new InvalidArgumentException('Invalid data.');
+ }
+ $jwkset = new self([]);
+ foreach ($data['keys'] as $key) {
+ $jwk = new JWK($key);
+ if ($jwk->has('kid')) {
+ $jwkset->keys[$jwk->get('kid')] = $jwk;
+ } else {
+ $jwkset->keys[] = $jwk;
+ }
+ }
+
+ return $jwkset;
+ }
+
+ /**
+ * Creates a JWKSet object using the given JWK objects.
+ *
+ * @deprecated Will be removed in v2.0. Please use constructor instead.
+ *
+ * @param JWK[] $keys
+ *
+ * @return JWKSet
+ */
+ public static function createFromKeys(array $keys): self
+ {
+ return new self($keys);
+ }
+
+ /**
+ * Creates a JWKSet object using the given Json string.
+ *
+ * @return JWKSet
+ */
+ public static function createFromJson(string $json): self
+ {
+ $data = \json_decode($json, true);
+ if (!\is_array($data)) {
+ throw new InvalidArgumentException('Invalid argument.');
+ }
+
+ return self::createFromKeyData($data);
+ }
+
+ /**
+ * Returns an array of keys stored in the key set.
+ *
+ * @return JWK[]
+ */
+ public function all(): array
+ {
+ return $this->keys;
+ }
+
+ /**
+ * Add key to store in the key set.
+ * This method is immutable and will return a new object.
+ *
+ * @return JWKSet
+ */
+ public function with(JWK $jwk): self
+ {
+ $clone = clone $this;
+
+ if ($jwk->has('kid')) {
+ $clone->keys[$jwk->get('kid')] = $jwk;
+ } else {
+ $clone->keys[] = $jwk;
+ }
+
+ return $clone;
+ }
+
+ /**
+ * Remove key from the key set.
+ * This method is immutable and will return a new object.
+ *
+ * @param int|string $key Key to remove from the key set
+ *
+ * @return JWKSet
+ */
+ public function without($key): self
+ {
+ if (!$this->has($key)) {
+ return $this;
+ }
+
+ $clone = clone $this;
+ unset($clone->keys[$key]);
+
+ return $clone;
+ }
+
+ /**
+ * Returns true if the key set contains a key with the given index.
+ *
+ * @param int|string $index
+ */
+ public function has($index): bool
+ {
+ return \array_key_exists($index, $this->keys);
+ }
+
+ /**
+ * Returns the key with the given index. Throws an exception if the index is not present in the key store.
+ *
+ * @param int|string $index
+ */
+ public function get($index): JWK
+ {
+ if (!$this->has($index)) {
+ throw new InvalidArgumentException('Undefined index.');
+ }
+
+ return $this->keys[$index];
+ }
+
+ /**
+ * Returns the values to be serialized.
+ */
+ public function jsonSerialize(): array
+ {
+ return ['keys' => \array_values($this->keys)];
+ }
+
+ /**
+ * Returns the number of keys in the key set.
+ *
+ * @param int $mode
+ */
+ public function count($mode = COUNT_NORMAL): int
+ {
+ return \count($this->keys, $mode);
+ }
+
+ /**
+ * Try to find a key that fits on the selected requirements.
+ * Returns null if not found.
+ *
+ * @param string $type Must be 'sig' (signature) or 'enc' (encryption)
+ * @param Algorithm|null $algorithm Specifies the algorithm to be used
+ * @param array $restrictions More restrictions such as 'kid' or 'kty'
+ */
+ public function selectKey(string $type, ?Algorithm $algorithm = null, array $restrictions = []): ?JWK
+ {
+ if (!\in_array($type, ['enc', 'sig'], true)) {
+ throw new InvalidArgumentException('Allowed key types are "sig" or "enc".');
+ }
+
+ $result = [];
+ foreach ($this->keys as $key) {
+ $ind = 0;
+
+ $can_use = $this->canKeyBeUsedFor($type, $key);
+ if (false === $can_use) {
+ continue;
+ }
+ $ind += $can_use;
+
+ $alg = $this->canKeyBeUsedWithAlgorithm($algorithm, $key);
+ if (false === $alg) {
+ continue;
+ }
+ $ind += $alg;
+
+ if (false === $this->doesKeySatisfyRestrictions($restrictions, $key)) {
+ continue;
+ }
+
+ $result[] = ['key' => $key, 'ind' => $ind];
+ }
+
+ if (empty($result)) {
+ return null;
+ }
+
+ \usort($result, [$this, 'sortKeys']);
+
+ return $result[0]['key'];
+ }
+
+ /**
+ * @return bool|int
+ */
+ private function canKeyBeUsedFor(string $type, JWK $key)
+ {
+ if ($key->has('use')) {
+ return $type === $key->get('use') ? 1 : false;
+ }
+ if ($key->has('key_ops')) {
+ return $type === self::convertKeyOpsToKeyUse($key->get('use')) ? 1 : false;
+ }
+
+ return 0;
+ }
+
+ /**
+ * @return bool|int
+ */
+ private function canKeyBeUsedWithAlgorithm(?Algorithm $algorithm, JWK $key)
+ {
+ if (null === $algorithm) {
+ return 0;
+ }
+ if (!\in_array($key->get('kty'), $algorithm->allowedKeyTypes(), true)) {
+ return false;
+ }
+ if ($key->has('alg')) {
+ return $algorithm->name() === $key->get('alg') ? 2 : false;
+ }
+
+ return 1;
+ }
+
+ private function doesKeySatisfyRestrictions(array $restrictions, JWK $key): bool
+ {
+ foreach ($restrictions as $k => $v) {
+ if (!$key->has($k) || $v !== $key->get($k)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static function convertKeyOpsToKeyUse(string $key_ops): string
+ {
+ switch ($key_ops) {
+ case 'verify':
+ case 'sign':
+ return 'sig';
+ case 'encrypt':
+ case 'decrypt':
+ case 'wrapKey':
+ case 'unwrapKey':
+ return 'enc';
+ default:
+ throw new InvalidArgumentException(\sprintf('Unsupported key operation value "%s"', $key_ops));
+ }
+ }
+
+ /**
+ * Internal method only. Should not be used.
+ *
+ * @internal
+ * @internal
+ */
+ public static function sortKeys(array $a, array $b): int
+ {
+ if ($a['ind'] === $b['ind']) {
+ return 0;
+ }
+
+ return ($a['ind'] > $b['ind']) ? -1 : 1;
+ }
+
+ /**
+ * Internal method only. Should not be used.
+ *
+ * @internal
+ */
+ public function getIterator()
+ {
+ return new \ArrayIterator($this->keys);
+ }
+}
|