[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/phpseclib/phpseclib/phpseclib/Crypt/ -> EC.php (source)

   1  <?php
   2  
   3  /**
   4   * Pure-PHP implementation of EC.
   5   *
   6   * PHP version 5
   7   *
   8   * Here's an example of how to create signatures and verify signatures with this library:
   9   * <code>
  10   * <?php
  11   * include 'vendor/autoload.php';
  12   *
  13   * $private = \phpseclib3\Crypt\EC::createKey('secp256k1');
  14   * $public = $private->getPublicKey();
  15   *
  16   * $plaintext = 'terrafrost';
  17   *
  18   * $signature = $private->sign($plaintext);
  19   *
  20   * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
  21   * ?>
  22   * </code>
  23   *
  24   * @category  Crypt
  25   * @package   EC
  26   * @author    Jim Wigginton <[email protected]>
  27   * @copyright 2016 Jim Wigginton
  28   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  29   * @link      http://phpseclib.sourceforge.net
  30   */
  31  
  32  namespace phpseclib3\Crypt;
  33  
  34  use phpseclib3\Crypt\Common\AsymmetricKey;
  35  use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
  36  use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
  37  use phpseclib3\Crypt\EC\Curves\Curve25519;
  38  use phpseclib3\Crypt\EC\Curves\Ed25519;
  39  use phpseclib3\Crypt\EC\Curves\Ed448;
  40  use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
  41  use phpseclib3\Crypt\EC\Parameters;
  42  use phpseclib3\Crypt\EC\PrivateKey;
  43  use phpseclib3\Crypt\EC\PublicKey;
  44  use phpseclib3\Exception\UnsupportedAlgorithmException;
  45  use phpseclib3\Exception\UnsupportedCurveException;
  46  use phpseclib3\Exception\UnsupportedOperationException;
  47  use phpseclib3\File\ASN1;
  48  use phpseclib3\File\ASN1\Maps\ECParameters;
  49  use phpseclib3\Math\BigInteger;
  50  
  51  /**
  52   * Pure-PHP implementation of EC.
  53   *
  54   * @package EC
  55   * @author  Jim Wigginton <[email protected]>
  56   * @access  public
  57   */
  58  abstract class EC extends AsymmetricKey
  59  {
  60      /**
  61       * Algorithm Name
  62       *
  63       * @var string
  64       * @access private
  65       */
  66      const ALGORITHM = 'EC';
  67  
  68      /**
  69       * Public Key QA
  70       *
  71       * @var object[]
  72       */
  73      protected $QA;
  74  
  75      /**
  76       * Curve
  77       *
  78       * @var \phpseclib3\Crypt\EC\BaseCurves\Base
  79       */
  80      protected $curve;
  81  
  82      /**
  83       * Signature Format
  84       *
  85       * @var string
  86       * @access private
  87       */
  88      protected $format;
  89  
  90      /**
  91       * Signature Format (Short)
  92       *
  93       * @var string
  94       * @access private
  95       */
  96      protected $shortFormat;
  97  
  98      /**
  99       * Curve Name
 100       *
 101       * @var string
 102       */
 103      private $curveName;
 104  
 105      /**
 106       * Curve Order
 107       *
 108       * Used for deterministic ECDSA
 109       *
 110       * @var \phpseclib3\Math\BigInteger
 111       */
 112      protected $q;
 113  
 114      /**
 115       * Alias for the private key
 116       *
 117       * Used for deterministic ECDSA. AsymmetricKey expects $x. I don't like x because
 118       * with x you have x * the base point yielding an (x, y)-coordinate that is the
 119       * public key. But the x is different depending on which side of the equal sign
 120       * you're on. It's less ambiguous if you do dA * base point = (x, y)-coordinate.
 121       *
 122       * @var \phpseclib3\Math\BigInteger
 123       */
 124      protected $x;
 125  
 126      /**
 127       * Context
 128       *
 129       * @var string
 130       */
 131      protected $context;
 132  
 133      /**
 134       * Create public / private key pair.
 135       *
 136       * @access public
 137       * @param string $curve
 138       * @return \phpseclib3\Crypt\EC\PrivateKey
 139       */
 140      public static function createKey($curve)
 141      {
 142          self::initialize_static_variables();
 143  
 144          if (!isset(self::$engines['PHP'])) {
 145              self::useBestEngine();
 146          }
 147  
 148          $curve = strtolower($curve);
 149          if (self::$engines['libsodium'] && $curve == 'ed25519' && function_exists('sodium_crypto_sign_keypair')) {
 150              $kp = sodium_crypto_sign_keypair();
 151  
 152              $privatekey = EC::loadFormat('libsodium', sodium_crypto_sign_secretkey($kp));
 153              //$publickey = EC::loadFormat('libsodium', sodium_crypto_sign_publickey($kp));
 154  
 155              $privatekey->curveName = 'Ed25519';
 156              //$publickey->curveName = $curve;
 157  
 158              return $privatekey;
 159          }
 160  
 161          $privatekey = new PrivateKey();
 162  
 163          $curveName = $curve;
 164          if (preg_match('#(?:^curve|^ed)\d+$#', $curveName)) {
 165              $curveName = ucfirst($curveName);
 166          } elseif (substr($curveName, 0, 10) == 'brainpoolp') {
 167              $curveName = 'brainpoolP' . substr($curveName, 10);
 168          }
 169          $curve = '\phpseclib3\Crypt\EC\Curves\\' . $curveName;
 170  
 171          if (!class_exists($curve)) {
 172              throw new UnsupportedCurveException('Named Curve of ' . $curveName . ' is not supported');
 173          }
 174  
 175          $reflect = new \ReflectionClass($curve);
 176          $curveName = $reflect->isFinal() ?
 177              $reflect->getParentClass()->getShortName() :
 178              $reflect->getShortName();
 179  
 180          $curve = new $curve();
 181          $privatekey->dA = $dA = $curve->createRandomMultiplier();
 182          if ($curve instanceof Curve25519 && self::$engines['libsodium']) {
 183              //$r = pack('H*', '0900000000000000000000000000000000000000000000000000000000000000');
 184              //$QA = sodium_crypto_scalarmult($dA->toBytes(), $r);
 185              $QA = sodium_crypto_box_publickey_from_secretkey($dA->toBytes());
 186              $privatekey->QA = [$curve->convertInteger(new BigInteger(strrev($QA), 256))];
 187          } else {
 188              $privatekey->QA = $curve->multiplyPoint($curve->getBasePoint(), $dA);
 189          }
 190          $privatekey->curve = $curve;
 191  
 192          //$publickey = clone $privatekey;
 193          //unset($publickey->dA);
 194          //unset($publickey->x);
 195  
 196          $privatekey->curveName = $curveName;
 197          //$publickey->curveName = $curveName;
 198  
 199          if ($privatekey->curve instanceof TwistedEdwardsCurve) {
 200              return $privatekey->withHash($curve::HASH);
 201          }
 202  
 203          return $privatekey;
 204      }
 205  
 206      /**
 207       * OnLoad Handler
 208       *
 209       * @return bool
 210       * @access protected
 211       * @param array $components
 212       */
 213      protected static function onLoad($components)
 214      {
 215          if (!isset(self::$engines['PHP'])) {
 216              self::useBestEngine();
 217          }
 218  
 219          if (!isset($components['dA']) && !isset($components['QA'])) {
 220              $new = new Parameters();
 221              $new->curve = $components['curve'];
 222              return $new;
 223          }
 224  
 225          $new = isset($components['dA']) ?
 226              new PrivateKey() :
 227              new PublicKey();
 228          $new->curve = $components['curve'];
 229          $new->QA = $components['QA'];
 230  
 231          if (isset($components['dA'])) {
 232              $new->dA = $components['dA'];
 233          }
 234  
 235          if ($new->curve instanceof TwistedEdwardsCurve) {
 236              return $new->withHash($components['curve']::HASH);
 237          }
 238  
 239          return $new;
 240      }
 241  
 242      /**
 243       * Constructor
 244       *
 245       * PublicKey and PrivateKey objects can only be created from abstract RSA class
 246       */
 247      protected function __construct()
 248      {
 249          $this->sigFormat = self::validatePlugin('Signature', 'ASN1');
 250          $this->shortFormat = 'ASN1';
 251  
 252          parent::__construct();
 253      }
 254  
 255      /**
 256       * Returns the curve
 257       *
 258       * Returns a string if it's a named curve, an array if not
 259       *
 260       * @access public
 261       * @return string|array
 262       */
 263      public function getCurve()
 264      {
 265          if ($this->curveName) {
 266              return $this->curveName;
 267          }
 268  
 269          if ($this->curve instanceof MontgomeryCurve) {
 270              $this->curveName = $this->curve instanceof Curve25519 ? 'Curve25519' : 'Curve448';
 271              return $this->curveName;
 272          }
 273  
 274          if ($this->curve instanceof TwistedEdwardsCurve) {
 275              $this->curveName = $this->curve instanceof Ed25519 ? 'Ed25519' : 'Ed448';
 276              return $this->curveName;
 277          }
 278  
 279          $params = $this->getParameters()->toString('PKCS8', ['namedCurve' => true]);
 280          $decoded = ASN1::extractBER($params);
 281          $decoded = ASN1::decodeBER($decoded);
 282          $decoded = ASN1::asn1map($decoded[0], ECParameters::MAP);
 283          if (isset($decoded['namedCurve'])) {
 284              $this->curveName = $decoded['namedCurve'];
 285              return $decoded['namedCurve'];
 286          }
 287  
 288          if (!$namedCurves) {
 289              PKCS1::useSpecifiedCurve();
 290          }
 291  
 292          return $decoded;
 293      }
 294  
 295      /**
 296       * Returns the key size
 297       *
 298       * Quoting https://tools.ietf.org/html/rfc5656#section-2,
 299       *
 300       * "The size of a set of elliptic curve domain parameters on a prime
 301       *  curve is defined as the number of bits in the binary representation
 302       *  of the field order, commonly denoted by p.  Size on a
 303       *  characteristic-2 curve is defined as the number of bits in the binary
 304       *  representation of the field, commonly denoted by m.  A set of
 305       *  elliptic curve domain parameters defines a group of order n generated
 306       *  by a base point P"
 307       *
 308       * @access public
 309       * @return int
 310       */
 311      public function getLength()
 312      {
 313          return $this->curve->getLength();
 314      }
 315  
 316      /**
 317       * Returns the current engine being used
 318       *
 319       * @see self::useInternalEngine()
 320       * @see self::useBestEngine()
 321       * @access public
 322       * @return string
 323       */
 324      public function getEngine()
 325      {
 326          if (!isset(self::$engines['PHP'])) {
 327              self::useBestEngine();
 328          }
 329          if ($this->curve instanceof TwistedEdwardsCurve) {
 330              return $this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context) ?
 331                  'libsodium' : 'PHP';
 332          }
 333  
 334          return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ?
 335              'OpenSSL' : 'PHP';
 336      }
 337  
 338      /**
 339       * Returns the public key coordinates as a string
 340       *
 341       * Used by ECDH
 342       *
 343       * @return string
 344       */
 345      public function getEncodedCoordinates()
 346      {
 347          if ($this->curve instanceof MontgomeryCurve) {
 348              return strrev($this->QA[0]->toBytes(true));
 349          }
 350          if ($this->curve instanceof TwistedEdwardsCurve) {
 351              return $this->curve->encodePoint($this->QA);
 352          }
 353          return "\4" . $this->QA[0]->toBytes(true) . $this->QA[1]->toBytes(true);
 354      }
 355  
 356      /**
 357       * Returns the parameters
 358       *
 359       * @see self::getPublicKey()
 360       * @access public
 361       * @param string $type optional
 362       * @return mixed
 363       */
 364      public function getParameters($type = 'PKCS1')
 365      {
 366          $type = self::validatePlugin('Keys', $type, 'saveParameters');
 367  
 368          $key = $type::saveParameters($this->curve);
 369  
 370          return EC::load($key, 'PKCS1')
 371              ->withHash($this->hash->getHash())
 372              ->withSignatureFormat($this->shortFormat);
 373      }
 374  
 375      /**
 376       * Determines the signature padding mode
 377       *
 378       * Valid values are: ASN1, SSH2, Raw
 379       *
 380       * @access public
 381       * @param string $format
 382       */
 383      public function withSignatureFormat($format)
 384      {
 385          if ($this->curve instanceof MontgomeryCurve) {
 386              throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
 387          }
 388  
 389          $new = clone $this;
 390          $new->shortFormat = $format;
 391          $new->sigFormat = self::validatePlugin('Signature', $format);
 392          return $new;
 393      }
 394  
 395      /**
 396       * Returns the signature format currently being used
 397       *
 398       * @access public
 399       */
 400      public function getSignatureFormat()
 401      {
 402          return $this->shortFormat;
 403      }
 404  
 405      /**
 406       * Sets the context
 407       *
 408       * Used by Ed25519 / Ed448.
 409       *
 410       * @see self::sign()
 411       * @see self::verify()
 412       * @access public
 413       * @param string $context optional
 414       */
 415      public function withContext($context = null)
 416      {
 417          if (!$this->curve instanceof TwistedEdwardsCurve) {
 418              throw new UnsupportedCurveException('Only Ed25519 and Ed448 support contexts');
 419          }
 420  
 421          $new = clone $this;
 422          if (!isset($context)) {
 423              $new->context = null;
 424              return $new;
 425          }
 426          if (!is_string($context)) {
 427              throw new \InvalidArgumentException('setContext expects a string');
 428          }
 429          if (strlen($context) > 255) {
 430              throw new \LengthException('The context is supposed to be, at most, 255 bytes long');
 431          }
 432          $new->context = $context;
 433          return $new;
 434      }
 435  
 436      /**
 437       * Returns the signature format currently being used
 438       *
 439       * @access public
 440       */
 441      public function getContext()
 442      {
 443          return $this->context;
 444      }
 445  
 446      /**
 447       * Determines which hashing function should be used
 448       *
 449       * @access public
 450       * @param string $hash
 451       */
 452      public function withHash($hash)
 453      {
 454          if ($this->curve instanceof MontgomeryCurve) {
 455              throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
 456          }
 457          if ($this->curve instanceof Ed25519 && $hash != 'sha512') {
 458              throw new UnsupportedAlgorithmException('Ed25519 only supports sha512 as a hash');
 459          }
 460          if ($this->curve instanceof Ed448 && $hash != 'shake256-912') {
 461              throw new UnsupportedAlgorithmException('Ed448 only supports shake256 with a length of 114 bytes');
 462          }
 463  
 464          return parent::withHash($hash);
 465      }
 466  
 467      /**
 468       * __toString() magic method
 469       *
 470       * @return string
 471       */
 472      public function __toString()
 473      {
 474          if ($this->curve instanceof MontgomeryCurve) {
 475              return '';
 476          }
 477  
 478          return parent::__toString();
 479      }
 480  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer