added predis and eseye back in.
This commit is contained in:
4
vendor/web-token/jwt-core/.github/CONTRIBUTING.md
vendored
Normal file
4
vendor/web-token/jwt-core/.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Contributing
|
||||
|
||||
This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY.
|
||||
Please do not submit any Pull Requests here. It will be automatically closed.
|
||||
1
vendor/web-token/jwt-core/.github/FUNDING.yml
vendored
Normal file
1
vendor/web-token/jwt-core/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
patreon: FlorentMorselli
|
||||
3
vendor/web-token/jwt-core/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
3
vendor/web-token/jwt-core/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Please do not submit any Pull Requests here. It will be automatically closed.
|
||||
|
||||
You should submit it here: https://github.com/web-token/jwt-framework/pulls
|
||||
29
vendor/web-token/jwt-core/Algorithm.php
vendored
Normal file
29
vendor/web-token/jwt-core/Algorithm.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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;
|
||||
|
||||
interface Algorithm
|
||||
{
|
||||
/**
|
||||
* Returns the name of the algorithm.
|
||||
*/
|
||||
public function name(): string;
|
||||
|
||||
/**
|
||||
* Returns the key types suitable for this algorithm (e.g. "oct", "RSA"...).
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function allowedKeyTypes(): array;
|
||||
}
|
||||
80
vendor/web-token/jwt-core/AlgorithmManager.php
vendored
Normal file
80
vendor/web-token/jwt-core/AlgorithmManager.php
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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 function array_key_exists;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class AlgorithmManager
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $algorithms = [];
|
||||
|
||||
/**
|
||||
* @param Algorithm[] $algorithms
|
||||
*/
|
||||
public function __construct(array $algorithms)
|
||||
{
|
||||
foreach ($algorithms as $algorithm) {
|
||||
$this->add($algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the algorithm is supported.
|
||||
*
|
||||
* @param string $algorithm The algorithm
|
||||
*/
|
||||
public function has(string $algorithm): bool
|
||||
{
|
||||
return array_key_exists($algorithm, $this->algorithms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of names of supported algorithms.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function list(): array
|
||||
{
|
||||
return array_keys($this->algorithms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the algorithm if supported, otherwise throw an exception.
|
||||
*
|
||||
* @param string $algorithm The algorithm
|
||||
*
|
||||
* @throws InvalidArgumentException if the algorithm is not supported
|
||||
*/
|
||||
public function get(string $algorithm): Algorithm
|
||||
{
|
||||
if (!$this->has($algorithm)) {
|
||||
throw new InvalidArgumentException(sprintf('The algorithm "%s" is not supported.', $algorithm));
|
||||
}
|
||||
|
||||
return $this->algorithms[$algorithm];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an algorithm to the manager.
|
||||
*/
|
||||
public function add(Algorithm $algorithm): void
|
||||
{
|
||||
$name = $algorithm->name();
|
||||
$this->algorithms[$name] = $algorithm;
|
||||
}
|
||||
}
|
||||
80
vendor/web-token/jwt-core/AlgorithmManagerFactory.php
vendored
Normal file
80
vendor/web-token/jwt-core/AlgorithmManagerFactory.php
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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;
|
||||
use function is_string;
|
||||
|
||||
class AlgorithmManagerFactory
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $algorithms = [];
|
||||
|
||||
/**
|
||||
* Adds an algorithm.
|
||||
*
|
||||
* Each algorithm is identified by an alias hence it is allowed to have the same algorithm twice (or more).
|
||||
* This can be helpful when an algorithm have several configuration options.
|
||||
*/
|
||||
public function add(string $alias, Algorithm $algorithm): void
|
||||
{
|
||||
$this->algorithms[$alias] = $algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of aliases.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function aliases(): array
|
||||
{
|
||||
return array_keys($this->algorithms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all algorithms supported by this factory.
|
||||
* This is an associative array. Keys are the aliases of the algorithms.
|
||||
*
|
||||
* @return Algorithm[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
return $this->algorithms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an algorithm manager using the given aliases.
|
||||
*
|
||||
* @param string[] $aliases
|
||||
*
|
||||
* @throws InvalidArgumentException if the alias is invalid or is not supported
|
||||
*/
|
||||
public function create(array $aliases): AlgorithmManager
|
||||
{
|
||||
$algorithms = [];
|
||||
foreach ($aliases as $alias) {
|
||||
if (!is_string($alias)) {
|
||||
throw new InvalidArgumentException('Invalid alias');
|
||||
}
|
||||
if (!isset($this->algorithms[$alias])) {
|
||||
throw new InvalidArgumentException(sprintf('The algorithm with the alias "%s" is not supported.', $alias));
|
||||
}
|
||||
$algorithms[] = $this->algorithms[$alias];
|
||||
}
|
||||
|
||||
return new AlgorithmManager($algorithms);
|
||||
}
|
||||
}
|
||||
143
vendor/web-token/jwt-core/JWK.php
vendored
Normal file
143
vendor/web-token/jwt-core/JWK.php
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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 function array_key_exists;
|
||||
use Base64Url\Base64Url;
|
||||
use function in_array;
|
||||
use InvalidArgumentException;
|
||||
use function is_array;
|
||||
use JsonSerializable;
|
||||
|
||||
class JWK implements JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $values = [];
|
||||
|
||||
/**
|
||||
* Creates a JWK object using the given values.
|
||||
* The member "kty" is mandatory. Other members are NOT checked.
|
||||
*
|
||||
* @throws InvalidArgumentException if the key parameter "kty" is missing
|
||||
*/
|
||||
public function __construct(array $values)
|
||||
{
|
||||
if (!isset($values['kty'])) {
|
||||
throw new InvalidArgumentException('The parameter "kty" is mandatory.');
|
||||
}
|
||||
$this->values = $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JWK object using the given Json string.
|
||||
*
|
||||
* @throws InvalidArgumentException if the data is not valid
|
||||
*
|
||||
* @return JWK
|
||||
*/
|
||||
public static function createFromJson(string $json): self
|
||||
{
|
||||
$data = json_decode($json, true);
|
||||
if (!is_array($data)) {
|
||||
throw new InvalidArgumentException('Invalid argument.');
|
||||
}
|
||||
|
||||
return new self($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values to be serialized.
|
||||
*/
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value with a specific key.
|
||||
*
|
||||
* @param string $key The key
|
||||
*
|
||||
* @throws InvalidArgumentException if the key does not exist
|
||||
*
|
||||
* @return null|mixed
|
||||
*/
|
||||
public function get(string $key)
|
||||
{
|
||||
if (!$this->has($key)) {
|
||||
throw new InvalidArgumentException(sprintf('The value identified by "%s" does not exist.', $key));
|
||||
}
|
||||
|
||||
return $this->values[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the JWK has the value identified by.
|
||||
*
|
||||
* @param string $key The key
|
||||
*/
|
||||
public function has(string $key): bool
|
||||
{
|
||||
return array_key_exists($key, $this->values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all values stored in the JWK object.
|
||||
*
|
||||
* @return array Values of the JWK object
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thumbprint of the key.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc7638
|
||||
*
|
||||
* @throws InvalidArgumentException if the hashing function is not supported
|
||||
*/
|
||||
public function thumbprint(string $hash_algorithm): string
|
||||
{
|
||||
if (!in_array($hash_algorithm, hash_algos(), true)) {
|
||||
throw new InvalidArgumentException(sprintf('The hash algorithm "%s" is not supported.', $hash_algorithm));
|
||||
}
|
||||
$values = array_intersect_key($this->values, array_flip(['kty', 'n', 'e', 'crv', 'x', 'y', 'k']));
|
||||
ksort($values);
|
||||
$input = json_encode($values, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
return Base64Url::encode(hash($hash_algorithm, $input, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated public key.
|
||||
* This method has no effect for:
|
||||
* - public keys
|
||||
* - shared keys
|
||||
* - unknown keys.
|
||||
*
|
||||
* Known keys are "oct", "RSA", "EC" and "OKP".
|
||||
*
|
||||
* @return JWK
|
||||
*/
|
||||
public function toPublic(): self
|
||||
{
|
||||
$values = array_diff_key($this->values, array_flip(['p', 'd', 'q', 'dp', 'dq', 'qi']));
|
||||
|
||||
return new self($values);
|
||||
}
|
||||
}
|
||||
338
vendor/web-token/jwt-core/JWKSet.php
vendored
Normal file
338
vendor/web-token/jwt-core/JWKSet.php
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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 function array_key_exists;
|
||||
use ArrayIterator;
|
||||
use function count;
|
||||
use Countable;
|
||||
use function in_array;
|
||||
use InvalidArgumentException;
|
||||
use function is_array;
|
||||
use IteratorAggregate;
|
||||
use JsonSerializable;
|
||||
use Traversable;
|
||||
|
||||
class JWKSet implements Countable, IteratorAggregate, JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $keys = [];
|
||||
|
||||
/**
|
||||
* @param JWK[] $keys
|
||||
*
|
||||
* @throws InvalidArgumentException if the list is invalid
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @throws InvalidArgumentException if the keyset is not valid
|
||||
*
|
||||
* @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 Json string.
|
||||
*
|
||||
* @throws InvalidArgumentException if the data is not valid
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @throws InvalidArgumentException if the index is not defined
|
||||
*/
|
||||
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 null|Algorithm $algorithm Specifies the algorithm to be used
|
||||
* @param array $restrictions More restrictions such as 'kid' or 'kty'
|
||||
*
|
||||
* @throws InvalidArgumentException if the key type is not valid (must be "sig" or "enc")
|
||||
*/
|
||||
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 (0 === count($result)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
usort($result, [$this, 'sortKeys']);
|
||||
|
||||
return $result[0]['key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the key does not fulfill with the "key_ops" constraint
|
||||
*
|
||||
* @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')) {
|
||||
$key_ops = $key->get('key_ops');
|
||||
if (!is_array($key_ops)) {
|
||||
throw new InvalidArgumentException('Invalid key parameter "key_ops". Should be a list of key operations');
|
||||
}
|
||||
|
||||
return $type === self::convertKeyOpsToKeyUse($key_ops) ? 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the key operation is not supported
|
||||
*/
|
||||
private static function convertKeyOpsToKeyUse(array $key_ops): string
|
||||
{
|
||||
switch (true) {
|
||||
case in_array('verify', $key_ops, true):
|
||||
case in_array('sign', $key_ops, true):
|
||||
return 'sig';
|
||||
case in_array('encrypt', $key_ops, true):
|
||||
case in_array('decrypt', $key_ops, true):
|
||||
case in_array('wrapKey', $key_ops, true):
|
||||
case in_array('unwrapKey', $key_ops, true):
|
||||
case in_array('deriveKey', $key_ops, true):
|
||||
case in_array('deriveBits', $key_ops, true):
|
||||
return 'enc';
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('Unsupported key operation value "%s"', $key_ops));
|
||||
}
|
||||
}
|
||||
}
|
||||
23
vendor/web-token/jwt-core/JWT.php
vendored
Normal file
23
vendor/web-token/jwt-core/JWT.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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;
|
||||
|
||||
interface JWT
|
||||
{
|
||||
/**
|
||||
* Returns the payload of the JWT.
|
||||
* null is a valid payload (e.g. JWS with detached payload).
|
||||
*/
|
||||
public function getPayload(): ?string;
|
||||
}
|
||||
21
vendor/web-token/jwt-core/LICENSE
vendored
Normal file
21
vendor/web-token/jwt-core/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2019 Spomky-Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
15
vendor/web-token/jwt-core/README.md
vendored
Normal file
15
vendor/web-token/jwt-core/README.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
PHP JWT Core Component
|
||||
======================
|
||||
|
||||
This repository is a sub repository of [the JWT Framework](https://github.com/web-token/jwt-framework) project and is READ ONLY.
|
||||
|
||||
**Please do not submit any Pull Request here.**
|
||||
You should go to [the main repository](https://github.com/web-token/jwt-framework) instead.
|
||||
|
||||
# Documentation
|
||||
|
||||
The official documentation is available as https://web-token.spomky-labs.com/
|
||||
|
||||
# Licence
|
||||
|
||||
This software is release under [MIT licence](LICENSE).
|
||||
82
vendor/web-token/jwt-core/Tests/AlgorithmManagerFactoryTest.php
vendored
Normal file
82
vendor/web-token/jwt-core/Tests/AlgorithmManagerFactoryTest.php
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Tests;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Jose\Component\Core\AlgorithmManager;
|
||||
use Jose\Component\Core\AlgorithmManagerFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use TypeError;
|
||||
|
||||
/**
|
||||
* @group unit
|
||||
* @group JWAManager
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class AlgorithmManagerFactoryTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var null|AlgorithmManagerFactory
|
||||
*/
|
||||
private $algorithmManagerFactory;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers \Jose\Component\Core\AlgorithmManagerFactory
|
||||
*/
|
||||
public function iCanListSupportedAliases(): void
|
||||
{
|
||||
static::assertEquals(['foo'], $this->getAlgorithmManagerFactory()->aliases());
|
||||
static::assertEquals(['foo'], array_keys($this->getAlgorithmManagerFactory()->all()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers \Jose\Component\Core\AlgorithmManager
|
||||
*/
|
||||
public function iCannotCreateAnAlgorithmManagerWithABadArgument(): void
|
||||
{
|
||||
$this->expectException(TypeError::class);
|
||||
|
||||
new AlgorithmManager(['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers \Jose\Component\Core\AlgorithmManager
|
||||
*/
|
||||
public function iCannotGetAnAlgorithmThatDoesNotExist(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('The algorithm "HS384" is not supported.');
|
||||
|
||||
$manager = new AlgorithmManager([new FooAlgorithm()]);
|
||||
|
||||
static::assertEquals(['foo'], $manager->list());
|
||||
static::assertTrue($manager->has('foo'));
|
||||
static::assertFalse($manager->has('HS384'));
|
||||
$manager->get('HS384');
|
||||
}
|
||||
|
||||
private function getAlgorithmManagerFactory(): AlgorithmManagerFactory
|
||||
{
|
||||
if (null === $this->algorithmManagerFactory) {
|
||||
$this->algorithmManagerFactory = new AlgorithmManagerFactory();
|
||||
$this->algorithmManagerFactory->add('foo', new FooAlgorithm());
|
||||
}
|
||||
|
||||
return $this->algorithmManagerFactory;
|
||||
}
|
||||
}
|
||||
29
vendor/web-token/jwt-core/Tests/FooAlgorithm.php
vendored
Normal file
29
vendor/web-token/jwt-core/Tests/FooAlgorithm.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Tests;
|
||||
|
||||
use Jose\Component\Core\Algorithm;
|
||||
|
||||
class FooAlgorithm implements Algorithm
|
||||
{
|
||||
public function name(): string
|
||||
{
|
||||
return 'foo';
|
||||
}
|
||||
|
||||
public function allowedKeyTypes(): array
|
||||
{
|
||||
return ['FOO'];
|
||||
}
|
||||
}
|
||||
286
vendor/web-token/jwt-core/Tests/JWKSetTest.php
vendored
Normal file
286
vendor/web-token/jwt-core/Tests/JWKSetTest.php
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Tests;
|
||||
|
||||
use function count;
|
||||
use InvalidArgumentException;
|
||||
use Jose\Component\Core\JWK;
|
||||
use Jose\Component\Core\JWKSet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @group unit
|
||||
* @group JWKSet
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class JWKSetTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanSelectAKeyInAKeySet(): void
|
||||
{
|
||||
$jwkset = $this->getPublicKeySet();
|
||||
|
||||
$jwk = $jwkset->selectKey('enc');
|
||||
static::assertInstanceOf(JWK::class, $jwk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCannotSelectAKeyFromAKeySetWithUnsupportedUsageParameter(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Allowed key types are "sig" or "enc".');
|
||||
|
||||
$jwkset = $this->getPublicKeySet();
|
||||
$jwkset->selectKey('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCannotCreateAKeySetWithBadArguments(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Invalid data.');
|
||||
|
||||
JWKSet::createFromKeyData(['keys' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanGetAllKeysInAKeySet(): void
|
||||
{
|
||||
$jwkset = $this->getPublicKeySet();
|
||||
static::assertEquals(3, count($jwkset->all()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanAddKeysInAKeySet(): void
|
||||
{
|
||||
$jwkset = $this->getPublicKeySet();
|
||||
$new_jwkset = $jwkset->with(new JWK(['kty' => 'none']));
|
||||
static::assertEquals(4, count($new_jwkset->all()));
|
||||
static::assertNotSame($jwkset, $new_jwkset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanSelectAKeyWithAlgorithm(): void
|
||||
{
|
||||
$jwkset = $this->getPublicKeySet();
|
||||
|
||||
$jwk = $jwkset->selectKey('enc', new FooAlgorithm());
|
||||
static::assertInstanceOf(JWK::class, $jwk);
|
||||
static::assertEquals(
|
||||
[
|
||||
'kid' => '71ee230371d19630bc17fb90ccf20ae632ad8cf8',
|
||||
'kty' => 'FOO',
|
||||
'alg' => 'foo',
|
||||
'use' => 'enc',
|
||||
],
|
||||
$jwk->all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanSelectAKeyWithAlgorithmAndKeyId(): void
|
||||
{
|
||||
$jwkset = $this->getPublicKeySet();
|
||||
|
||||
$jwk = $jwkset->selectKey('sig', new FooAlgorithm(), ['kid' => '02491f945c951adf156f370788e8ccdabf8877a8']);
|
||||
static::assertInstanceOf(JWK::class, $jwk);
|
||||
static::assertEquals(
|
||||
[
|
||||
'kid' => '02491f945c951adf156f370788e8ccdabf8877a8',
|
||||
'kty' => 'FOO',
|
||||
'alg' => 'foo',
|
||||
'use' => 'sig',
|
||||
],
|
||||
$jwk->all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanSelectAKeyWithWithKeyId(): void
|
||||
{
|
||||
$jwkset = $this->getPublicKeySet();
|
||||
|
||||
$jwk = $jwkset->selectKey('sig', null, ['kid' => '02491f945c951adf156f370788e8ccdabf8877a8']);
|
||||
static::assertInstanceOf(JWK::class, $jwk);
|
||||
static::assertEquals(
|
||||
[
|
||||
'kid' => '02491f945c951adf156f370788e8ccdabf8877a8',
|
||||
'kty' => 'FOO',
|
||||
'alg' => 'foo',
|
||||
'use' => 'sig',
|
||||
],
|
||||
$jwk->all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function theKeySetDoesNotContainsSuitableAKeyThatFitsOnTheRequirements(): void
|
||||
{
|
||||
$jwkset = $this->getPublicKeySet();
|
||||
|
||||
$jwk = $jwkset->selectKey('enc', null, ['kid' => '02491f945c951adf156f370788e8ccdabf8877a8']);
|
||||
static::assertNull($jwk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanCreateAKeySetUsingValues(): void
|
||||
{
|
||||
$values = ['keys' => [[
|
||||
'kid' => '71ee230371d19630bc17fb90ccf20ae632ad8cf8',
|
||||
'kty' => 'FOO',
|
||||
'alg' => 'foo',
|
||||
'use' => 'sig',
|
||||
]]];
|
||||
$jwkset = JWKSet::createFromKeyData($values);
|
||||
static::assertEquals(1, count($jwkset));
|
||||
static::assertTrue($jwkset->has('71ee230371d19630bc17fb90ccf20ae632ad8cf8'));
|
||||
static::assertFalse($jwkset->has(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function keySet(): void
|
||||
{
|
||||
$jwk1 = new JWK([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'use' => 'sign',
|
||||
'key_ops' => ['sign'],
|
||||
'alg' => 'ES256',
|
||||
'kid' => '0123456789',
|
||||
]);
|
||||
|
||||
$jwk2 = new JWK([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'd' => 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI',
|
||||
'use' => 'sign',
|
||||
'key_ops' => ['verify'],
|
||||
'alg' => 'ES256',
|
||||
'kid' => '9876543210',
|
||||
]);
|
||||
|
||||
$jwkset = new JWKSet([$jwk1]);
|
||||
$jwkset = $jwkset->with($jwk2);
|
||||
|
||||
static::assertEquals('{"keys":[{"kty":"EC","crv":"P-256","x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU","y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0","use":"sign","key_ops":["sign"],"alg":"ES256","kid":"0123456789"},{"kty":"EC","crv":"P-256","x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU","y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0","d":"jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI","use":"sign","key_ops":["verify"],"alg":"ES256","kid":"9876543210"}]}', json_encode($jwkset));
|
||||
static::assertEquals(2, count($jwkset));
|
||||
static::assertEquals(2, $jwkset->count());
|
||||
static::assertTrue($jwkset->has('0123456789'));
|
||||
static::assertTrue($jwkset->has('9876543210'));
|
||||
static::assertFalse($jwkset->has(0));
|
||||
|
||||
foreach ($jwkset as $key) {
|
||||
static::assertEquals('EC', $key->get('kty'));
|
||||
}
|
||||
|
||||
static::assertEquals('9876543210', $jwkset->get('9876543210')->get('kid'));
|
||||
$jwkset = $jwkset->without('9876543210');
|
||||
$jwkset = $jwkset->without('9876543210');
|
||||
|
||||
static::assertEquals(1, count($jwkset));
|
||||
static::assertEquals(1, $jwkset->count());
|
||||
|
||||
$jwkset = $jwkset->without('0123456789');
|
||||
static::assertEquals(0, $jwkset->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function keySet2(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Undefined index.');
|
||||
|
||||
$jwk1 = new JWK([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'use' => 'sign',
|
||||
'key_ops' => ['sign'],
|
||||
'alg' => 'ES256',
|
||||
'kid' => '0123456789',
|
||||
]);
|
||||
|
||||
$jwk2 = new JWK([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'd' => 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI',
|
||||
'use' => 'sign',
|
||||
'key_ops' => ['verify'],
|
||||
'alg' => 'ES256',
|
||||
'kid' => '9876543210',
|
||||
]);
|
||||
|
||||
$jwkset = new JWKSet([$jwk1, $jwk2]);
|
||||
|
||||
$jwkset->get(2);
|
||||
}
|
||||
|
||||
private function getPublicKeySet(): JWKSet
|
||||
{
|
||||
$keys = ['keys' => [
|
||||
[
|
||||
'kid' => '71ee230371d19630bc17fb90ccf20ae632ad8cf8',
|
||||
'kty' => 'FOO',
|
||||
'alg' => 'foo',
|
||||
'use' => 'enc',
|
||||
],
|
||||
[
|
||||
'kid' => '02491f945c951adf156f370788e8ccdabf8877a8',
|
||||
'kty' => 'FOO',
|
||||
'alg' => 'foo',
|
||||
'use' => 'sig',
|
||||
],
|
||||
[
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
],
|
||||
]];
|
||||
|
||||
return JWKSet::createFromKeyData($keys);
|
||||
}
|
||||
}
|
||||
147
vendor/web-token/jwt-core/Tests/JWKTest.php
vendored
Normal file
147
vendor/web-token/jwt-core/Tests/JWKTest.php
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Tests;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Jose\Component\Core\JWK;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @group unit
|
||||
* @group JWK
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class JWKTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function aKeyContainsAllExpectedParameters(): void
|
||||
{
|
||||
$jwk = new JWK([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'use' => 'sig',
|
||||
'key_ops' => ['sign'],
|
||||
'alg' => 'ES256',
|
||||
'bar' => 'plic',
|
||||
]);
|
||||
|
||||
static::assertEquals('EC', $jwk->get('kty'));
|
||||
static::assertEquals('ES256', $jwk->get('alg'));
|
||||
static::assertEquals('sig', $jwk->get('use'));
|
||||
static::assertFalse($jwk->has('kid'));
|
||||
static::assertEquals(['sign'], $jwk->get('key_ops'));
|
||||
static::assertEquals('P-256', $jwk->get('crv'));
|
||||
static::assertFalse($jwk->has('x5u'));
|
||||
static::assertFalse($jwk->has('x5c'));
|
||||
static::assertFalse($jwk->has('x5t'));
|
||||
static::assertFalse($jwk->has('x5t#256'));
|
||||
static::assertEquals('f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU', $jwk->get('x'));
|
||||
static::assertEquals('x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0', $jwk->get('y'));
|
||||
static::assertEquals('{"kty":"EC","crv":"P-256","x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU","y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0","use":"sig","key_ops":["sign"],"alg":"ES256","bar":"plic"}', json_encode($jwk));
|
||||
static::assertEquals('oKIywvGUpTVTyxMQ3bwIIeQUudfr_CkLMjCE19ECD-U', $jwk->thumbprint('sha256'));
|
||||
static::assertEquals('EMMMl6Rj75mqhcABihxxl_VCN9s', $jwk->thumbprint('sha1'));
|
||||
static::assertEquals('dqwHnan4iJ1_eEll-o4Egw', $jwk->thumbprint('md5'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCannotGetTheThumbprintOfTheKeyWhenIUseAnUnsupportedHashingAlgorithm(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('The hash algorithm "foo" is not supported.');
|
||||
|
||||
$jwk = new JWK([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'use' => 'sig',
|
||||
'key_ops' => ['sign'],
|
||||
'alg' => 'ES256',
|
||||
'bar' => 'plic',
|
||||
]);
|
||||
|
||||
$jwk->thumbprint('foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iMustSetAtLeastTheKtyParameter(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('The parameter "kty" is mandatory.');
|
||||
|
||||
new JWK([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCannotGetAParameterThatDoesNotExist(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('The value identified by "ABCD" does not exist.');
|
||||
|
||||
$jwk = new JWK([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'use' => 'sign',
|
||||
'key_ops' => ['sign'],
|
||||
'alg' => 'ES256',
|
||||
'bar' => 'plic',
|
||||
]);
|
||||
|
||||
$jwk->get('ABCD');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanConvertAPrivateKeyIntoPublicKey(): void
|
||||
{
|
||||
$private = new JWK([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'd' => 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI',
|
||||
'use' => 'sign',
|
||||
'key_ops' => ['verify'],
|
||||
'alg' => 'ES256',
|
||||
'kid' => '9876543210',
|
||||
]);
|
||||
|
||||
$public = $private->toPublic();
|
||||
|
||||
static::assertEquals(json_encode([
|
||||
'kty' => 'EC',
|
||||
'crv' => 'P-256',
|
||||
'x' => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
|
||||
'y' => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
|
||||
'use' => 'sign',
|
||||
'key_ops' => ['verify'],
|
||||
'alg' => 'ES256',
|
||||
'kid' => '9876543210',
|
||||
]), json_encode($public));
|
||||
}
|
||||
}
|
||||
35
vendor/web-token/jwt-core/Tests/JsonConverterTest.php
vendored
Normal file
35
vendor/web-token/jwt-core/Tests/JsonConverterTest.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Tests;
|
||||
|
||||
use Jose\Component\Core\Util\JsonConverter;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @group unit
|
||||
* @group JsonConverter
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class JsonConverterTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function iCanConvertAnObjectIntoAJsonString(): void
|
||||
{
|
||||
static::assertEquals('{"foo":"BAR"}', JsonConverter::encode(['foo' => 'BAR']));
|
||||
static::assertEquals(['foo' => 'BAR'], JsonConverter::decode('{"foo":"BAR"}'));
|
||||
}
|
||||
}
|
||||
223
vendor/web-token/jwt-core/Util/BigInteger.php
vendored
Normal file
223
vendor/web-token/jwt-core/Util/BigInteger.php
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Util;
|
||||
|
||||
use Brick\Math\BigInteger as BrickBigInteger;
|
||||
use function chr;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class BigInteger
|
||||
{
|
||||
/**
|
||||
* Holds the BigInteger's value.
|
||||
*
|
||||
* @var BrickBigInteger
|
||||
*/
|
||||
private $value;
|
||||
|
||||
private function __construct(BrickBigInteger $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public static function createFromBinaryString(string $value): self
|
||||
{
|
||||
$data = current(unpack('H*', $value));
|
||||
|
||||
return new self(BrickBigInteger::fromBase($data, 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public static function createFromDecimal(int $value): self
|
||||
{
|
||||
return new self(BrickBigInteger::of($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public static function createFromBigInteger(BrickBigInteger $value): self
|
||||
{
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a BigInteger to a binary string.
|
||||
*/
|
||||
public function toBytes(): string
|
||||
{
|
||||
if ($this->value->isEqualTo(BrickBigInteger::zero())) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$temp = $this->value->toBase(16);
|
||||
$temp = 0 !== (mb_strlen($temp, '8bit') & 1) ? '0'.$temp : $temp;
|
||||
$temp = hex2bin($temp);
|
||||
|
||||
return ltrim($temp, chr(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two BigIntegers.
|
||||
*
|
||||
* @param BigInteger $y
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function add(self $y): self
|
||||
{
|
||||
$value = $this->value->plus($y->value);
|
||||
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts two BigIntegers.
|
||||
*
|
||||
* @param BigInteger $y
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function subtract(self $y): self
|
||||
{
|
||||
$value = $this->value->minus($y->value);
|
||||
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two BigIntegers.
|
||||
*
|
||||
* @param BigInteger $x
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function multiply(self $x): self
|
||||
{
|
||||
$value = $this->value->multipliedBy($x->value);
|
||||
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides two BigIntegers.
|
||||
*
|
||||
* @param BigInteger $x
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function divide(self $x): self
|
||||
{
|
||||
$value = $this->value->dividedBy($x->value);
|
||||
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs modular exponentiation.
|
||||
*
|
||||
* @param BigInteger $e
|
||||
* @param BigInteger $n
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function modPow(self $e, self $n): self
|
||||
{
|
||||
$value = $this->value->modPow($e->value, $n->value);
|
||||
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs modular exponentiation.
|
||||
*
|
||||
* @param BigInteger $d
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function mod(self $d): self
|
||||
{
|
||||
$value = $this->value->mod($d->value);
|
||||
|
||||
return new self($value);
|
||||
}
|
||||
|
||||
public function modInverse(BigInteger $m): BigInteger
|
||||
{
|
||||
return new self($this->value->modInverse($m->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two numbers.
|
||||
*
|
||||
* @param BigInteger $y
|
||||
*/
|
||||
public function compare(self $y): int
|
||||
{
|
||||
return $this->value->compareTo($y->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BigInteger $y
|
||||
*/
|
||||
public function equals(self $y): bool
|
||||
{
|
||||
return $this->value->isEqualTo($y->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BigInteger $y
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public static function random(self $y): self
|
||||
{
|
||||
return new self(BrickBigInteger::randomRange(0, $y->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BigInteger $y
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function gcd(self $y): self
|
||||
{
|
||||
return new self($this->value->gcd($y->value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BigInteger $y
|
||||
*/
|
||||
public function lowerThan(self $y): bool
|
||||
{
|
||||
return $this->value->isLessThan($y->value);
|
||||
}
|
||||
|
||||
public function isEven(): bool
|
||||
{
|
||||
return $this->value->isEven();
|
||||
}
|
||||
|
||||
public function get(): BrickBigInteger
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
335
vendor/web-token/jwt-core/Util/ECKey.php
vendored
Normal file
335
vendor/web-token/jwt-core/Util/ECKey.php
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Util;
|
||||
|
||||
use Base64Url\Base64Url;
|
||||
use function extension_loaded;
|
||||
use InvalidArgumentException;
|
||||
use Jose\Component\Core\JWK;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ECKey
|
||||
{
|
||||
public static function convertToPEM(JWK $jwk): string
|
||||
{
|
||||
if ($jwk->has('d')) {
|
||||
return self::convertPrivateKeyToPEM($jwk);
|
||||
}
|
||||
|
||||
return self::convertPublicKeyToPEM($jwk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the curve is not supported
|
||||
*/
|
||||
public static function convertPublicKeyToPEM(JWK $jwk): string
|
||||
{
|
||||
switch ($jwk->get('crv')) {
|
||||
case 'P-256':
|
||||
$der = self::p256PublicKey();
|
||||
|
||||
break;
|
||||
case 'secp256k1':
|
||||
$der = self::p256KPublicKey();
|
||||
|
||||
break;
|
||||
case 'P-384':
|
||||
$der = self::p384PublicKey();
|
||||
|
||||
break;
|
||||
case 'P-521':
|
||||
$der = self::p521PublicKey();
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported curve.');
|
||||
}
|
||||
$der .= self::getKey($jwk);
|
||||
$pem = '-----BEGIN PUBLIC KEY-----'.PHP_EOL;
|
||||
$pem .= chunk_split(base64_encode($der), 64, PHP_EOL);
|
||||
$pem .= '-----END PUBLIC KEY-----'.PHP_EOL;
|
||||
|
||||
return $pem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the curve is not supported
|
||||
*/
|
||||
public static function convertPrivateKeyToPEM(JWK $jwk): string
|
||||
{
|
||||
switch ($jwk->get('crv')) {
|
||||
case 'P-256':
|
||||
$der = self::p256PrivateKey($jwk);
|
||||
|
||||
break;
|
||||
case 'secp256k1':
|
||||
$der = self::p256KPrivateKey($jwk);
|
||||
|
||||
break;
|
||||
case 'P-384':
|
||||
$der = self::p384PrivateKey($jwk);
|
||||
|
||||
break;
|
||||
case 'P-521':
|
||||
$der = self::p521PrivateKey($jwk);
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported curve.');
|
||||
}
|
||||
$der .= self::getKey($jwk);
|
||||
$pem = '-----BEGIN EC PRIVATE KEY-----'.PHP_EOL;
|
||||
$pem .= chunk_split(base64_encode($der), 64, PHP_EOL);
|
||||
$pem .= '-----END EC PRIVATE KEY-----'.PHP_EOL;
|
||||
|
||||
return $pem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a EC key with the given curve and additional values.
|
||||
*
|
||||
* @param string $curve The curve
|
||||
* @param array $values values to configure the key
|
||||
*/
|
||||
public static function createECKey(string $curve, array $values = []): JWK
|
||||
{
|
||||
$jwk = self::createECKeyUsingOpenSSL($curve);
|
||||
$values = array_merge($values, $jwk);
|
||||
|
||||
return new JWK($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the curve is not supported
|
||||
*/
|
||||
private static function getNistCurveSize(string $curve): int
|
||||
{
|
||||
switch ($curve) {
|
||||
case 'P-256':
|
||||
case 'secp256k1':
|
||||
return 256;
|
||||
case 'P-384':
|
||||
return 384;
|
||||
case 'P-521':
|
||||
return 521;
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('The curve "%s" is not supported.', $curve));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException if the extension OpenSSL is not available
|
||||
* @throws RuntimeException if the key cannot be created
|
||||
*/
|
||||
private static function createECKeyUsingOpenSSL(string $curve): array
|
||||
{
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new RuntimeException('Please install the OpenSSL extension');
|
||||
}
|
||||
$key = openssl_pkey_new([
|
||||
'curve_name' => self::getOpensslCurveName($curve),
|
||||
'private_key_type' => OPENSSL_KEYTYPE_EC,
|
||||
]);
|
||||
if (false === $key) {
|
||||
throw new RuntimeException('Unable to create the key');
|
||||
}
|
||||
$result = openssl_pkey_export($key, $out);
|
||||
if (false === $result) {
|
||||
throw new RuntimeException('Unable to create the key');
|
||||
}
|
||||
$res = openssl_pkey_get_private($out);
|
||||
if (false === $res) {
|
||||
throw new RuntimeException('Unable to create the key');
|
||||
}
|
||||
$details = openssl_pkey_get_details($res);
|
||||
$nistCurveSize = self::getNistCurveSize($curve);
|
||||
|
||||
return [
|
||||
'kty' => 'EC',
|
||||
'crv' => $curve,
|
||||
'd' => Base64Url::encode(str_pad($details['ec']['d'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)),
|
||||
'x' => Base64Url::encode(str_pad($details['ec']['x'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)),
|
||||
'y' => Base64Url::encode(str_pad($details['ec']['y'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the curve is not supported
|
||||
*/
|
||||
private static function getOpensslCurveName(string $curve): string
|
||||
{
|
||||
switch ($curve) {
|
||||
case 'P-256':
|
||||
return 'prime256v1';
|
||||
case 'secp256k1':
|
||||
return 'secp256k1';
|
||||
case 'P-384':
|
||||
return 'secp384r1';
|
||||
case 'P-521':
|
||||
return 'secp521r1';
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('The curve "%s" is not supported.', $curve));
|
||||
}
|
||||
}
|
||||
|
||||
private static function p256PublicKey(): string
|
||||
{
|
||||
return pack(
|
||||
'H*',
|
||||
'3059' // SEQUENCE, length 89
|
||||
.'3013' // SEQUENCE, length 19
|
||||
.'0607' // OID, length 7
|
||||
.'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key
|
||||
.'0608' // OID, length 8
|
||||
.'2a8648ce3d030107' // 1.2.840.10045.3.1.7 = P-256 Curve
|
||||
.'0342' // BIT STRING, length 66
|
||||
.'00' // prepend with NUL - pubkey will follow
|
||||
);
|
||||
}
|
||||
|
||||
private static function p256KPublicKey(): string
|
||||
{
|
||||
return pack(
|
||||
'H*',
|
||||
'3056' // SEQUENCE, length 86
|
||||
.'3010' // SEQUENCE, length 16
|
||||
.'0607' // OID, length 7
|
||||
.'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key
|
||||
.'0605' // OID, length 8
|
||||
.'2B8104000A' // 1.3.132.0.10 secp256k1
|
||||
.'0342' // BIT STRING, length 66
|
||||
.'00' // prepend with NUL - pubkey will follow
|
||||
);
|
||||
}
|
||||
|
||||
private static function p384PublicKey(): string
|
||||
{
|
||||
return pack(
|
||||
'H*',
|
||||
'3076' // SEQUENCE, length 118
|
||||
.'3010' // SEQUENCE, length 16
|
||||
.'0607' // OID, length 7
|
||||
.'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key
|
||||
.'0605' // OID, length 5
|
||||
.'2b81040022' // 1.3.132.0.34 = P-384 Curve
|
||||
.'0362' // BIT STRING, length 98
|
||||
.'00' // prepend with NUL - pubkey will follow
|
||||
);
|
||||
}
|
||||
|
||||
private static function p521PublicKey(): string
|
||||
{
|
||||
return pack(
|
||||
'H*',
|
||||
'30819b' // SEQUENCE, length 154
|
||||
.'3010' // SEQUENCE, length 16
|
||||
.'0607' // OID, length 7
|
||||
.'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key
|
||||
.'0605' // OID, length 5
|
||||
.'2b81040023' // 1.3.132.0.35 = P-521 Curve
|
||||
.'038186' // BIT STRING, length 134
|
||||
.'00' // prepend with NUL - pubkey will follow
|
||||
);
|
||||
}
|
||||
|
||||
private static function p256PrivateKey(JWK $jwk): string
|
||||
{
|
||||
$d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 32, "\0", STR_PAD_LEFT))[1];
|
||||
|
||||
return pack(
|
||||
'H*',
|
||||
'3077' // SEQUENCE, length 87+length($d)=32
|
||||
.'020101' // INTEGER, 1
|
||||
.'0420' // OCTET STRING, length($d) = 32
|
||||
.$d
|
||||
.'a00a' // TAGGED OBJECT #0, length 10
|
||||
.'0608' // OID, length 8
|
||||
.'2a8648ce3d030107' // 1.3.132.0.34 = P-256 Curve
|
||||
.'a144' // TAGGED OBJECT #1, length 68
|
||||
.'0342' // BIT STRING, length 66
|
||||
.'00' // prepend with NUL - pubkey will follow
|
||||
);
|
||||
}
|
||||
|
||||
private static function p256KPrivateKey(JWK $jwk): string
|
||||
{
|
||||
$d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 32, "\0", STR_PAD_LEFT))[1];
|
||||
|
||||
return pack(
|
||||
'H*',
|
||||
'3074' // SEQUENCE, length 84+length($d)=32
|
||||
.'020101' // INTEGER, 1
|
||||
.'0420' // OCTET STRING, length($d) = 32
|
||||
.$d
|
||||
.'a007' // TAGGED OBJECT #0, length 7
|
||||
.'0605' // OID, length 5
|
||||
.'2b8104000a' // 1.3.132.0.10 secp256k1
|
||||
.'a144' // TAGGED OBJECT #1, length 68
|
||||
.'0342' // BIT STRING, length 66
|
||||
.'00' // prepend with NUL - pubkey will follow
|
||||
);
|
||||
}
|
||||
|
||||
private static function p384PrivateKey(JWK $jwk): string
|
||||
{
|
||||
$d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 48, "\0", STR_PAD_LEFT))[1];
|
||||
|
||||
return pack(
|
||||
'H*',
|
||||
'3081a4' // SEQUENCE, length 116 + length($d)=48
|
||||
.'020101' // INTEGER, 1
|
||||
.'0430' // OCTET STRING, length($d) = 30
|
||||
.$d
|
||||
.'a007' // TAGGED OBJECT #0, length 7
|
||||
.'0605' // OID, length 5
|
||||
.'2b81040022' // 1.3.132.0.34 = P-384 Curve
|
||||
.'a164' // TAGGED OBJECT #1, length 100
|
||||
.'0362' // BIT STRING, length 98
|
||||
.'00' // prepend with NUL - pubkey will follow
|
||||
);
|
||||
}
|
||||
|
||||
private static function p521PrivateKey(JWK $jwk): string
|
||||
{
|
||||
$d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 66, "\0", STR_PAD_LEFT))[1];
|
||||
|
||||
return pack(
|
||||
'H*',
|
||||
'3081dc' // SEQUENCE, length 154 + length($d)=66
|
||||
.'020101' // INTEGER, 1
|
||||
.'0442' // OCTET STRING, length(d) = 66
|
||||
.$d
|
||||
.'a007' // TAGGED OBJECT #0, length 7
|
||||
.'0605' // OID, length 5
|
||||
.'2b81040023' // 1.3.132.0.35 = P-521 Curve
|
||||
.'a18189' // TAGGED OBJECT #1, length 137
|
||||
.'038186' // BIT STRING, length 134
|
||||
.'00' // prepend with NUL - pubkey will follow
|
||||
);
|
||||
}
|
||||
|
||||
private static function getKey(JWK $jwk): string
|
||||
{
|
||||
$nistCurveSize = self::getNistCurveSize($jwk->get('crv'));
|
||||
$length = (int) ceil($nistCurveSize / 8);
|
||||
|
||||
return
|
||||
"\04"
|
||||
.str_pad(Base64Url::decode($jwk->get('x')), $length, "\0", STR_PAD_LEFT)
|
||||
.str_pad(Base64Url::decode($jwk->get('y')), $length, "\0", STR_PAD_LEFT);
|
||||
}
|
||||
}
|
||||
132
vendor/web-token/jwt-core/Util/ECSignature.php
vendored
Normal file
132
vendor/web-token/jwt-core/Util/ECSignature.php
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Util;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use const STR_PAD_LEFT;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class ECSignature
|
||||
{
|
||||
private const ASN1_SEQUENCE = '30';
|
||||
private const ASN1_INTEGER = '02';
|
||||
private const ASN1_MAX_SINGLE_BYTE = 128;
|
||||
private const ASN1_LENGTH_2BYTES = '81';
|
||||
private const ASN1_BIG_INTEGER_LIMIT = '7f';
|
||||
private const ASN1_NEGATIVE_INTEGER = '00';
|
||||
private const BYTE_SIZE = 2;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the length of the signature is invalid
|
||||
*/
|
||||
public static function toAsn1(string $signature, int $length): string
|
||||
{
|
||||
$signature = bin2hex($signature);
|
||||
|
||||
if (self::octetLength($signature) !== $length) {
|
||||
throw new InvalidArgumentException('Invalid signature length.');
|
||||
}
|
||||
|
||||
$pointR = self::preparePositiveInteger(mb_substr($signature, 0, $length, '8bit'));
|
||||
$pointS = self::preparePositiveInteger(mb_substr($signature, $length, null, '8bit'));
|
||||
|
||||
$lengthR = self::octetLength($pointR);
|
||||
$lengthS = self::octetLength($pointS);
|
||||
|
||||
$totalLength = $lengthR + $lengthS + self::BYTE_SIZE + self::BYTE_SIZE;
|
||||
$lengthPrefix = $totalLength > self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : '';
|
||||
|
||||
return hex2bin(
|
||||
self::ASN1_SEQUENCE
|
||||
.$lengthPrefix.dechex($totalLength)
|
||||
.self::ASN1_INTEGER.dechex($lengthR).$pointR
|
||||
.self::ASN1_INTEGER.dechex($lengthS).$pointS
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the signature is not an ASN.1 sequence
|
||||
*/
|
||||
public static function fromAsn1(string $signature, int $length): string
|
||||
{
|
||||
$message = bin2hex($signature);
|
||||
$position = 0;
|
||||
|
||||
if (self::ASN1_SEQUENCE !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) {
|
||||
throw new InvalidArgumentException('Invalid data. Should start with a sequence.');
|
||||
}
|
||||
|
||||
if (self::ASN1_LENGTH_2BYTES === self::readAsn1Content($message, $position, self::BYTE_SIZE)) {
|
||||
$position += self::BYTE_SIZE;
|
||||
}
|
||||
|
||||
$pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
|
||||
$pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
|
||||
|
||||
return hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT).str_pad($pointS, $length, '0', STR_PAD_LEFT));
|
||||
}
|
||||
|
||||
private static function octetLength(string $data): int
|
||||
{
|
||||
return (int) (mb_strlen($data, '8bit') / self::BYTE_SIZE);
|
||||
}
|
||||
|
||||
private static function preparePositiveInteger(string $data): string
|
||||
{
|
||||
if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) {
|
||||
return self::ASN1_NEGATIVE_INTEGER.$data;
|
||||
}
|
||||
|
||||
while (0 === mb_strpos($data, self::ASN1_NEGATIVE_INTEGER, 0, '8bit')
|
||||
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT) {
|
||||
$data = mb_substr($data, 2, null, '8bit');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function readAsn1Content(string $message, int &$position, int $length): string
|
||||
{
|
||||
$content = mb_substr($message, $position, $length, '8bit');
|
||||
$position += $length;
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the data is not an integer
|
||||
*/
|
||||
private static function readAsn1Integer(string $message, int &$position): string
|
||||
{
|
||||
if (self::ASN1_INTEGER !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) {
|
||||
throw new InvalidArgumentException('Invalid data. Should contain an integer.');
|
||||
}
|
||||
|
||||
$length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE));
|
||||
|
||||
return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE);
|
||||
}
|
||||
|
||||
private static function retrievePositiveInteger(string $data): string
|
||||
{
|
||||
while (0 === mb_strpos($data, self::ASN1_NEGATIVE_INTEGER, 0, '8bit')
|
||||
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) {
|
||||
$data = mb_substr($data, 2, null, '8bit');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
103
vendor/web-token/jwt-core/Util/Hash.php
vendored
Normal file
103
vendor/web-token/jwt-core/Util/Hash.php
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Util;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class Hash
|
||||
{
|
||||
/**
|
||||
* Hash Parameter.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $hash;
|
||||
|
||||
/**
|
||||
* DER encoding T.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $t;
|
||||
|
||||
/**
|
||||
* Hash Length.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $length;
|
||||
|
||||
private function __construct(string $hash, int $length, string $t)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
$this->length = $length;
|
||||
$this->t = $t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Hash
|
||||
*/
|
||||
public static function sha1(): self
|
||||
{
|
||||
return new self('sha1', 20, "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Hash
|
||||
*/
|
||||
public static function sha256(): self
|
||||
{
|
||||
return new self('sha256', 32, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Hash
|
||||
*/
|
||||
public static function sha384(): self
|
||||
{
|
||||
return new self('sha384', 48, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Hash
|
||||
*/
|
||||
public static function sha512(): self
|
||||
{
|
||||
return new self('sha512', 64, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40");
|
||||
}
|
||||
|
||||
public function getLength(): int
|
||||
{
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the HMAC.
|
||||
*/
|
||||
public function hash(string $text): string
|
||||
{
|
||||
return hash($this->hash, $text, true);
|
||||
}
|
||||
|
||||
public function name(): string
|
||||
{
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
public function t(): string
|
||||
{
|
||||
return $this->t;
|
||||
}
|
||||
}
|
||||
48
vendor/web-token/jwt-core/Util/JsonConverter.php
vendored
Normal file
48
vendor/web-token/jwt-core/Util/JsonConverter.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Util;
|
||||
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
final class JsonConverter
|
||||
{
|
||||
/**
|
||||
* @param mixed $payload
|
||||
*
|
||||
* @throws RuntimeException if the payload cannot be encoded
|
||||
*/
|
||||
public static function encode($payload): string
|
||||
{
|
||||
try {
|
||||
return json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
} catch (Throwable $throwable) {
|
||||
throw new RuntimeException('Invalid content.', $throwable->getCode(), $throwable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RuntimeException if the payload cannot be decoded
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function decode(string $payload)
|
||||
{
|
||||
try {
|
||||
return json_decode($payload, true, 512, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||
} catch (Throwable $throwable) {
|
||||
throw new RuntimeException('Invalid content.', $throwable->getCode(), $throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
113
vendor/web-token/jwt-core/Util/KeyChecker.php
vendored
Normal file
113
vendor/web-token/jwt-core/Util/KeyChecker.php
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Util;
|
||||
|
||||
use function in_array;
|
||||
use InvalidArgumentException;
|
||||
use function is_array;
|
||||
use Jose\Component\Core\JWK;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class KeyChecker
|
||||
{
|
||||
public static function checkKeyUsage(JWK $key, string $usage): void
|
||||
{
|
||||
if ($key->has('use')) {
|
||||
self::checkUsage($key, $usage);
|
||||
}
|
||||
if ($key->has('key_ops')) {
|
||||
self::checkOperation($key, $usage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the key is not suitable for the selected algorithm
|
||||
*/
|
||||
public static function checkKeyAlgorithm(JWK $key, string $algorithm): void
|
||||
{
|
||||
if (!$key->has('alg')) {
|
||||
return;
|
||||
}
|
||||
if ($key->get('alg') !== $algorithm) {
|
||||
throw new InvalidArgumentException(sprintf('Key is only allowed for algorithm "%s".', $key->get('alg')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the key is not suitable for the selected operation
|
||||
*/
|
||||
private static function checkOperation(JWK $key, string $usage): void
|
||||
{
|
||||
$ops = $key->get('key_ops');
|
||||
if (!is_array($ops)) {
|
||||
throw new InvalidArgumentException('Invalid key parameter "key_ops". Should be a list of key operations');
|
||||
}
|
||||
switch ($usage) {
|
||||
case 'verification':
|
||||
if (!in_array('verify', $ops, true)) {
|
||||
throw new InvalidArgumentException('Key cannot be used to verify a signature');
|
||||
}
|
||||
|
||||
break;
|
||||
case 'signature':
|
||||
if (!in_array('sign', $ops, true)) {
|
||||
throw new InvalidArgumentException('Key cannot be used to sign');
|
||||
}
|
||||
|
||||
break;
|
||||
case 'encryption':
|
||||
if (!in_array('encrypt', $ops, true) && !in_array('wrapKey', $ops, true) && !in_array('deriveKey', $ops, true)) {
|
||||
throw new InvalidArgumentException('Key cannot be used to encrypt');
|
||||
}
|
||||
|
||||
break;
|
||||
case 'decryption':
|
||||
if (!in_array('decrypt', $ops, true) && !in_array('unwrapKey', $ops, true) && !in_array('deriveBits', $ops, true)) {
|
||||
throw new InvalidArgumentException('Key cannot be used to decrypt');
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported key usage.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if the key is not suitable for the selected operation
|
||||
*/
|
||||
private static function checkUsage(JWK $key, string $usage): void
|
||||
{
|
||||
$use = $key->get('use');
|
||||
switch ($usage) {
|
||||
case 'verification':
|
||||
case 'signature':
|
||||
if ('sig' !== $use) {
|
||||
throw new InvalidArgumentException('Key cannot be used to sign or verify a signature.');
|
||||
}
|
||||
|
||||
break;
|
||||
case 'encryption':
|
||||
case 'decryption':
|
||||
if ('enc' !== $use) {
|
||||
throw new InvalidArgumentException('Key cannot be used to encrypt or decrypt.');
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException('Unsupported key usage.');
|
||||
}
|
||||
}
|
||||
}
|
||||
310
vendor/web-token/jwt-core/Util/RSAKey.php
vendored
Normal file
310
vendor/web-token/jwt-core/Util/RSAKey.php
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2020 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\Util;
|
||||
|
||||
use function array_key_exists;
|
||||
use Base64Url\Base64Url;
|
||||
use function count;
|
||||
use FG\ASN1\Universal\BitString;
|
||||
use FG\ASN1\Universal\Integer;
|
||||
use FG\ASN1\Universal\NullObject;
|
||||
use FG\ASN1\Universal\ObjectIdentifier;
|
||||
use FG\ASN1\Universal\OctetString;
|
||||
use FG\ASN1\Universal\Sequence;
|
||||
use Jose\Component\Core\JWK;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class RSAKey
|
||||
{
|
||||
/**
|
||||
* @var Sequence
|
||||
*/
|
||||
private $sequence;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $private;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $values;
|
||||
|
||||
/**
|
||||
* @var BigInteger
|
||||
*/
|
||||
private $modulus;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $modulus_length;
|
||||
|
||||
/**
|
||||
* @var BigInteger
|
||||
*/
|
||||
private $public_exponent;
|
||||
|
||||
/**
|
||||
* @var null|BigInteger
|
||||
*/
|
||||
private $private_exponent;
|
||||
|
||||
/**
|
||||
* @var BigInteger[]
|
||||
*/
|
||||
private $primes = [];
|
||||
|
||||
/**
|
||||
* @var BigInteger[]
|
||||
*/
|
||||
private $exponents = [];
|
||||
|
||||
/**
|
||||
* @var null|BigInteger
|
||||
*/
|
||||
private $coefficient;
|
||||
|
||||
private function __construct(JWK $data)
|
||||
{
|
||||
$this->values = $data->all();
|
||||
$this->populateBigIntegers();
|
||||
$this->private = array_key_exists('d', $this->values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RSAKey
|
||||
*/
|
||||
public static function createFromJWK(JWK $jwk): self
|
||||
{
|
||||
return new self($jwk);
|
||||
}
|
||||
|
||||
public function getModulus(): BigInteger
|
||||
{
|
||||
return $this->modulus;
|
||||
}
|
||||
|
||||
public function getModulusLength(): int
|
||||
{
|
||||
return $this->modulus_length;
|
||||
}
|
||||
|
||||
public function getExponent(): BigInteger
|
||||
{
|
||||
$d = $this->getPrivateExponent();
|
||||
if (null !== $d) {
|
||||
return $d;
|
||||
}
|
||||
|
||||
return $this->getPublicExponent();
|
||||
}
|
||||
|
||||
public function getPublicExponent(): BigInteger
|
||||
{
|
||||
return $this->public_exponent;
|
||||
}
|
||||
|
||||
public function getPrivateExponent(): ?BigInteger
|
||||
{
|
||||
return $this->private_exponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger[]
|
||||
*/
|
||||
public function getPrimes(): array
|
||||
{
|
||||
return $this->primes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger[]
|
||||
*/
|
||||
public function getExponents(): array
|
||||
{
|
||||
return $this->exponents;
|
||||
}
|
||||
|
||||
public function getCoefficient(): ?BigInteger
|
||||
{
|
||||
return $this->coefficient;
|
||||
}
|
||||
|
||||
public function isPublic(): bool
|
||||
{
|
||||
return !array_key_exists('d', $this->values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RSAKey $private
|
||||
*
|
||||
* @return RSAKey
|
||||
*/
|
||||
public static function toPublic(self $private): self
|
||||
{
|
||||
$data = $private->toArray();
|
||||
$keys = ['p', 'd', 'q', 'dp', 'dq', 'qi'];
|
||||
foreach ($keys as $key) {
|
||||
if (array_key_exists($key, $data)) {
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return new self(new JWK($data));
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
public function toPEM(): string
|
||||
{
|
||||
if (null === $this->sequence) {
|
||||
$this->sequence = new Sequence();
|
||||
if (array_key_exists('d', $this->values)) {
|
||||
$this->initPrivateKey();
|
||||
} else {
|
||||
$this->initPublicKey();
|
||||
}
|
||||
}
|
||||
$result = '-----BEGIN '.($this->private ? 'RSA PRIVATE' : 'PUBLIC').' KEY-----'.PHP_EOL;
|
||||
$result .= chunk_split(base64_encode($this->sequence->getBinary()), 64, PHP_EOL);
|
||||
$result .= '-----END '.($this->private ? 'RSA PRIVATE' : 'PUBLIC').' KEY-----'.PHP_EOL;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exponentiate with or without Chinese Remainder Theorem.
|
||||
* Operation with primes 'p' and 'q' is appox. 2x faster.
|
||||
*
|
||||
* @param RSAKey $key
|
||||
*
|
||||
* @throws RuntimeException if the exponentiation cannot be achieved
|
||||
*/
|
||||
public static function exponentiate(self $key, BigInteger $c): BigInteger
|
||||
{
|
||||
if ($c->compare(BigInteger::createFromDecimal(0)) < 0 || $c->compare($key->getModulus()) > 0) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if ($key->isPublic() || null === $key->getCoefficient() || 0 === count($key->getPrimes()) || 0 === count($key->getExponents())) {
|
||||
return $c->modPow($key->getExponent(), $key->getModulus());
|
||||
}
|
||||
|
||||
$p = $key->getPrimes()[0];
|
||||
$q = $key->getPrimes()[1];
|
||||
$dP = $key->getExponents()[0];
|
||||
$dQ = $key->getExponents()[1];
|
||||
$qInv = $key->getCoefficient();
|
||||
|
||||
$m1 = $c->modPow($dP, $p);
|
||||
$m2 = $c->modPow($dQ, $q);
|
||||
$h = $qInv->multiply($m1->subtract($m2)->add($p))->mod($p);
|
||||
|
||||
return $m2->add($h->multiply($q));
|
||||
}
|
||||
|
||||
private function populateBigIntegers(): void
|
||||
{
|
||||
$this->modulus = $this->convertBase64StringToBigInteger($this->values['n']);
|
||||
$this->modulus_length = mb_strlen($this->getModulus()->toBytes(), '8bit');
|
||||
$this->public_exponent = $this->convertBase64StringToBigInteger($this->values['e']);
|
||||
|
||||
if (!$this->isPublic()) {
|
||||
$this->private_exponent = $this->convertBase64StringToBigInteger($this->values['d']);
|
||||
|
||||
if (array_key_exists('p', $this->values) && array_key_exists('q', $this->values)) {
|
||||
$this->primes = [
|
||||
$this->convertBase64StringToBigInteger($this->values['p']),
|
||||
$this->convertBase64StringToBigInteger($this->values['q']),
|
||||
];
|
||||
if (array_key_exists('dp', $this->values) && array_key_exists('dq', $this->values) && array_key_exists('qi', $this->values)) {
|
||||
$this->exponents = [
|
||||
$this->convertBase64StringToBigInteger($this->values['dp']),
|
||||
$this->convertBase64StringToBigInteger($this->values['dq']),
|
||||
];
|
||||
$this->coefficient = $this->convertBase64StringToBigInteger($this->values['qi']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function convertBase64StringToBigInteger(string $value): BigInteger
|
||||
{
|
||||
return BigInteger::createFromBinaryString(Base64Url::decode($value));
|
||||
}
|
||||
|
||||
private function initPublicKey(): void
|
||||
{
|
||||
$oid_sequence = new Sequence();
|
||||
$oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1'));
|
||||
$oid_sequence->addChild(new NullObject());
|
||||
$this->sequence->addChild($oid_sequence);
|
||||
$n = new Integer($this->fromBase64ToInteger($this->values['n']));
|
||||
$e = new Integer($this->fromBase64ToInteger($this->values['e']));
|
||||
$key_sequence = new Sequence();
|
||||
$key_sequence->addChild($n);
|
||||
$key_sequence->addChild($e);
|
||||
$key_bit_string = new BitString(bin2hex($key_sequence->getBinary()));
|
||||
$this->sequence->addChild($key_bit_string);
|
||||
}
|
||||
|
||||
private function initPrivateKey(): void
|
||||
{
|
||||
$this->sequence->addChild(new Integer(0));
|
||||
$oid_sequence = new Sequence();
|
||||
$oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1'));
|
||||
$oid_sequence->addChild(new NullObject());
|
||||
$this->sequence->addChild($oid_sequence);
|
||||
$v = new Integer(0);
|
||||
$n = new Integer($this->fromBase64ToInteger($this->values['n']));
|
||||
$e = new Integer($this->fromBase64ToInteger($this->values['e']));
|
||||
$d = new Integer($this->fromBase64ToInteger($this->values['d']));
|
||||
$p = new Integer($this->fromBase64ToInteger($this->values['p']));
|
||||
$q = new Integer($this->fromBase64ToInteger($this->values['q']));
|
||||
$dp = array_key_exists('dp', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dp'])) : new Integer(0);
|
||||
$dq = array_key_exists('dq', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dq'])) : new Integer(0);
|
||||
$qi = array_key_exists('qi', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['qi'])) : new Integer(0);
|
||||
$key_sequence = new Sequence();
|
||||
$key_sequence->addChild($v);
|
||||
$key_sequence->addChild($n);
|
||||
$key_sequence->addChild($e);
|
||||
$key_sequence->addChild($d);
|
||||
$key_sequence->addChild($p);
|
||||
$key_sequence->addChild($q);
|
||||
$key_sequence->addChild($dp);
|
||||
$key_sequence->addChild($dq);
|
||||
$key_sequence->addChild($qi);
|
||||
$key_octet_string = new OctetString(bin2hex($key_sequence->getBinary()));
|
||||
$this->sequence->addChild($key_octet_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function fromBase64ToInteger($value)
|
||||
{
|
||||
$hex = current(unpack('H*', Base64Url::decode($value)));
|
||||
|
||||
return \Brick\Math\BigInteger::fromBase($hex, 16)->toBase(10);
|
||||
}
|
||||
}
|
||||
49
vendor/web-token/jwt-core/composer.json
vendored
Normal file
49
vendor/web-token/jwt-core/composer.json
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "web-token/jwt-core",
|
||||
"description": "Core component of the JWT Framework.",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"keywords": ["JWS", "JWT", "JWE", "JWA", "JWK", "JWKSet", "Jot", "Jose", "RFC7515", "RFC7516", "RFC7517", "RFC7518", "RFC7519", "RFC7520", "Bundle", "Symfony"],
|
||||
"homepage": "https://github.com/web-token",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Florent Morselli",
|
||||
"homepage": "https://github.com/Spomky"
|
||||
},{
|
||||
"name": "All contributors",
|
||||
"homepage": "https://github.com/web-token/jwt-framework/contributors"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Jose\\Component\\Core\\": ""
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"brick/math": "^0.8.17|^0.9",
|
||||
"fgrosse/phpasn1": "^2.0",
|
||||
"spomky-labs/base64url": "^1.0|^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"spomky-labs/jose": "*"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"v1.0": "1.0.x-dev",
|
||||
"v1.1": "1.1.x-dev",
|
||||
"v1.2": "1.2.x-dev",
|
||||
"v1.3": "1.3.x-dev",
|
||||
"v2.0": "2.0.x-dev",
|
||||
"v2.1": "2.1.x-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
29
vendor/web-token/jwt-core/phpunit.xml.dist
vendored
Normal file
29
vendor/web-token/jwt-core/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true">
|
||||
<testsuites>
|
||||
<testsuite name="Test Suite">
|
||||
<directory>./Tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./</directory>
|
||||
<exclude>
|
||||
<directory>./vendor</directory>
|
||||
<directory>./Tests</directory>
|
||||
<directory suffix="Test.php">./src</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
Reference in New Issue
Block a user