updated plugin WP-WebAuthn version 1.3.1

This commit is contained in:
2023-10-22 22:21:36 +00:00
committed by Gitium
parent 959829cf69
commit c7746517a0
931 changed files with 5408 additions and 1937 deletions

View File

@ -0,0 +1,145 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2021 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Cose\Key;
use function array_key_exists;
use Assert\Assertion;
use FG\ASN1\ExplicitlyTaggedObject;
use FG\ASN1\Universal\BitString;
use FG\ASN1\Universal\Integer;
use FG\ASN1\Universal\ObjectIdentifier;
use FG\ASN1\Universal\OctetString;
use FG\ASN1\Universal\Sequence;
class Ec2Key extends Key
{
public const CURVE_P256 = 1;
public const CURVE_P256K = 8;
public const CURVE_P384 = 2;
public const CURVE_P521 = 3;
public const DATA_CURVE = -1;
public const DATA_X = -2;
public const DATA_Y = -3;
public const DATA_D = -4;
private const SUPPORTED_CURVES = [
self::CURVE_P256,
self::CURVE_P256K,
self::CURVE_P384,
self::CURVE_P521,
];
private const NAMED_CURVE_OID = [
self::CURVE_P256 => '1.2.840.10045.3.1.7', // NIST P-256 / secp256r1
self::CURVE_P256K => '1.3.132.0.10', // NIST P-256K / secp256k1
self::CURVE_P384 => '1.3.132.0.34', // NIST P-384 / secp384r1
self::CURVE_P521 => '1.3.132.0.35', // NIST P-521 / secp521r1
];
private const CURVE_KEY_LENGTH = [
self::CURVE_P256 => 32,
self::CURVE_P256K => 32,
self::CURVE_P384 => 48,
self::CURVE_P521 => 66,
];
public function __construct(array $data)
{
parent::__construct($data);
Assertion::eq($data[self::TYPE], self::TYPE_EC2, 'Invalid EC2 key. The key type does not correspond to an EC2 key');
Assertion::keyExists($data, self::DATA_CURVE, 'Invalid EC2 key. The curve is missing');
Assertion::keyExists($data, self::DATA_X, 'Invalid EC2 key. The x coordinate is missing');
Assertion::keyExists($data, self::DATA_Y, 'Invalid EC2 key. The y coordinate is missing');
Assertion::length($data[self::DATA_X], self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]], 'Invalid length for x coordinate', null, '8bit');
Assertion::length($data[self::DATA_Y], self::CURVE_KEY_LENGTH[$data[self::DATA_CURVE]], 'Invalid length for y coordinate', null, '8bit');
Assertion::inArray((int) $data[self::DATA_CURVE], self::SUPPORTED_CURVES, 'The curve is not supported');
}
public function toPublic(): self
{
$data = $this->getData();
unset($data[self::DATA_D]);
return new self($data);
}
public function x(): string
{
return $this->get(self::DATA_X);
}
public function y(): string
{
return $this->get(self::DATA_Y);
}
public function isPrivate(): bool
{
return array_key_exists(self::DATA_D, $this->getData());
}
public function d(): string
{
Assertion::true($this->isPrivate(), 'The key is not private');
return $this->get(self::DATA_D);
}
public function curve(): int
{
return (int) $this->get(self::DATA_CURVE);
}
public function asPEM(): string
{
if ($this->isPrivate()) {
$der = new Sequence(
new Integer(1),
new OctetString(bin2hex($this->d())),
new ExplicitlyTaggedObject(0, new ObjectIdentifier($this->getCurveOid())),
new ExplicitlyTaggedObject(1, new BitString(bin2hex($this->getUncompressedCoordinates())))
);
return $this->pem('EC PRIVATE KEY', $der->getBinary());
}
$der = new Sequence(
new Sequence(
new ObjectIdentifier('1.2.840.10045.2.1'),
new ObjectIdentifier($this->getCurveOid())
),
new BitString(bin2hex($this->getUncompressedCoordinates()))
);
return $this->pem('PUBLIC KEY', $der->getBinary());
}
public function getUncompressedCoordinates(): string
{
return "\x04".$this->x().$this->y();
}
private function getCurveOid(): string
{
return self::NAMED_CURVE_OID[$this->curve()];
}
private function pem(string $type, string $der): string
{
return sprintf("-----BEGIN %s-----\n", mb_strtoupper($type)).
chunk_split(base64_encode($der), 64, "\n").
sprintf("-----END %s-----\n", mb_strtoupper($type));
}
}

View File

@ -0,0 +1,91 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2021 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Cose\Key;
use function array_key_exists;
use Assert\Assertion;
class Key
{
public const TYPE = 1;
public const TYPE_OKP = 1;
public const TYPE_EC2 = 2;
public const TYPE_RSA = 3;
public const TYPE_OCT = 4;
public const KID = 2;
public const ALG = 3;
public const KEY_OPS = 4;
public const BASE_IV = 5;
/**
* @var array
*/
private $data;
public function __construct(array $data)
{
Assertion::keyExists($data, self::TYPE, 'Invalid key: the type is not defined');
$this->data = $data;
}
public static function createFromData(array $data): self
{
Assertion::keyExists($data, self::TYPE, 'Invalid key: the type is not defined');
switch ($data[self::TYPE]) {
case 1:
return new OkpKey($data);
case 2:
return new Ec2Key($data);
case 3:
return new RsaKey($data);
case 4:
return new SymmetricKey($data);
default:
return new self($data);
}
}
/**
* @return int|string
*/
public function type()
{
return $this->data[self::TYPE];
}
public function alg(): int
{
return (int) $this->get(self::ALG);
}
public function getData(): array
{
return $this->data;
}
public function has(int $key): bool
{
return array_key_exists($key, $this->data);
}
/**
* @return mixed
*/
public function get(int $key)
{
Assertion::keyExists($this->data, $key, sprintf('The key has no data at index %d', $key));
return $this->data[$key];
}
}

