[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/ -> Common.php (source)

   1  <?php
   2  
   3  /**
   4   * Generic EC Key Parsing Helper functions
   5   *
   6   * PHP version 5
   7   *
   8   * @author    Jim Wigginton <terrafrost@php.net>
   9   * @copyright 2015 Jim Wigginton
  10   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  11   * @link      http://phpseclib.sourceforge.net
  12   */
  13  
  14  namespace phpseclib3\Crypt\EC\Formats\Keys;
  15  
  16  use phpseclib3\Common\Functions\Strings;
  17  use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
  18  use phpseclib3\Crypt\EC\BaseCurves\Binary as BinaryCurve;
  19  use phpseclib3\Crypt\EC\BaseCurves\Prime as PrimeCurve;
  20  use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
  21  use phpseclib3\Exception\UnsupportedCurveException;
  22  use phpseclib3\File\ASN1;
  23  use phpseclib3\File\ASN1\Maps;
  24  use phpseclib3\Math\BigInteger;
  25  
  26  /**
  27   * Generic EC Key Parsing Helper functions
  28   *
  29   * @author  Jim Wigginton <terrafrost@php.net>
  30   */
  31  trait Common
  32  {
  33      /**
  34       * Curve OIDs
  35       *
  36       * @var array
  37       */
  38      private static $curveOIDs = [];
  39  
  40      /**
  41       * Child OIDs loaded
  42       *
  43       * @var bool
  44       */
  45      protected static $childOIDsLoaded = false;
  46  
  47      /**
  48       * Use Named Curves
  49       *
  50       * @var bool
  51       */
  52      private static $useNamedCurves = true;
  53  
  54      /**
  55       * Initialize static variables
  56       */
  57      private static function initialize_static_variables()
  58      {
  59          if (empty(self::$curveOIDs)) {
  60              // the sec* curves are from the standards for efficient cryptography group
  61              // sect* curves are curves over binary finite fields
  62              // secp* curves are curves over prime finite fields
  63              // sec*r* curves are regular curves; sec*k* curves are koblitz curves
  64              // brainpool*r* curves are regular prime finite field curves
  65              // brainpool*t* curves are twisted versions of the brainpool*r* curves
  66              self::$curveOIDs = [
  67                  'prime192v1' => '1.2.840.10045.3.1.1', // J.5.1, example 1 (aka secp192r1)
  68                  'prime192v2' => '1.2.840.10045.3.1.2', // J.5.1, example 2
  69                  'prime192v3' => '1.2.840.10045.3.1.3', // J.5.1, example 3
  70                  'prime239v1' => '1.2.840.10045.3.1.4', // J.5.2, example 1
  71                  'prime239v2' => '1.2.840.10045.3.1.5', // J.5.2, example 2
  72                  'prime239v3' => '1.2.840.10045.3.1.6', // J.5.2, example 3
  73                  'prime256v1' => '1.2.840.10045.3.1.7', // J.5.3, example 1 (aka secp256r1)
  74  
  75                  // https://tools.ietf.org/html/rfc5656#section-10
  76                  'nistp256' => '1.2.840.10045.3.1.7', // aka secp256r1
  77                  'nistp384' => '1.3.132.0.34', // aka secp384r1
  78                  'nistp521' => '1.3.132.0.35', // aka secp521r1
  79  
  80                  'nistk163' => '1.3.132.0.1', // aka sect163k1
  81                  'nistp192' => '1.2.840.10045.3.1.1', // aka secp192r1
  82                  'nistp224' => '1.3.132.0.33', // aka secp224r1
  83                  'nistk233' => '1.3.132.0.26', // aka sect233k1
  84                  'nistb233' => '1.3.132.0.27', // aka sect233r1
  85                  'nistk283' => '1.3.132.0.16', // aka sect283k1
  86                  'nistk409' => '1.3.132.0.36', // aka sect409k1
  87                  'nistb409' => '1.3.132.0.37', // aka sect409r1
  88                  'nistt571' => '1.3.132.0.38', // aka sect571k1
  89  
  90                  // from https://tools.ietf.org/html/rfc5915
  91                  'secp192r1' => '1.2.840.10045.3.1.1', // aka prime192v1
  92                  'sect163k1' => '1.3.132.0.1',
  93                  'sect163r2' => '1.3.132.0.15',
  94                  'secp224r1' => '1.3.132.0.33',
  95                  'sect233k1' => '1.3.132.0.26',
  96                  'sect233r1' => '1.3.132.0.27',
  97                  'secp256r1' => '1.2.840.10045.3.1.7', // aka prime256v1
  98                  'sect283k1' => '1.3.132.0.16',
  99                  'sect283r1' => '1.3.132.0.17',
 100                  'secp384r1' => '1.3.132.0.34',
 101                  'sect409k1' => '1.3.132.0.36',
 102                  'sect409r1' => '1.3.132.0.37',
 103                  'secp521r1' => '1.3.132.0.35',
 104                  'sect571k1' => '1.3.132.0.38',
 105                  'sect571r1' => '1.3.132.0.39',
 106                  // from http://www.secg.org/SEC2-Ver-1.0.pdf
 107                  'secp112r1' => '1.3.132.0.6',
 108                  'secp112r2' => '1.3.132.0.7',
 109                  'secp128r1' => '1.3.132.0.28',
 110                  'secp128r2' => '1.3.132.0.29',
 111                  'secp160k1' => '1.3.132.0.9',
 112                  'secp160r1' => '1.3.132.0.8',
 113                  'secp160r2' => '1.3.132.0.30',
 114                  'secp192k1' => '1.3.132.0.31',
 115                  'secp224k1' => '1.3.132.0.32',
 116                  'secp256k1' => '1.3.132.0.10',
 117  
 118                  'sect113r1' => '1.3.132.0.4',
 119                  'sect113r2' => '1.3.132.0.5',
 120                  'sect131r1' => '1.3.132.0.22',
 121                  'sect131r2' => '1.3.132.0.23',
 122                  'sect163r1' => '1.3.132.0.2',
 123                  'sect193r1' => '1.3.132.0.24',
 124                  'sect193r2' => '1.3.132.0.25',
 125                  'sect239k1' => '1.3.132.0.3',
 126  
 127                  // from http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.202.2977&rep=rep1&type=pdf#page=36
 128                  /*
 129                  'c2pnb163v1' => '1.2.840.10045.3.0.1', // J.4.1, example 1
 130                  'c2pnb163v2' => '1.2.840.10045.3.0.2', // J.4.1, example 2
 131                  'c2pnb163v3' => '1.2.840.10045.3.0.3', // J.4.1, example 3
 132                  'c2pnb172w1' => '1.2.840.10045.3.0.4', // J.4.2, example 1
 133                  'c2tnb191v1' => '1.2.840.10045.3.0.5', // J.4.3, example 1
 134                  'c2tnb191v2' => '1.2.840.10045.3.0.6', // J.4.3, example 2
 135                  'c2tnb191v3' => '1.2.840.10045.3.0.7', // J.4.3, example 3
 136                  'c2onb191v4' => '1.2.840.10045.3.0.8', // J.4.3, example 4
 137                  'c2onb191v5' => '1.2.840.10045.3.0.9', // J.4.3, example 5
 138                  'c2pnb208w1' => '1.2.840.10045.3.0.10', // J.4.4, example 1
 139                  'c2tnb239v1' => '1.2.840.10045.3.0.11', // J.4.5, example 1
 140                  'c2tnb239v2' => '1.2.840.10045.3.0.12', // J.4.5, example 2
 141                  'c2tnb239v3' => '1.2.840.10045.3.0.13', // J.4.5, example 3
 142                  'c2onb239v4' => '1.2.840.10045.3.0.14', // J.4.5, example 4
 143                  'c2onb239v5' => '1.2.840.10045.3.0.15', // J.4.5, example 5
 144                  'c2pnb272w1' => '1.2.840.10045.3.0.16', // J.4.6, example 1
 145                  'c2pnb304w1' => '1.2.840.10045.3.0.17', // J.4.7, example 1
 146                  'c2tnb359v1' => '1.2.840.10045.3.0.18', // J.4.8, example 1
 147                  'c2pnb368w1' => '1.2.840.10045.3.0.19', // J.4.9, example 1
 148                  'c2tnb431r1' => '1.2.840.10045.3.0.20', // J.4.10, example 1
 149                  */
 150  
 151                  // http://www.ecc-brainpool.org/download/Domain-parameters.pdf
 152                  // https://tools.ietf.org/html/rfc5639
 153                  'brainpoolP160r1' => '1.3.36.3.3.2.8.1.1.1',
 154                  'brainpoolP160t1' => '1.3.36.3.3.2.8.1.1.2',
 155                  'brainpoolP192r1' => '1.3.36.3.3.2.8.1.1.3',
 156                  'brainpoolP192t1' => '1.3.36.3.3.2.8.1.1.4',
 157                  'brainpoolP224r1' => '1.3.36.3.3.2.8.1.1.5',
 158                  'brainpoolP224t1' => '1.3.36.3.3.2.8.1.1.6',
 159                  'brainpoolP256r1' => '1.3.36.3.3.2.8.1.1.7',
 160                  'brainpoolP256t1' => '1.3.36.3.3.2.8.1.1.8',
 161                  'brainpoolP320r1' => '1.3.36.3.3.2.8.1.1.9',
 162                  'brainpoolP320t1' => '1.3.36.3.3.2.8.1.1.10',
 163                  'brainpoolP384r1' => '1.3.36.3.3.2.8.1.1.11',
 164                  'brainpoolP384t1' => '1.3.36.3.3.2.8.1.1.12',
 165                  'brainpoolP512r1' => '1.3.36.3.3.2.8.1.1.13',
 166                  'brainpoolP512t1' => '1.3.36.3.3.2.8.1.1.14'
 167              ];
 168              ASN1::loadOIDs([
 169                  'prime-field' => '1.2.840.10045.1.1',
 170                  'characteristic-two-field' => '1.2.840.10045.1.2',
 171                  'characteristic-two-basis' => '1.2.840.10045.1.2.3',
 172                  // per http://www.secg.org/SEC1-Ver-1.0.pdf#page=84, gnBasis "not used here"
 173                  'gnBasis' => '1.2.840.10045.1.2.3.1', // NULL
 174                  'tpBasis' => '1.2.840.10045.1.2.3.2', // Trinomial
 175                  'ppBasis' => '1.2.840.10045.1.2.3.3'  // Pentanomial
 176              ] + self::$curveOIDs);
 177          }
 178      }
 179  
 180      /**
 181       * Explicitly set the curve
 182       *
 183       * If the key contains an implicit curve phpseclib needs the curve
 184       * to be explicitly provided
 185       *
 186       * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
 187       */
 188      public static function setImplicitCurve(BaseCurve $curve)
 189      {
 190          self::$implicitCurve = $curve;
 191      }
 192  
 193      /**
 194       * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based
 195       * on the curve parameters
 196       *
 197       * @param array $params
 198       * @return \phpseclib3\Crypt\EC\BaseCurves\Base|false
 199       */
 200      protected static function loadCurveByParam(array $params)
 201      {
 202          if (count($params) > 1) {
 203              throw new \RuntimeException('No parameters are present');
 204          }
 205          if (isset($params['namedCurve'])) {
 206              $curve = '\phpseclib3\Crypt\EC\Curves\\' . $params['namedCurve'];
 207              if (!class_exists($curve)) {
 208                  throw new UnsupportedCurveException('Named Curve of ' . $params['namedCurve'] . ' is not supported');
 209              }
 210              return new $curve();
 211          }
 212          if (isset($params['implicitCurve'])) {
 213              if (!isset(self::$implicitCurve)) {
 214                  throw new \RuntimeException('Implicit curves can be provided by calling setImplicitCurve');
 215              }
 216              return self::$implicitCurve;
 217          }
 218          if (isset($params['specifiedCurve'])) {
 219              $data = $params['specifiedCurve'];
 220              switch ($data['fieldID']['fieldType']) {
 221                  case 'prime-field':
 222                      $curve = new PrimeCurve();
 223                      $curve->setModulo($data['fieldID']['parameters']);
 224                      $curve->setCoefficients(
 225                          new BigInteger($data['curve']['a'], 256),
 226                          new BigInteger($data['curve']['b'], 256)
 227                      );
 228                      $point = self::extractPoint("\0" . $data['base'], $curve);
 229                      $curve->setBasePoint(...$point);
 230                      $curve->setOrder($data['order']);
 231                      return $curve;
 232                  case 'characteristic-two-field':
 233                      $curve = new BinaryCurve();
 234                      $params = ASN1::decodeBER($data['fieldID']['parameters']);
 235                      $params = ASN1::asn1map($params[0], Maps\Characteristic_two::MAP);
 236                      $modulo = [(int) $params['m']->toString()];
 237                      switch ($params['basis']) {
 238                          case 'tpBasis':
 239                              $modulo[] = (int) $params['parameters']->toString();
 240                              break;
 241                          case 'ppBasis':
 242                              $temp = ASN1::decodeBER($params['parameters']);
 243                              $temp = ASN1::asn1map($temp[0], Maps\Pentanomial::MAP);
 244                              $modulo[] = (int) $temp['k3']->toString();
 245                              $modulo[] = (int) $temp['k2']->toString();
 246                              $modulo[] = (int) $temp['k1']->toString();
 247                      }
 248                      $modulo[] = 0;
 249                      $curve->setModulo(...$modulo);
 250                      $len = ceil($modulo[0] / 8);
 251                      $curve->setCoefficients(
 252                          Strings::bin2hex($data['curve']['a']),
 253                          Strings::bin2hex($data['curve']['b'])
 254                      );
 255                      $point = self::extractPoint("\0" . $data['base'], $curve);
 256                      $curve->setBasePoint(...$point);
 257                      $curve->setOrder($data['order']);
 258                      return $curve;
 259                  default:
 260                      throw new UnsupportedCurveException('Field Type of ' . $data['fieldID']['fieldType'] . ' is not supported');
 261              }
 262          }
 263          throw new \RuntimeException('No valid parameters are present');
 264      }
 265  
 266      /**
 267       * Extract points from a string
 268       *
 269       * Supports both compressed and uncompressed points
 270       *
 271       * @param string $str
 272       * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
 273       * @return object[]
 274       */
 275      public static function extractPoint($str, BaseCurve $curve)
 276      {
 277          if ($curve instanceof TwistedEdwardsCurve) {
 278              // first step of point deciding as discussed at the following URL's:
 279              // https://tools.ietf.org/html/rfc8032#section-5.1.3
 280              // https://tools.ietf.org/html/rfc8032#section-5.2.3
 281              $y = $str;
 282              $y = strrev($y);
 283              $sign = (bool) (ord($y[0]) & 0x80);
 284              $y[0] = $y[0] & chr(0x7F);
 285              $y = new BigInteger($y, 256);
 286              if ($y->compare($curve->getModulo()) >= 0) {
 287                  throw new \RuntimeException('The Y coordinate should not be >= the modulo');
 288              }
 289              $point = $curve->recoverX($y, $sign);
 290              if (!$curve->verifyPoint($point)) {
 291                  throw new \RuntimeException('Unable to verify that point exists on curve');
 292              }
 293              return $point;
 294          }
 295  
 296          // the first byte of a bit string represents the number of bits in the last byte that are to be ignored but,
 297          // currently, bit strings wanting a non-zero amount of bits trimmed are not supported
 298          if (($val = Strings::shift($str)) != "\0") {
 299              throw new \UnexpectedValueException('extractPoint expects the first byte to be null - not ' . Strings::bin2hex($val));
 300          }
 301          if ($str == "\0") {
 302              return [];
 303          }
 304  
 305          $keylen = strlen($str);
 306          $order = $curve->getLengthInBytes();
 307          // point compression is being used
 308          if ($keylen == $order + 1) {
 309              return $curve->derivePoint($str);
 310          }
 311  
 312          // point compression is not being used
 313          if ($keylen == 2 * $order + 1) {
 314              preg_match("#(.)(.{{$order}})(.{{$order}})#s", $str, $matches);
 315              list(, $w, $x, $y) = $matches;
 316              if ($w != "\4") {
 317                  throw new \UnexpectedValueException('The first byte of an uncompressed point should be 04 - not ' . Strings::bin2hex($val));
 318              }
 319              $point = [
 320                  $curve->convertInteger(new BigInteger($x, 256)),
 321                  $curve->convertInteger(new BigInteger($y, 256))
 322              ];
 323  
 324              if (!$curve->verifyPoint($point)) {
 325                  throw new \RuntimeException('Unable to verify that point exists on curve');
 326              }
 327  
 328              return $point;
 329          }
 330  
 331          throw new \UnexpectedValueException('The string representation of the points is not of an appropriate length');
 332      }
 333  
 334      /**
 335       * Encode Parameters
 336       *
 337       * @todo Maybe at some point this could be moved to __toString() for each of the curves?
 338       * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
 339       * @param bool $returnArray optional
 340       * @param array $options optional
 341       * @return string|false
 342       */
 343      private static function encodeParameters(BaseCurve $curve, $returnArray = false, array $options = [])
 344      {
 345          $useNamedCurves = isset($options['namedCurve']) ? $options['namedCurve'] : self::$useNamedCurves;
 346  
 347          $reflect = new \ReflectionClass($curve);
 348          $name = $reflect->getShortName();
 349          if ($useNamedCurves) {
 350              if (isset(self::$curveOIDs[$name])) {
 351                  if ($reflect->isFinal()) {
 352                      $reflect = $reflect->getParentClass();
 353                      $name = $reflect->getShortName();
 354                  }
 355                  return $returnArray ?
 356                      ['namedCurve' => $name] :
 357                      ASN1::encodeDER(['namedCurve' => $name], Maps\ECParameters::MAP);
 358              }
 359              foreach (new \DirectoryIterator(__DIR__ . '/../../Curves/') as $file) {
 360                  if ($file->getExtension() != 'php') {
 361                      continue;
 362                  }
 363                  $testName = $file->getBasename('.php');
 364                  $class = 'phpseclib3\Crypt\EC\Curves\\' . $testName;
 365                  $reflect = new \ReflectionClass($class);
 366                  if ($reflect->isFinal()) {
 367                      continue;
 368                  }
 369                  $candidate = new $class();
 370                  switch ($name) {
 371                      case 'Prime':
 372                          if (!$candidate instanceof PrimeCurve) {
 373                              break;
 374                          }
 375                          if (!$candidate->getModulo()->equals($curve->getModulo())) {
 376                              break;
 377                          }
 378                          if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) {
 379                              break;
 380                          }
 381                          if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) {
 382                              break;
 383                          }
 384  
 385                          list($candidateX, $candidateY) = $candidate->getBasePoint();
 386                          list($curveX, $curveY) = $curve->getBasePoint();
 387                          if ($candidateX->toBytes() != $curveX->toBytes()) {
 388                              break;
 389                          }
 390                          if ($candidateY->toBytes() != $curveY->toBytes()) {
 391                              break;
 392                          }
 393  
 394                          return $returnArray ?
 395                              ['namedCurve' => $testName] :
 396                              ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP);
 397                      case 'Binary':
 398                          if (!$candidate instanceof BinaryCurve) {
 399                              break;
 400                          }
 401                          if ($candidate->getModulo() != $curve->getModulo()) {
 402                              break;
 403                          }
 404                          if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) {
 405                              break;
 406                          }
 407                          if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) {
 408                              break;
 409                          }
 410  
 411                          list($candidateX, $candidateY) = $candidate->getBasePoint();
 412                          list($curveX, $curveY) = $curve->getBasePoint();
 413                          if ($candidateX->toBytes() != $curveX->toBytes()) {
 414                              break;
 415                          }
 416                          if ($candidateY->toBytes() != $curveY->toBytes()) {
 417                              break;
 418                          }
 419  
 420                          return $returnArray ?
 421                              ['namedCurve' => $testName] :
 422                              ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP);
 423                  }
 424              }
 425          }
 426  
 427          $order = $curve->getOrder();
 428          // we could try to calculate the order thusly:
 429          // https://crypto.stackexchange.com/a/27914/4520
 430          // https://en.wikipedia.org/wiki/Schoof%E2%80%93Elkies%E2%80%93Atkin_algorithm
 431          if (!$order) {
 432              throw new \RuntimeException('Specified Curves need the order to be specified');
 433          }
 434          $point = $curve->getBasePoint();
 435          $x = $point[0]->toBytes();
 436          $y = $point[1]->toBytes();
 437  
 438          if ($curve instanceof PrimeCurve) {
 439              /*
 440               * valid versions are:
 441               *
 442               * ecdpVer1:
 443               *   - neither the curve or the base point are generated verifiably randomly.
 444               * ecdpVer2:
 445               *   - curve and base point are generated verifiably at random and curve.seed is present
 446               * ecdpVer3:
 447               *   - base point is generated verifiably at random but curve is not. curve.seed is present
 448               */
 449              // other (optional) parameters can be calculated using the methods discused at
 450              // https://crypto.stackexchange.com/q/28947/4520
 451              $data = [
 452                  'version' => 'ecdpVer1',
 453                  'fieldID' => [
 454                      'fieldType' => 'prime-field',
 455                      'parameters' => $curve->getModulo()
 456                  ],
 457                  'curve' => [
 458                      'a' => $curve->getA()->toBytes(),
 459                      'b' => $curve->getB()->toBytes()
 460                  ],
 461                  'base' => "\4" . $x . $y,
 462                  'order' => $order
 463              ];
 464  
 465              return $returnArray ?
 466                  ['specifiedCurve' => $data] :
 467                  ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP);
 468          }
 469          if ($curve instanceof BinaryCurve) {
 470              $modulo = $curve->getModulo();
 471              $basis = count($modulo);
 472              $m = array_shift($modulo);
 473              array_pop($modulo); // the last parameter should always be 0
 474              //rsort($modulo);
 475              switch ($basis) {
 476                  case 3:
 477                      $basis = 'tpBasis';
 478                      $modulo = new BigInteger($modulo[0]);
 479                      break;
 480                  case 5:
 481                      $basis = 'ppBasis';
 482                      // these should be in strictly ascending order (hence the commented out rsort above)
 483                      $modulo = [
 484                          'k1' => new BigInteger($modulo[2]),
 485                          'k2' => new BigInteger($modulo[1]),
 486                          'k3' => new BigInteger($modulo[0])
 487                      ];
 488                      $modulo = ASN1::encodeDER($modulo, Maps\Pentanomial::MAP);
 489                      $modulo = new ASN1\Element($modulo);
 490              }
 491              $params = ASN1::encodeDER([
 492                  'm' => new BigInteger($m),
 493                  'basis' => $basis,
 494                  'parameters' => $modulo
 495              ], Maps\Characteristic_two::MAP);
 496              $params = new ASN1\Element($params);
 497              $a = ltrim($curve->getA()->toBytes(), "\0");
 498              if (!strlen($a)) {
 499                  $a = "\0";
 500              }
 501              $b = ltrim($curve->getB()->toBytes(), "\0");
 502              if (!strlen($b)) {
 503                  $b = "\0";
 504              }
 505              $data = [
 506                  'version' => 'ecdpVer1',
 507                  'fieldID' => [
 508                      'fieldType' => 'characteristic-two-field',
 509                      'parameters' => $params
 510                  ],
 511                  'curve' => [
 512                      'a' => $a,
 513                      'b' => $b
 514                  ],
 515                  'base' => "\4" . $x . $y,
 516                  'order' => $order
 517              ];
 518  
 519              return $returnArray ?
 520                  ['specifiedCurve' => $data] :
 521                  ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP);
 522          }
 523  
 524          throw new UnsupportedCurveException('Curve cannot be serialized');
 525      }
 526  
 527      /**
 528       * Use Specified Curve
 529       *
 530       * A specified curve has all the coefficients, the base points, etc, explicitely included.
 531       * A specified curve is a more verbose way of representing a curve
 532       */
 533      public static function useSpecifiedCurve()
 534      {
 535          self::$useNamedCurves = false;
 536      }
 537  
 538      /**
 539       * Use Named Curve
 540       *
 541       * A named curve does not include any parameters. It is up to the EC parameters to
 542       * know what the coefficients, the base points, etc, are from the name of the curve.
 543       * A named curve is a more concise way of representing a curve
 544       */
 545      public static function useNamedCurve()
 546      {
 547          self::$useNamedCurves = true;
 548      }
 549  }