diff options
Diffstat (limited to 'vendor/web-token/jwt-util-ecc/Curve.php')
-rw-r--r-- | vendor/web-token/jwt-util-ecc/Curve.php | 630 |
1 files changed, 315 insertions, 315 deletions
diff --git a/vendor/web-token/jwt-util-ecc/Curve.php b/vendor/web-token/jwt-util-ecc/Curve.php index 8c7d07d..d688598 100644 --- a/vendor/web-token/jwt-util-ecc/Curve.php +++ b/vendor/web-token/jwt-util-ecc/Curve.php @@ -1,315 +1,315 @@ -<?php - -declare(strict_types=1); - -/* - * The MIT License (MIT) - * - * Copyright (c) 2014-2018 Spomky-Labs - * - * This software may be modified and distributed under the terms - * of the MIT license. See the LICENSE file for details. - */ - -namespace Jose\Component\Core\Util\Ecc; - -/** - * @internal - */ -class Curve -{ - /** - * Elliptic curve over the field of integers modulo a prime. - * - * @var \GMP - */ - private $a; - - /** - * @var \GMP - */ - private $b; - - /** - * @var \GMP - */ - private $prime; - - /** - * Binary length of keys associated with these curve parameters. - * - * @var int - */ - private $size; - - /** - * @var Point - */ - private $generator; - - public function __construct(int $size, \GMP $prime, \GMP $a, \GMP $b, Point $generator) - { - $this->size = $size; - $this->prime = $prime; - $this->a = $a; - $this->b = $b; - $this->generator = $generator; - } - - public function getA(): \GMP - { - return $this->a; - } - - public function getB(): \GMP - { - return $this->b; - } - - public function getPrime(): \GMP - { - return $this->prime; - } - - public function getSize(): int - { - return $this->size; - } - - public function getPoint(\GMP $x, \GMP $y, ?\GMP $order = null): Point - { - if (!$this->contains($x, $y)) { - throw new \RuntimeException('Curve '.$this->__toString().' does not contain point ('.Math::toString($x).', '.Math::toString($y).')'); - } - $point = Point::create($x, $y, $order); - if (!\is_null($order)) { - $mul = $this->mul($point, $order); - if (!$mul->isInfinity()) { - throw new \RuntimeException('SELF * ORDER MUST EQUAL INFINITY. ('.(string) $mul.' found instead)'); - } - } - - return $point; - } - - public function getPublicKeyFrom(\GMP $x, \GMP $y): PublicKey - { - $zero = \gmp_init(0, 10); - if (Math::cmp($x, $zero) < 0 || Math::cmp($this->generator->getOrder(), $x) <= 0 || Math::cmp($y, $zero) < 0 || Math::cmp($this->generator->getOrder(), $y) <= 0) { - throw new \RuntimeException('Generator point has x and y out of range.'); - } - $point = $this->getPoint($x, $y); - - return PublicKey::create($point); - } - - public function contains(\GMP $x, \GMP $y): bool - { - $eq_zero = Math::equals( - ModularArithmetic::sub( - Math::pow($y, 2), - Math::add( - Math::add( - Math::pow($x, 3), - Math::mul($this->getA(), $x) - ), - $this->getB() - ), - $this->getPrime() - ), - \gmp_init(0, 10) - ); - - return $eq_zero; - } - - public function add(Point $one, Point $two): Point - { - if ($two->isInfinity()) { - return clone $one; - } - - if ($one->isInfinity()) { - return clone $two; - } - - if (Math::equals($two->getX(), $one->getX())) { - if (Math::equals($two->getY(), $one->getY())) { - return $this->getDouble($one); - } else { - return Point::infinity(); - } - } - - $slope = ModularArithmetic::div( - Math::sub($two->getY(), $one->getY()), - Math::sub($two->getX(), $one->getX()), - $this->getPrime() - ); - - $xR = ModularArithmetic::sub( - Math::sub(Math::pow($slope, 2), $one->getX()), - $two->getX(), - $this->getPrime() - ); - - $yR = ModularArithmetic::sub( - Math::mul($slope, Math::sub($one->getX(), $xR)), - $one->getY(), - $this->getPrime() - ); - - return $this->getPoint($xR, $yR, $one->getOrder()); - } - - public function mul(Point $one, \GMP $n): Point - { - if ($one->isInfinity()) { - return Point::infinity(); - } - - /** @var \GMP $zero */ - $zero = \gmp_init(0, 10); - if (Math::cmp($one->getOrder(), $zero) > 0) { - $n = Math::mod($n, $one->getOrder()); - } - - if (Math::equals($n, $zero)) { - return Point::infinity(); - } - - /** @var Point[] $r */ - $r = [ - Point::infinity(), - clone $one, - ]; - - $k = $this->getSize(); - $n = \str_pad(Math::baseConvert(Math::toString($n), 10, 2), $k, '0', STR_PAD_LEFT); - - for ($i = 0; $i < $k; ++$i) { - $j = $n[$i]; - Point::cswap($r[0], $r[1], $j ^ 1); - $r[0] = $this->add($r[0], $r[1]); - $r[1] = $this->getDouble($r[1]); - Point::cswap($r[0], $r[1], $j ^ 1); - } - - $this->validate($r[0]); - - return $r[0]; - } - - /** - * @param Curve $other - */ - public function cmp(self $other): int - { - $equal = Math::equals($this->getA(), $other->getA()); - $equal &= Math::equals($this->getB(), $other->getB()); - $equal &= Math::equals($this->getPrime(), $other->getPrime()); - - return $equal ? 0 : 1; - } - - /** - * @param Curve $other - */ - public function equals(self $other): bool - { - return 0 === $this->cmp($other); - } - - public function __toString(): string - { - return 'curve('.Math::toString($this->getA()).', '.Math::toString($this->getB()).', '.Math::toString($this->getPrime()).')'; - } - - private function validate(Point $point) - { - if (!$point->isInfinity() && !$this->contains($point->getX(), $point->getY())) { - throw new \RuntimeException('Invalid point'); - } - } - - public function getDouble(Point $point): Point - { - if ($point->isInfinity()) { - return Point::infinity(); - } - - $a = $this->getA(); - $threeX2 = Math::mul(\gmp_init(3, 10), Math::pow($point->getX(), 2)); - - $tangent = ModularArithmetic::div( - Math::add($threeX2, $a), - Math::mul(\gmp_init(2, 10), $point->getY()), - $this->getPrime() - ); - - $x3 = ModularArithmetic::sub( - Math::pow($tangent, 2), - Math::mul(\gmp_init(2, 10), $point->getX()), - $this->getPrime() - ); - - $y3 = ModularArithmetic::sub( - Math::mul($tangent, Math::sub($point->getX(), $x3)), - $point->getY(), - $this->getPrime() - ); - - return $this->getPoint($x3, $y3, $point->getOrder()); - } - - public function createPrivateKey(): PrivateKey - { - return PrivateKey::create($this->generate()); - } - - public function createPublicKey(PrivateKey $privateKey): PublicKey - { - $point = $this->mul($this->generator, $privateKey->getSecret()); - - return PublicKey::create($point); - } - - private function generate(): \GMP - { - $max = $this->generator->getOrder(); - $numBits = $this->bnNumBits($max); - $numBytes = (int) \ceil($numBits / 8); - // Generate an integer of size >= $numBits - $bytes = \random_bytes($numBytes); - $value = Math::stringToInt($bytes); - $mask = \gmp_sub(\gmp_pow(2, $numBits), 1); - $integer = \gmp_and($value, $mask); - - return $integer; - } - - /** - * Returns the number of bits used to store this number. Non-significant upper bits are not counted. - * - * @see https://www.openssl.org/docs/crypto/BN_num_bytes.html - */ - private function bnNumBits(\GMP $x): int - { - $zero = \gmp_init(0, 10); - if (Math::equals($x, $zero)) { - return 0; - } - $log2 = 0; - while (false === Math::equals($x, $zero)) { - $x = Math::rightShift($x, 1); - ++$log2; - } - - return $log2; - } - - public function getGenerator(): Point - { - return $this->generator; - } -} +<?php
+
+declare(strict_types=1);
+
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2018 Spomky-Labs
+ *
+ * This software may be modified and distributed under the terms
+ * of the MIT license. See the LICENSE file for details.
+ */
+
+namespace Jose\Component\Core\Util\Ecc;
+
+/**
+ * @internal
+ */
+class Curve
+{
+ /**
+ * Elliptic curve over the field of integers modulo a prime.
+ *
+ * @var \GMP
+ */
+ private $a;
+
+ /**
+ * @var \GMP
+ */
+ private $b;
+
+ /**
+ * @var \GMP
+ */
+ private $prime;
+
+ /**
+ * Binary length of keys associated with these curve parameters.
+ *
+ * @var int
+ */
+ private $size;
+
+ /**
+ * @var Point
+ */
+ private $generator;
+
+ public function __construct(int $size, \GMP $prime, \GMP $a, \GMP $b, Point $generator)
+ {
+ $this->size = $size;
+ $this->prime = $prime;
+ $this->a = $a;
+ $this->b = $b;
+ $this->generator = $generator;
+ }
+
+ public function getA(): \GMP
+ {
+ return $this->a;
+ }
+
+ public function getB(): \GMP
+ {
+ return $this->b;
+ }
+
+ public function getPrime(): \GMP
+ {
+ return $this->prime;
+ }
+
+ public function getSize(): int
+ {
+ return $this->size;
+ }
+
+ public function getPoint(\GMP $x, \GMP $y, ?\GMP $order = null): Point
+ {
+ if (!$this->contains($x, $y)) {
+ throw new \RuntimeException('Curve '.$this->__toString().' does not contain point ('.Math::toString($x).', '.Math::toString($y).')');
+ }
+ $point = Point::create($x, $y, $order);
+ if (!\is_null($order)) {
+ $mul = $this->mul($point, $order);
+ if (!$mul->isInfinity()) {
+ throw new \RuntimeException('SELF * ORDER MUST EQUAL INFINITY. ('.(string) $mul.' found instead)');
+ }
+ }
+
+ return $point;
+ }
+
+ public function getPublicKeyFrom(\GMP $x, \GMP $y): PublicKey
+ {
+ $zero = \gmp_init(0, 10);
+ if (Math::cmp($x, $zero) < 0 || Math::cmp($this->generator->getOrder(), $x) <= 0 || Math::cmp($y, $zero) < 0 || Math::cmp($this->generator->getOrder(), $y) <= 0) {
+ throw new \RuntimeException('Generator point has x and y out of range.');
+ }
+ $point = $this->getPoint($x, $y);
+
+ return PublicKey::create($point);
+ }
+
+ public function contains(\GMP $x, \GMP $y): bool
+ {
+ $eq_zero = Math::equals(
+ ModularArithmetic::sub(
+ Math::pow($y, 2),
+ Math::add(
+ Math::add(
+ Math::pow($x, 3),
+ Math::mul($this->getA(), $x)
+ ),
+ $this->getB()
+ ),
+ $this->getPrime()
+ ),
+ \gmp_init(0, 10)
+ );
+
+ return $eq_zero;
+ }
+
+ public function add(Point $one, Point $two): Point
+ {
+ if ($two->isInfinity()) {
+ return clone $one;
+ }
+
+ if ($one->isInfinity()) {
+ return clone $two;
+ }
+
+ if (Math::equals($two->getX(), $one->getX())) {
+ if (Math::equals($two->getY(), $one->getY())) {
+ return $this->getDouble($one);
+ } else {
+ return Point::infinity();
+ }
+ }
+
+ $slope = ModularArithmetic::div(
+ Math::sub($two->getY(), $one->getY()),
+ Math::sub($two->getX(), $one->getX()),
+ $this->getPrime()
+ );
+
+ $xR = ModularArithmetic::sub(
+ Math::sub(Math::pow($slope, 2), $one->getX()),
+ $two->getX(),
+ $this->getPrime()
+ );
+
+ $yR = ModularArithmetic::sub(
+ Math::mul($slope, Math::sub($one->getX(), $xR)),
+ $one->getY(),
+ $this->getPrime()
+ );
+
+ return $this->getPoint($xR, $yR, $one->getOrder());
+ }
+
+ public function mul(Point $one, \GMP $n): Point
+ {
+ if ($one->isInfinity()) {
+ return Point::infinity();
+ }
+
+ /** @var \GMP $zero */
+ $zero = \gmp_init(0, 10);
+ if (Math::cmp($one->getOrder(), $zero) > 0) {
+ $n = Math::mod($n, $one->getOrder());
+ }
+
+ if (Math::equals($n, $zero)) {
+ return Point::infinity();
+ }
+
+ /** @var Point[] $r */
+ $r = [
+ Point::infinity(),
+ clone $one,
+ ];
+
+ $k = $this->getSize();
+ $n = \str_pad(Math::baseConvert(Math::toString($n), 10, 2), $k, '0', STR_PAD_LEFT);
+
+ for ($i = 0; $i < $k; ++$i) {
+ $j = $n[$i];
+ Point::cswap($r[0], $r[1], $j ^ 1);
+ $r[0] = $this->add($r[0], $r[1]);
+ $r[1] = $this->getDouble($r[1]);
+ Point::cswap($r[0], $r[1], $j ^ 1);
+ }
+
+ $this->validate($r[0]);
+
+ return $r[0];
+ }
+
+ /**
+ * @param Curve $other
+ */
+ public function cmp(self $other): int
+ {
+ $equal = Math::equals($this->getA(), $other->getA());
+ $equal &= Math::equals($this->getB(), $other->getB());
+ $equal &= Math::equals($this->getPrime(), $other->getPrime());
+
+ return $equal ? 0 : 1;
+ }
+
+ /**
+ * @param Curve $other
+ */
+ public function equals(self $other): bool
+ {
+ return 0 === $this->cmp($other);
+ }
+
+ public function __toString(): string
+ {
+ return 'curve('.Math::toString($this->getA()).', '.Math::toString($this->getB()).', '.Math::toString($this->getPrime()).')';
+ }
+
+ private function validate(Point $point)
+ {
+ if (!$point->isInfinity() && !$this->contains($point->getX(), $point->getY())) {
+ throw new \RuntimeException('Invalid point');
+ }
+ }
+
+ public function getDouble(Point $point): Point
+ {
+ if ($point->isInfinity()) {
+ return Point::infinity();
+ }
+
+ $a = $this->getA();
+ $threeX2 = Math::mul(\gmp_init(3, 10), Math::pow($point->getX(), 2));
+
+ $tangent = ModularArithmetic::div(
+ Math::add($threeX2, $a),
+ Math::mul(\gmp_init(2, 10), $point->getY()),
+ $this->getPrime()
+ );
+
+ $x3 = ModularArithmetic::sub(
+ Math::pow($tangent, 2),
+ Math::mul(\gmp_init(2, 10), $point->getX()),
+ $this->getPrime()
+ );
+
+ $y3 = ModularArithmetic::sub(
+ Math::mul($tangent, Math::sub($point->getX(), $x3)),
+ $point->getY(),
+ $this->getPrime()
+ );
+
+ return $this->getPoint($x3, $y3, $point->getOrder());
+ }
+
+ public function createPrivateKey(): PrivateKey
+ {
+ return PrivateKey::create($this->generate());
+ }
+
+ public function createPublicKey(PrivateKey $privateKey): PublicKey
+ {
+ $point = $this->mul($this->generator, $privateKey->getSecret());
+
+ return PublicKey::create($point);
+ }
+
+ private function generate(): \GMP
+ {
+ $max = $this->generator->getOrder();
+ $numBits = $this->bnNumBits($max);
+ $numBytes = (int) \ceil($numBits / 8);
+ // Generate an integer of size >= $numBits
+ $bytes = \random_bytes($numBytes);
+ $value = Math::stringToInt($bytes);
+ $mask = \gmp_sub(\gmp_pow(2, $numBits), 1);
+ $integer = \gmp_and($value, $mask);
+
+ return $integer;
+ }
+
+ /**
+ * Returns the number of bits used to store this number. Non-significant upper bits are not counted.
+ *
+ * @see https://www.openssl.org/docs/crypto/BN_num_bytes.html
+ */
+ private function bnNumBits(\GMP $x): int
+ {
+ $zero = \gmp_init(0, 10);
+ if (Math::equals($x, $zero)) {
+ return 0;
+ }
+ $log2 = 0;
+ while (false === Math::equals($x, $zero)) {
+ $x = Math::rightShift($x, 1);
+ ++$log2;
+ }
+
+ return $log2;
+ }
+
+ public function getGenerator(): Point
+ {
+ return $this->generator;
+ }
+}
|