View File

@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2021 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Cose\Key;
use function array_key_exists;
use Assert\Assertion;
class OkpKey extends Key
{
public const CURVE_X25519 = 4;
public const CURVE_X448 = 5;
public const CURVE_ED25519 = 6;
public const CURVE_ED448 = 7;
public const DATA_CURVE = -1;
public const DATA_X = -2;
public const DATA_D = -4;
private const SUPPORTED_CURVES = [
self::CURVE_X25519,
self::CURVE_X448,
self::CURVE_ED25519,
self::CURVE_ED448,
];
public function __construct(array $data)
{
parent::__construct($data);
Assertion::eq($data[self::TYPE], self::TYPE_OKP, 'Invalid OKP key. The key type does not correspond to an OKP key');
Assertion::keyExists($data, self::DATA_CURVE, 'Invalid EC2 key. The curve is missing');
Assertion::keyExists($data, self::DATA_X, 'Invalid OKP key. The x coordinate is missing');
Assertion::inArray((int) $data[self::DATA_CURVE], self::SUPPORTED_CURVES, 'The curve is not supported');
}
public function x(): string
{
return $this->get(self::DATA_X);
}
public function isPrivate(): bool
{
return array_key_exists(self::DATA_D, $this->getData());
}
public function d(): string
{
Assertion::true($this->isPrivate(), 'The key is not private');
return $this->get(self::DATA_D);
}
public function curve(): int
{
return (int) $this->get(self::DATA_CURVE);
}
}

View File

@ -0,0 +1,207 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2021 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Cose\Key;
use function array_key_exists;
use Assert\Assertion;
use Brick\Math\BigInteger;
use FG\ASN1\Universal\BitString;
use FG\ASN1\Universal\Integer;
use FG\ASN1\Universal\NullObject;
use FG\ASN1\Universal\ObjectIdentifier;
use FG\ASN1\Universal\Sequence;
use InvalidArgumentException;
class RsaKey extends Key
{
public const DATA_N = -1;
public const DATA_E = -2;
public const DATA_D = -3;
public const DATA_P = -4;
public const DATA_Q = -5;
public const DATA_DP = -6;
public const DATA_DQ = -7;
public const DATA_QI = -8;
public const DATA_OTHER = -9;
public const DATA_RI = -10;
public const DATA_DI = -11;
public const DATA_TI = -12;
public function __construct(array $data)
{
parent::__construct($data);
Assertion::eq($data[self::TYPE], self::TYPE_RSA, 'Invalid RSA key. The key type does not correspond to a RSA key');
Assertion::keyExists($data, self::DATA_N, 'Invalid RSA key. The modulus is missing');
Assertion::keyExists($data, self::DATA_E, 'Invalid RSA key. The exponent is missing');
}
public function n(): string
{
return $this->get(self::DATA_N);
}
public function e(): string
{
return $this->get(self::DATA_E);
}
public function d(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_D);
}
public function p(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_P);
}
public function q(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_Q);
}
public function dP(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_DP);
}
public function dQ(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_DQ);
}
public function QInv(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_QI);
}
public function other(): array
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_OTHER);
}
public function rI(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_RI);
}
public function dI(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_DI);
}
public function tI(): string
{
Assertion::true($this->isPrivate(), 'The key is not private.');
return $this->get(self::DATA_TI);
}
public function hasPrimes(): bool
{
return $this->has(self::DATA_P) && $this->has(self::DATA_Q);
}
public function primes(): array
{
return [
$this->p(),
$this->q(),
];
}
public function hasExponents(): bool
{
return $this->has(self::DATA_DP) && $this->has(self::DATA_DQ);
}
public function exponents(): array
{
return [
$this->dP(),
$this->dQ(),
];
}
public function hasCoefficient(): bool
{
return $this->has(self::DATA_QI);
}
public function isPublic(): bool
{
return !$this->isPrivate();
}
public function isPrivate(): bool
{
return array_key_exists(self::DATA_D, $this->getData());
}
public function asPem(): string
{
Assertion::false($this->isPrivate(), 'Unsupported for private keys.');
$bitSring = new Sequence(
new Integer($this->fromBase64ToInteger($this->n())),
new Integer($this->fromBase64ToInteger($this->e()))
);
$der = new Sequence(
new Sequence(
new ObjectIdentifier('1.2.840.113549.1.1.1'),
new NullObject()
),
new BitString(bin2hex($bitSring->getBinary()))
);
return $this->pem('PUBLIC KEY', $der->getBinary());
}
private function fromBase64ToInteger(string $value): string
{
$data = unpack('H*', $value);
if (false === $data) {
throw new InvalidArgumentException('Unable to convert to an integer');
}
$hex = current($data);
return BigInteger::fromBase($hex, 16)->toBase(10);
}
private function pem(string $type, string $der): string
{
return sprintf("-----BEGIN %s-----\n", mb_strtoupper($type)).
chunk_split(base64_encode($der), 64, "\n").
sprintf("-----END %s-----\n", mb_strtoupper($type));
}
}

View File

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2021 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Cose\Key;
use Assert\Assertion;
class SymmetricKey extends Key
{
public const DATA_K = -1;
public function __construct(array $data)
{
parent::__construct($data);
Assertion::eq($data[self::TYPE], self::TYPE_OCT, 'Invalid symmetric key. The key type does not correspond to a symmetric key');
Assertion::keyExists($data, self::DATA_K, 'Invalid symmetric key. The parameter "k" is missing');
}
public function k(): string
{
return $this->get(self::DATA_K);
}
}