Subversion Repositories oidplus

Rev

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