Subversion Repositories oidplus

Rev

Rev 874 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
827 daniel-mar 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(
1042 daniel-mar 252
                        Strings::bin2hex($data['curve']['a']),
253
                        Strings::bin2hex($data['curve']['b'])
827 daniel-mar 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") {
1042 daniel-mar 299
            throw new \UnexpectedValueException('extractPoint expects the first byte to be null - not ' . Strings::bin2hex($val));
827 daniel-mar 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") {
1042 daniel-mar 317
                throw new \UnexpectedValueException('The first byte of an uncompressed point should be 04 - not ' . Strings::bin2hex($val));
827 daniel-mar 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
}