misuzu/src/JWT/ArrayJWKSet.php
2025-02-26 22:03:13 +00:00

65 lines
2.2 KiB
PHP

<?php
namespace Misuzu\JWT;
use RuntimeException;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Crypt\Common\{AsymmetricKey,PrivateKey,PublicKey};
class ArrayJWKSet implements JWKSet {
/** @param array<string, JWK> $keys */
public function __construct(public private(set) array $keys) {}
public function getKey(?string $keyId = null, ?string $algo = null): JWK {
if($keyId === null) {
if($algo === null)
return $this->keys[array_key_first($this->keys)];
foreach($this->keys as $key)
if($key->algo !== null && hash_equals($key->algo, $algo))
return $key;
throw new RuntimeException('could not find a key that matched the requested algorithm');
}
if(!array_key_exists($keyId, $this->keys))
throw new RuntimeException('could not find a key with that id');
$key = $this->keys[$keyId];
if($algo !== null && $key->algo !== null && !hash_equals($key->algo, $algo))
throw new RuntimeException('requested algorithm does not match');
return $key;
}
/**
* @param string|mixed[]|object $json
*/
public static function decodeJson(string|array|object $json): ArrayJWKSet {
if(is_object($json))
$json = (array)$json;
elseif(is_string($json))
$json = json_decode($json);
if(is_array($json))
$json = (object)$json;
if(!property_exists($json, 'keys') || !is_array($json->keys) || !array_is_list($json->keys))
return new ArrayJWKSet([]);
$keys = [];
foreach($json->keys as $keyInfo) {
$key = PublicKeyLoader::load(json_encode($keyInfo));
if($key instanceof AsymmetricKey && ($key instanceof PrivateKey || $key instanceof PublicKey))
$key = new SecLibJWK($key, property_exists($keyInfo, 'alg') && is_string($keyInfo->alg) ? $keyInfo->alg : null);
if(property_exists($keyInfo, 'kid') && is_string($keyInfo->kid))
$keys[$keyInfo->kid] = $key;
else
$keys[] = $key;
}
return new ArrayJWKSet($keys);
}
}