File: KeyTest.php

package info (click to toggle)
php-phpseclib3 3.0.46-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 5,528 kB
  • sloc: php: 30,756; xml: 392; makefile: 21
file content (764 lines) | stat: -rw-r--r-- 31,861 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
<?php

/**
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2013 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */

namespace phpseclib3\Tests\Unit\Crypt\EC;

use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\EC\Formats\Keys\OpenSSH;
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
use phpseclib3\Crypt\EC\Formats\Keys\PKCS8;
use phpseclib3\Crypt\EC\Formats\Keys\PuTTY;
use phpseclib3\Crypt\EC\Formats\Keys\XML;
use phpseclib3\Crypt\EC\PrivateKey;
use phpseclib3\Crypt\EC\PublicKey;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Tests\PhpseclibTestCase;

class KeyTest extends PhpseclibTestCase
{
    public function testBinaryPKCS1PrivateParameters()
    {
        $key = PublicKeyLoader::load('-----BEGIN EC PARAMETERS-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDBPoZHEeuf9UjjhevAbGxWwsmmWw34vkxJwtZ0AknmSUAHo0OAowJSQ
Stf/0U65RhWgBwYFK4EEACKhZANiAASVZJGIs6m/TZhbFoTwBtpvU1JcyixD2YI3
5YnoIx/6Q1oqJg1vrrmUoXaeEpaO6JH8RgItTl9lYMdmOk5309WJka6tI1QAAK3+
Jq9z4moG4whp3JsuiBQG9wnaHVrQPA4=
-----END EC PRIVATE KEY-----');
        $this->assertSameNL('secp384r1', $key->getCurve());
    }

    // openssl ecparam -name secp256k1 -genkey -noout -out secp256k1.pem
    public function testPKCS1PrivateKey()
    {
        $key = PublicKeyLoader::load($expected = '-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIEzUawcXqUsQhaEQ51JLeOIY0ddzlO2nNgwDk32ETqwkoAcGBSuBBAAK
oUQDQgAEFuVcVb9iCUhg2cknHPE+BouHGhQ39ORjMaMI3T4RfRxr6dj5HAXdEqVZ
1W94KMe30ndmTndcJ8BPeT1Dd15FdQ==
-----END EC PRIVATE KEY-----');
        $this->assertSameNL('secp256k1', $key->getCurve());
        //PKCS1::useNamedCurve();
        $this->assertSameNL($expected, $key->toString('PKCS1'));
    }

    // openssl ecparam -name secp256k1 -genkey -noout -out secp256k1.pem -param_enc explicit
    public function testPKCS1PrivateKeySpecifiedCurve()
    {
        $key = PublicKeyLoader::load('-----BEGIN EC PRIVATE KEY-----
MIIBEwIBAQQgFr6TF5meGfgCXDqVxoSEltGI+T94G42PPbA6/ibq+ouggaUwgaIC
AQEwLAYHKoZIzj0BAQIhAP////////////////////////////////////7///wv
MAYEAQAEAQcEQQR5vmZ++dy7rFWgYpXOhwsHApv82y3OKNlZ8oFbFvgXmEg62ncm
o8RlXaT7/A4RCKj9F7RIpoVUGZxH0I/7ENS4AiEA/////////////////////rqu
3OavSKA7v9JejNA2QUECAQGhRANCAASCTRhjXqmdbqphSdxNkfTNAOmDW5cZ5fnZ
ys0Tk4pUv/XdiMZtVCGTNsotGeFbT5X64JkP/BFi3PVqjwy2VhOc
-----END EC PRIVATE KEY-----');
        $this->assertSameNL('secp256k1', $key->getCurve());

        // this key and the above key have a few small differences.
        // in both keys the coefficient's are 0 and 7. in the above
        // key both coefficients are encoded using a single byte.
        // in the following key the coefficient's are encoded
        // as 32 bytes (ie. the length of the reduction prime).
        // eg. one byte null padded to 32 bytes.
        // also, in the above key the cofactor (1; optional) is
        // included whereas in the following key it is not
        $expected = '-----BEGIN EC PRIVATE KEY-----
MIIBTgIBAQQgFr6TF5meGfgCXDqVxoSEltGI+T94G42PPbA6/ibq+ouggeAwgd0C
AQEwLAYHKoZIzj0BAQIhAP////////////////////////////////////7///wv
MEQEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAABwRBBHm+Zn753LusVaBilc6HCwcCm/zbLc4o
2VnygVsW+BeYSDradyajxGVdpPv8DhEIqP0XtEimhVQZnEfQj/sQ1LgCIQD/////
///////////////+uq7c5q9IoDu/0l6M0DZBQaFEA0IABIJNGGNeqZ1uqmFJ3E2R
9M0A6YNblxnl+dnKzROTilS/9d2Ixm1UIZM2yi0Z4VtPlfrgmQ/8EWLc9WqPDLZW
E5w=
-----END EC PRIVATE KEY-----';
        PKCS1::useSpecifiedCurve();
        $this->assertSameNL($expected, $key->toString('PKCS1'));
    }

    // openssl ecparam -name secp256k1 -genkey -noout -out secp256k1.pem
    // openssl pkcs8 -topk8 -nocrypt -in secp256k1.pem -out secp256k1-2.pem
    public function testPKCS8PrivateKey()
    {
        $key = PublicKeyLoader::load($expected = '-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgAYCXwnhqMT6fCIKIkQ0w
cac7QqHrn4TCQMF9a+im74WhRANCAATwCjyGuP8xQbvVjznqazL36oeAnD32I+X2
+wscW3OmyTDpk41HaWYPh+j+BoufsSkCwf8dBRGEQbCieZbbZogy
-----END PRIVATE KEY-----');
        $this->assertSameNL('secp256k1', $key->getCurve());
        $this->assertSameNL($expected, $key->toString('PKCS8'));
    }

    // openssl ecparam -name secp256k1 -genkey -noout -out secp256k1.pem -param_enc explicit
    // openssl pkcs8 -topk8 -nocrypt -in secp256k1.pem -out secp256k1-2.pem
    public function testPKCS8PrivateKeySpecifiedCurve()
    {
        $key = PublicKeyLoader::load('-----BEGIN PRIVATE KEY-----
MIIBIwIBADCBrgYHKoZIzj0CATCBogIBATAsBgcqhkjOPQEBAiEA////////////
/////////////////////////v///C8wBgQBAAQBBwRBBHm+Zn753LusVaBilc6H
CwcCm/zbLc4o2VnygVsW+BeYSDradyajxGVdpPv8DhEIqP0XtEimhVQZnEfQj/sQ
1LgCIQD////////////////////+uq7c5q9IoDu/0l6M0DZBQQIBAQRtMGsCAQEE
IKFfw3vfd5pqA5SZOTFtpr7hdJoKP/rmTPMCggkAOA35oUQDQgAEnX66+UCzUW3T
/fkLGIIfZjJm5bIMwAV85LpDom2hI441JRx+/W4WqtGuW+B/LABS6ZHp+qzepThC
HsjS3Q9Pew==
-----END PRIVATE KEY-----');
        $this->assertSameNL('secp256k1', $key->getCurve());

        // see testPKCS1PrivateKeySpecifiedCurve for an explanation
        // of how this key and the above key differ
        $expected = '-----BEGIN PRIVATE KEY-----
MIIBXgIBADCB6QYHKoZIzj0CATCB3QIBATAsBgcqhkjOPQEBAiEA////////////
/////////////////////////v///C8wRAQgAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBEEE
eb5mfvncu6xVoGKVzocLBwKb/NstzijZWfKBWxb4F5hIOtp3JqPEZV2k+/wOEQio
/Re0SKaFVBmcR9CP+xDUuAIhAP////////////////////66rtzmr0igO7/SXozQ
NkFBBG0wawIBAQQgoV/De993mmoDlJk5MW2mvuF0mgo/+uZM8wKCCQA4DfmhRANC
AASdfrr5QLNRbdP9+QsYgh9mMmblsgzABXzkukOibaEjjjUlHH79bhaq0a5b4H8s
AFLpken6rN6lOEIeyNLdD097
-----END PRIVATE KEY-----';
        PKCS8::useSpecifiedCurve();
        $this->assertSameNL($expected, $key->toString('PKCS8'));
    }

    // openssl ecparam -name sect113r1 -genkey -noout -out sect113r1.pem
    public function testBinaryPKCS1PrivateKey()
    {
        $key = PublicKeyLoader::load('-----BEGIN EC PRIVATE KEY-----
MEECAQEEDwBZdP4eSzKk/uQa6jdtfKAHBgUrgQQABKEiAyAABAHqCoNb++mK5qvE
c4rCzQEuI19czqvXpEPcAWSXew==
-----END EC PRIVATE KEY-----');
        $this->assertSameNL('sect113r1', $key->getCurve());

        // the difference between this and the above key is that
        // the privateKey part of the above key has a leading null
        // byte whereas this one doesn't
        $expected = '-----BEGIN EC PRIVATE KEY-----
MEACAQEEDll0/h5LMqT+5BrqN218oAcGBSuBBAAEoSIDIAAEAeoKg1v76Yrmq8Rz
isLNAS4jX1zOq9ekQ9wBZJd7
-----END EC PRIVATE KEY-----';

        PKCS1::useNamedCurve();
        $this->assertSameNL($expected, $key->toString('PKCS1'));
    }

    // openssl ecparam -name sect113r1 -genkey -noout -out sect113r1.pem -param_enc explicit
    public function testBinaryPKCS1PrivateKeySpecifiedCurve()
    {
        $key = PublicKeyLoader::load('-----BEGIN EC PRIVATE KEY-----
MIHNAgEBBA8AuSc4BeeyYTq9rbSDuL2ggZIwgY8CAQEwHAYHKoZIzj0BAjARAgFx
BgkqhkjOPQECAwICAQkwNwQOMIglDKbnx/5knOhYIPcEDui+5NPiJgdEGIvg6ccj
AxUAEOcjqxTWluZ2h1YVF1b+v4/LSakEHwQAnXNhbzX0qxQH1zViwQ8ApSgwJ3lY
7oTRMV7TGIYCDwEAAAAAAAAA2czsijnlbwIBAqEiAyAABAFC7c50y7uw+iuHeMCt
WwCpKNBUcVeiHme609Dv/g==
-----END EC PRIVATE KEY-----');
        $this->assertSameNL('sect113r1', $key->getCurve());

        // this key and the above key have a few small differences.
        // the above key has the (optional) seed for the verifiably
        // random function whereas the following key does not.
        // also, in the above key the cofactor (1; optional) is
        // included whereas in the following key it is not;
        // finally, in the above the privateKey has a leading null
        // byte whereas it doesn't in the following key
        $expected = '-----BEGIN EC PRIVATE KEY-----
MIGwAgEBBA65JzgF57JhOr2ttIO4vaB3MHUCAQEwHAYHKoZIzj0BAjARAgFxBgkq
hkjOPQECAwICAQkwIAQOMIglDKbnx/5knOhYIPcEDui+5NPiJgdEGIvg6ccjBB8E
AJ1zYW819KsUB9c1YsEPAKUoMCd5WO6E0TFe0xiGAg8BAAAAAAAAANnM7Io55W+h
IgMgAAQBQu3OdMu7sPorh3jArVsAqSjQVHFXoh5nutPQ7/4=
-----END EC PRIVATE KEY-----';
        PKCS1::useSpecifiedCurve();
        $this->assertSameNL($expected, $key->toString('PKCS1'));
    }

    // openssl ecparam -name sect113r1 -genkey -noout -out sect113r1.pem
    // openssl pkcs8 -topk8 -nocrypt -in sect113r1.pem -out sect113r1-2.pem
    // sect113r1's reduction polynomial is a trinomial
    public function testBinaryPKCS8PrivateKey()
    {
        $key = PublicKeyLoader::load('-----BEGIN PRIVATE KEY-----
MFECAQAwEAYHKoZIzj0CAQYFK4EEAAQEOjA4AgEBBA8A5OuqAY8HYoFOaz9mE6mh
IgMgAAQASF3rOTPXvH0QdRBvsrMBdLMf27yd8AWABrZTxvI=
-----END PRIVATE KEY-----');
        $this->assertSameNL('sect113r1', $key->getCurve());

        // the difference between this and the above key is that
        // the privateKey part of the above key has a leading null
        // byte whereas this one doesn't
        $expected = '-----BEGIN PRIVATE KEY-----
MFACAQAwEAYHKoZIzj0CAQYFK4EEAAQEOTA3AgEBBA7k66oBjwdigU5rP2YTqaEi
AyAABABIXes5M9e8fRB1EG+yswF0sx/bvJ3wBYAGtlPG8g==
-----END PRIVATE KEY-----';

        PKCS8::useNamedCurve();
        $this->assertSameNL($expected, $key->toString('PKCS8'));
    }

    // openssl ecparam -name sect113r1 -genkey -noout -out sect113r1.pem -param_enc explicit
    // openssl pkcs8 -topk8 -nocrypt -in sect113r1.pem -out sect113r1-2.pem
    public function testBinaryPKCS8PrivateKeySpecifiedCurve()
    {
        $key = PublicKeyLoader::load('-----BEGIN PRIVATE KEY-----
MIHdAgEAMIGbBgcqhkjOPQIBMIGPAgEBMBwGByqGSM49AQIwEQIBcQYJKoZIzj0B
AgMCAgEJMDcEDjCIJQym58f+ZJzoWCD3BA7ovuTT4iYHRBiL4OnHIwMVABDnI6sU
1pbmdodWFRdW/r+Py0mpBB8EAJ1zYW819KsUB9c1YsEPAKUoMCd5WO6E0TFe0xiG
Ag8BAAAAAAAAANnM7Io55W8CAQIEOjA4AgEBBA8AXtfDMRsRTx8snPbWHquhIgMg
AAQA9xdWGJ6vV23+vkdq0C8BLJVg5E3amMyf/5keGa4=
-----END PRIVATE KEY-----');
        $this->assertSameNL('sect113r1', $key->getCurve());

        // see testBinaryPKCS1PrivateKeySpecifiedCurve() for an
        // explanation of the differences between the above key
        // and the following key
        $expected = '-----BEGIN PRIVATE KEY-----
MIHBAgEAMIGABgcqhkjOPQIBMHUCAQEwHAYHKoZIzj0BAjARAgFxBgkqhkjOPQEC
AwICAQkwIAQOMIglDKbnx/5knOhYIPcEDui+5NPiJgdEGIvg6ccjBB8EAJ1zYW81
9KsUB9c1YsEPAKUoMCd5WO6E0TFe0xiGAg8BAAAAAAAAANnM7Io55W8EOTA3AgEB
BA5e18MxGxFPHyyc9tYeq6EiAyAABAD3F1YYnq9Xbf6+R2rQLwEslWDkTdqYzJ//
mR4Zrg==
-----END PRIVATE KEY-----';
        PKCS8::useSpecifiedCurve();
        $this->assertSameNL($expected, $key->toString('PKCS8'));
    }

    // openssl ecparam -name sect131r1 -genkey -noout -out sect131r1.pem -param_enc explicit
    // sect131r1's reduction polynomial is a pentanomial
    public function testBinaryPentanomialPKCS1PrivateKey()
    {
        $key = PublicKeyLoader::load('-----BEGIN EC PRIVATE KEY-----
MIHoAgEBBBECPEK9NCISWf2riBsORoTM+6CBpzCBpAIBATAlBgcqhkjOPQECMBoC
AgCDBgkqhkjOPQECAwMwCQIBAgIBAwIBCDA9BBEHoRsJp2tWIURBj/P/jCVwuAQR
AhfAVhCIS2O5xscpFnj500EDFQBNaW5naHVhUXWYW9OtutohtDqX4gQjBACBuvkf
35gzxA+cGBNDY4OZB4xufqOMAB9zyBNLG0754VACEQQAAAAAAAAAAjEjlTqUZLVN
AgECoSYDJAAEBEIolGjo5lnsYqNagqYPOaEGOglkllDO2aWPtB6n+x/WXw==
-----END EC PRIVATE KEY-----');
        $this->assertSameNL('sect131r1', $key->getCurve());

        // see testBinaryPKCS1PrivateKeySpecifiedCurve() for an
        // explanation of the differences between the above key
        // and the following key
        $expected = '-----BEGIN EC PRIVATE KEY-----
MIHOAgEBBBECPEK9NCISWf2riBsORoTM+6CBjTCBigIBATAlBgcqhkjOPQECMBoC
AgCDBgkqhkjOPQECAwMwCQIBAgIBAwIBCDAmBBEHoRsJp2tWIURBj/P/jCVwuAQR
AhfAVhCIS2O5xscpFnj500EEIwQAgbr5H9+YM8QPnBgTQ2ODmQeMbn6jjAAfc8gT
SxtO+eFQAhEEAAAAAAAAAAIxI5U6lGS1TaEmAyQABARCKJRo6OZZ7GKjWoKmDzmh
BjoJZJZQztmlj7Qep/sf1l8=
-----END EC PRIVATE KEY-----';
        PKCS1::useSpecifiedCurve();
        $this->assertSameNL($expected, $key->toString('PKCS1'));
    }

    // from https://tools.ietf.org/html/draft-ietf-curdle-pkix-07#section-10.1
    public function testEd25519PublicKey()
    {
        $expected = '-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE=
-----END PUBLIC KEY-----';
        $key = PublicKeyLoader::load($expected);
        $this->assertSameNL('Ed25519', $key->getCurve());
        $this->assertSameNL($expected, $key->toString('PKCS8'));
    }

    // from https://tools.ietf.org/html/draft-ietf-curdle-pkix-07#section-10.3
    public function testEd25519PrivateKey()
    {
        // without public key (public key should be derived)
        $expected = '-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC
-----END PRIVATE KEY-----';
        $key = PublicKeyLoader::load($expected);
        $this->assertSameNL($expected, $key->toString('PKCS8'));
        $this->assertSameNL('Ed25519', $key->getCurve());
        $this->assertSameNL('Ed25519', $key->getPublicKey()->getCurve());

        // with public key
        $key = PublicKeyLoader::load('-----BEGIN PRIVATE KEY-----
MHICAQEwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC
oB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrB
Z9w7lshQhqowtrbLDFw4rXAxZuE=
-----END PRIVATE KEY-----');
        $this->assertSameNL('Ed25519', $key->getCurve());
        $this->assertSameNL('Ed25519', $key->getPublicKey()->getCurve());

        // the above key not only omits NULL - it also includes a
        // unstructuredName attribute with a value of "Curdle Chairs"
        // that the following key does not have
        $key = PublicKeyLoader::load('-----BEGIN PRIVATE KEY-----
MFMCAQEwBwYDK2VwBQAEIgQg1O5y2/kTWErVttjx92n4rTr+fCjL8dT74Jeoj0R1
WEKBIQAZv0QJaYTN/oVBusFn3DuWyFCGqjC2tssMXDitcDFm4Q==
-----END PRIVATE KEY-----');
        $this->assertSameNL('Ed25519', $key->getCurve());
        $this->assertSameNL('Ed25519', $key->getPublicKey()->getCurve());
    }

    // Generate with:
    // openssl genpkey -algorithm ed448 | openssl ec -pubout
    public function testEd448PublicKey()
    {
        $expected = '-----BEGIN PUBLIC KEY-----
MEMwBQYDK2VxAzoAsA7zbld48IfDhm7Qd6FYrvnljtjhPRRqZi04NWyj8VXrWe1x
BMLQFJEE0JDmKayUWpUWsRXwmb6A
-----END PUBLIC KEY-----';
        $key = PublicKeyLoader::load($expected);
        $this->assertSameNL('Ed448', $key->getCurve());
        $this->assertSameNL($expected, $key->toString('PKCS8'));
    }

    // Generate with:
    // openssl genpkey -algorithm ed448
    public function testEd448PrivateKey()
    {
        $expected = '-----BEGIN PRIVATE KEY-----
MEcCAQAwBQYDK2VxBDsEOettXaJYob4hJNKJNOD+FfMvdesLKNp0KwochI6AKmAb
tWhtkn99WOjd1PsGMh9zz2Vhdg3MwasOMQ==
-----END PRIVATE KEY-----';
        $key = PublicKeyLoader::load($expected);
        $this->assertSameNL($expected, $key->toString('PKCS8'));
        $this->assertSameNL('Ed448', $key->getCurve());
        $this->assertSameNL('Ed448', $key->getPublicKey()->getCurve());
    }

    public function testPuTTYnistp256()
    {
        $key = PublicKeyLoader::load($expected = 'PuTTY-User-Key-File-2: ecdsa-sha2-nistp256
Encryption: none
Comment: ecdsa-key-20181105
Public-Lines: 3
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJEXCsWA8s18
m25MJlVE1urbXPYFi4q8oMbb2H0kE2f5WPxizsKXRmb1J68paXQizryL9fC4FTqI
CJ1+UnaPfk0=
Private-Lines: 1
AAAAIQDwaPlajbXY1SxhuwsUqN1CEZ5g4adsbmJsKm+ZbUVm4g==
Private-MAC: b85ca0eb7c612df5d18af85128821bd53faaa3ef
');
        $this->assertSameNL('secp256r1', $key->getCurve());

        PuTTY::setComment('ecdsa-key-20181105');
        $this->assertSameNL($expected, $key->toString('PuTTY'));

        $key = PublicKeyLoader::load($expected = 'ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJEXCsWA8s18m25MJlVE1urbXPYFi4q8oMbb2H0kE2f5WPxizsKXRmb1J68paXQizryL9fC4FTqICJ1+UnaPfk0= ecdsa-key-20181105');
        $this->assertSameNL('secp256r1', $key->getCurve());

        OpenSSH::setComment('ecdsa-key-20181105');
        $this->assertSameNL($expected, $key->toString('OpenSSH'));
    }

    public function testPuTTYnistp384()
    {
        $key = PublicKeyLoader::load($expected = 'PuTTY-User-Key-File-2: ecdsa-sha2-nistp384
Encryption: none
Comment: ecdsa-key-20181105
Public-Lines: 3
AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBOI53wHG3Cdc
AJZq5PXWZAEAxxsNVFQlQgOX9toWEOgqQF5LbK2nWLKRvaHMzocUXaTYZDccSS0A
TZFPT3j1Er1LU9cu4PHpyS07v262jdzkxIvKCPcAeISuV80MC7rHog==
Private-Lines: 2
AAAAMQCEMkGMDg6N7bUqdvLXe0YmY4qBSi8hmAuMvU38RDoVFVmV+R4RYmMueyrX
be9Oyus=
Private-MAC: 97a990a3d5f6b8f268d4be9c4ab9ebfd8fa79849
');
        $this->assertSameNL('secp384r1', $key->getCurve());

        PuTTY::setComment('ecdsa-key-20181105');
        $this->assertSameNL($expected, $key->toString('PuTTY'));

        $key = PublicKeyLoader::load($expected = 'ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBOI53wHG3CdcAJZq5PXWZAEAxxsNVFQlQgOX9toWEOgqQF5LbK2nWLKRvaHMzocUXaTYZDccSS0ATZFPT3j1Er1LU9cu4PHpyS07v262jdzkxIvKCPcAeISuV80MC7rHog== ecdsa-key-20181105');
        $this->assertSameNL('secp384r1', $key->getCurve());

        OpenSSH::setComment('ecdsa-key-20181105');
        $this->assertSameNL($expected, $key->toString('OpenSSH'));
    }

    public function testPuTTYnistp521()
    {
        $key = PublicKeyLoader::load($expected = 'PuTTY-User-Key-File-2: ecdsa-sha2-nistp521
Encryption: none
Comment: ecdsa-key-20181105
Public-Lines: 4
AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF1Eg0MjaJw
ooFj6HCNh4RWbvmQRY+sdczJyBdT3EaTc/6IUcCfW7w7rAeRp2CDdE9RlAVD8IuL
qW7DJH06Xeov8wBO5G6jUqXu0rlHsOSiC6VcCxBJuWVNB1IorHnS7PX0f6HdLlIE
me73P77drqpn5YY0XLtP6hFrF7H5XfCxpNyaJA==
Private-Lines: 2
AAAAQgHJl8/dIArolFymdzhagXCfd2l8UF3CQXWGVGDQ0R04nnntlyztYiVdRXXK
r84NnzS7dJcAsR9YaUOZ69NRKNiUAQ==
Private-MAC: 6d49ce289b85549a43d74422dd8bb3ba8798c72c
');
        $this->assertSameNL('secp521r1', $key->getCurve());

        PuTTY::setComment('ecdsa-key-20181105');
        $this->assertSameNL($expected, $key->toString('PuTTY'));

        $key = PublicKeyLoader::load($expected = 'ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF1Eg0MjaJwooFj6HCNh4RWbvmQRY+sdczJyBdT3EaTc/6IUcCfW7w7rAeRp2CDdE9RlAVD8IuLqW7DJH06Xeov8wBO5G6jUqXu0rlHsOSiC6VcCxBJuWVNB1IorHnS7PX0f6HdLlIEme73P77drqpn5YY0XLtP6hFrF7H5XfCxpNyaJA== ecdsa-key-20181105');
        $this->assertSameNL('secp521r1', $key->getCurve());

        OpenSSH::setComment('ecdsa-key-20181105');
        $this->assertSameNL($expected, $key->toString('OpenSSH'));
    }

    public function testPuTTYed25519()
    {
        $key = PublicKeyLoader::load($expected = 'PuTTY-User-Key-File-2: ssh-ed25519
Encryption: none
Comment: ed25519-key-20181105
Public-Lines: 2
AAAAC3NzaC1lZDI1NTE5AAAAIC6I6RyYAqtBcWXws9EDqGbhFtc5rKG4NMn/G7te
mQtu
Private-Lines: 1
AAAAIAHu1uI7dxFzo/SleEI2CekXKmgqlXwOgvfaRWxiX4Jd
Private-MAC: 8a06821a1c8b8b40fc40f876e543c4ea3fb81bb9
');
        $this->assertSameNL('Ed25519', $key->getCurve());

        PuTTY::setComment('ed25519-key-20181105');
        $this->assertSameNL($expected, $key->toString('PuTTY'));

        $key = PublicKeyLoader::load($expected = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC6I6RyYAqtBcWXws9EDqGbhFtc5rKG4NMn/G7temQtu ed25519-key-20181105');
        $this->assertSameNL('Ed25519', $key->getCurve());

        OpenSSH::setComment('ed25519-key-20181105');
        $this->assertSameNL($expected, $key->toString('OpenSSH'));
    }

    public function testlibsodium()
    {
        if (!function_exists('sodium_crypto_sign_keypair')) {
            self::markTestSkipped('libsodium extension is not available.');
        }

        $kp = sodium_crypto_sign_keypair();

        $key = EC::loadFormat('libsodium', $expected = sodium_crypto_sign_secretkey($kp));
        $this->assertSameNL('Ed25519', $key->getCurve());
        $this->assertSameNL($expected, $key->toString('libsodium'));

        $key = EC::loadFormat('libsodium', $expected = sodium_crypto_sign_publickey($kp));
        $this->assertSameNL('Ed25519', $key->getCurve());
        $this->assertSameNL($expected, $key->toString('libsodium'));
    }

    // ssh-keygen -t ed25519
    public function testOpenSSHPrivateKey()
    {
        $key = PublicKeyLoader::load('-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCpm7dS1/WDTW+uuhp2+aFLPKaJle6+oJqDGLXhlQAX4AAAAJg8TmN5PE5j
eQAAAAtzc2gtZWQyNTUxOQAAACCpm7dS1/WDTW+uuhp2+aFLPKaJle6+oJqDGLXhlQAX4A
AAAEDltCTSbrr42IS4hhkS6ly0W2XItRQwxjLT+03bIyA+V6mbt1LX9YNNb666Gnb5oUs8
pomV7r6gmoMYteGVABfgAAAAD3ZhZ3JhbnRAdmFncmFudAECAwQFBg==
-----END OPENSSH PRIVATE KEY-----');
        $this->assertSameNL('Ed25519', $key->getCurve());

        // testing this key is a little difficult because of this format's
        // two back to back checkint fields. both fields correspond to the
        // same randomly generated number. ostensibly this let's you verify
        // successful decryption of encrypted keys but phpseclib doesn't
        // support encrypted keys
        // none-the-less, because of the randomized component we can't easily
        // see if the key string is equal to another known string
        $key2 = PublicKeyLoader::load($key->toString('OpenSSH'));
        $this->assertSameNL('Ed25519', $key2->getCurve());
    }

    // from https://www.w3.org/TR/xmldsig-core/#sec-RFC4050Compat
    public function testXMLKey()
    {
        $key = PublicKeyLoader::load($orig = '<ECDSAKeyValue xmlns="http://www.w3.org/2001/04/xmldsig-more#">
<DomainParameters>
  <NamedCurve URN="urn:oid:1.2.840.10045.3.1.7" />
</DomainParameters>
<PublicKey>
  <X Value="58511060653801744393249179046482833320204931884267326155134056258624064349885" />
  <Y Value="102403352136827775240910267217779508359028642524881540878079119895764161434936" />
</PublicKey>
</ECDSAKeyValue>');
        $this->assertSameNL('secp256r1', $key->getCurve());

        XML::enableRFC4050Syntax();

        $dom = new \DOMDocument();
        $dom->preserveWhiteSpace = false;
        $dom->loadXML($orig);
        $expected = $dom->C14N();

        //$dom = new DOMDocument();
        //$dom->preserveWhiteSpace = false;
        $dom->loadXML($key->toString('XML'));
        $actual = $dom->C14N();

        $this->assertSameNL($expected, $actual);
    }

    public function assertSameNL($expected, $actual, $message = '')
    {
        $expected = str_replace("\r\n", "\n", $expected);
        $actual = str_replace("\r\n", "\n", $actual);
        $this->assertSame($expected, $actual, $message);
    }

    public function testOpenSSHPrivateEC()
    {
        $key = '-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTk2tbDiyQPzljR+LLIsMzJiwqkfHkG
StUt3kO00FKMoYv3RJfP6mqdE3E3pPcT5cBg4yB+KzYsYDxwuBc03oQcAAAAqCTU2l0k1N
pdAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOTa1sOLJA/OWNH4
ssiwzMmLCqR8eQZK1S3eQ7TQUoyhi/dEl8/qap0TcTek9xPlwGDjIH4rNixgPHC4FzTehB
wAAAAgZ8mK8+EsQ46susQn4mwMNmpvTaKX9Q9KDvOrzotP2qgAAAAMcm9vdEB2YWdyYW50
AQIDBA==
-----END OPENSSH PRIVATE KEY-----';

        $key = PublicKeyLoader::load($key);

        $key2 = PublicKeyLoader::load($key->toString('OpenSSH'));
        $this->assertInstanceOf(PrivateKey::class, $key2);

        $sig = $key->sign('zzz');

        $key = 'ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOTa1sOLJA/OWNH4ssiwzMmLCqR8eQZK1S3eQ7TQUoyhi/dEl8/qap0TcTek9xPlwGDjIH4rNixgPHC4FzTehBw= root@vagrant';
        $key = PublicKeyLoader::load($key);

        $this->assertTrue($key->verify('zzz', $sig));
    }

    public function testOpenSSHPrivateEd25519()
    {
        $key = '-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACChhCZwqkIh43AfURPOgbyYeZRCKvd4jFcyAK4xmiqxQwAAAJDqGgwS6hoM
EgAAAAtzc2gtZWQyNTUxOQAAACChhCZwqkIh43AfURPOgbyYeZRCKvd4jFcyAK4xmiqxQw
AAAEDzL/Yl1Vr/5MxhIIEkVKXBMEIumVG8gUjT9i2PTGSehqGEJnCqQiHjcB9RE86BvJh5
lEIq93iMVzIArjGaKrFDAAAADHJvb3RAdmFncmFudAE=
-----END OPENSSH PRIVATE KEY-----';

        $key = PublicKeyLoader::load($key);
        $sig = $key->sign('zzz');
        $sig2 = $key->withSignatureFormat('SSH2')->sign('zzz');

        $key = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKGEJnCqQiHjcB9RE86BvJh5lEIq93iMVzIArjGaKrFD root@vagrant';
        $key = PublicKeyLoader::load($key);

        $this->assertTrue($key->verify('zzz', $sig));
        $this->assertTrue($key->withSignatureFormat('SSH2')->verify('zzz', $sig2));
    }

    /**
     * @group github1712
     */
    public function testKeyTooLarge()
    {
        $this->expectException('RangeException');

        $key = '-----BEGIN PRIVATE KEY-----
MIIEDwIBADATBgcqhkjOPQIBBggqhkjOPQMBBwSCA/MwggPvAgEBBIID6P//////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
//////////////////////////////////////////////8=
-----END PRIVATE KEY-----';

        $private = EC::loadFormat('PKCS8', $key);
    }

    /**
     * @group github1712
     */
    public function testLargeCurve25519Key()
    {
        $raw = pack('H*', '8426220e7a57dc8d685d3966e3a23600e32563ce6033e07d0c89dbb5bd296577');
        $key = EC::loadFormat('MontgomeryPrivate', $raw);

        $this->assertSameNL($raw, $key->toString('MontgomeryPrivate'));
    }

    public function testOpenSSHEncryptedCreation()
    {
        if (PHP_INT_SIZE == 4) {
            self::markTestSkipped('32-bit integers slow OpenSSH encrypted keys down too much');
        }

        $key = EC::createKey('Ed25519');
        $key = $key->withPassword('test')->toString('OpenSSH');

        $key = PublicKeyLoader::load($key, 'test');
        $this->assertInstanceOf(PrivateKey::class, $key);
    }

    public function testECasJWK()
    {
        // keys are from https://datatracker.ietf.org/doc/html/rfc7517#appendix-A

        $plaintext = 'zzz';

        $key = '     {"keys":
       [
         {"kty":"EC",
          "crv":"P-256",
          "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
          "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
          "d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
          "use":"enc",
          "kid":"1"}
       ]
     }';

        $keyWithoutWS = preg_replace('#\s#', '', $key);

        $key = PublicKeyLoader::load($key);

        $phpseclibKey = str_replace('=', '', $key->toString('JWK', [
            'use' => 'enc',
            'kid' => '1'
        ]));

        $this->assertSame($keyWithoutWS, $phpseclibKey);

        $sig = $key->sign($plaintext);

        $key = '{"keys":
       [
         {"kty":"EC",
          "crv":"P-256",
          "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
          "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
          "use":"enc",
          "kid":"1"}
       ]
     }';

        $keyWithoutWS = preg_replace('#\s#', '', $key);

        $key = PublicKeyLoader::load($key);

        $phpseclibKey = str_replace('=', '', $key->toString('JWK', [
            'use' => 'enc',
            'kid' => '1'
        ]));

        $this->assertSame($keyWithoutWS, $phpseclibKey);

        $this->assertTrue($key->verify($plaintext, $sig));
    }

    public function testEd25519asJWK()
    {
        // keys are from https://www.rfc-editor.org/rfc/rfc8037.html#appendix-A

        $plaintext = 'zzz';

        $key = '   {"kty":"OKP","crv":"Ed25519",
   "x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
   "d":"nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A"}';

        $keyWithoutWS = preg_replace('#\s#', '', $key);
        $keyWithoutWS = '{"keys":[' . $keyWithoutWS . ']}';

        $key = PublicKeyLoader::load($key);

        $phpseclibKey = str_replace('=', '', $key->toString('JWK'));

        $this->assertSame($keyWithoutWS, $phpseclibKey);

        $sig = $key->sign($plaintext);

        $key = '   {"kty":"OKP","crv":"Ed25519",
   "x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"}';

        $keyWithoutWS = preg_replace('#\s#', '', $key);
        $keyWithoutWS = '{"keys":[' . $keyWithoutWS . ']}';

        $key = PublicKeyLoader::load($key);

        $phpseclibKey = str_replace('=', '', $key->toString('JWK'));

        $this->assertSame($keyWithoutWS, $phpseclibKey);

        $this->assertTrue($key->verify($plaintext, $sig));
    }

    public function testNakedPKCS8PubKey()
    {
        $key = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErPJyxEu2/oKCrJaaTVTrq39DKJ2XcN6W+k8UvGf+Y/lDWNbFitQocabsDUvSN0edHH3UKP5QPTz4cOlyIPMrXQ==';
        $key = PublicKeyLoader::load($key);
        $this->assertInstanceOf(PublicKey::class, $key);
    }

    public function testMislabledPKCS8PubKey()
    {
        $this->expectException('\phpseclib3\Exception\NoKeyLoadedException');

        $key = '-----BEGIN PRIVATE KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErPJyxEu2/oKCrJaaTVTrq39DKJ2X
cN6W+k8UvGf+Y/lDWNbFitQocabsDUvSN0edHH3UKP5QPTz4cOlyIPMrXQ==
-----END PUBLIC KEY-----';
        $key = PublicKeyLoader::load($key);
        $this->assertInstanceOf(PublicKey::class, $key);
    }

    /**
     * @group github1956
     */
    public function testIEEESignature()
    {
        $key = '{"alg":"ES256","crv":"P-256","ext":true,"key_ops":["verify"],"kty":"EC","x":"FKwqyGd4i2NAl8RUXCCBRCAIbcpeGyfyXwgA_AWHb8Y","y":"njxhw5O6zGVkBlcPDKYj0E-6VO1giHTUkJWBhgKNqd8"}';
        $key = PublicKeyLoader::load($key)->withSignatureFormat('IEEE')->withHash('sha384');

        $signature = 'a4f61518323bac50b4f87a0f766ebb10d1db25358a0a20a98dab20be4e9c3be2d77ff5a8415cfce2967999c73d2a49b2d8c01990f72c04d99ebe3c4ebf75b4e9';
        $signature = pack('H*', $signature);

        $this->assertTrue($key->verify('hello world!', $signature));
    }

    public function testExcessivelyLargeBinaryField()
    {
        $this->expectException('\OutOfBoundsException');

        $key = '-----BEGIN PUBLIC KEY-----
MIIBDDCB0wYHKoZIzj0CATCBxwIBATAgBgcqhkjOPQECMBUCBH////8GCSqGSM49
AQIDAgICAMEwTQQZABeFj+t6mJdRaeFx93tAh94JisipEd97AQQZAP37Sb/mw6if
rK2qeh5bvHzBwuXYMUeIFAMVABA/rsdNaW5naHVhUXV3f8Wxke8wBDMEAfSBvF8P
+Ep0rWzfb970v2F5YlNy2MDF4QAl45nykDcSzPPqnjoa0X+wsyAbavfOGwUCGQEA
AAAAAAAAAAAAAADH80p3j0Q6zJIOukkCAQIDNAAEAE2mUTAwdPK952h3G8ZinK8B
z9DYTLdGkQDqox3AtEs9nn6kE1O/vHE4bqMegjj4gbA=
-----END PUBLIC KEY-----';
        $key = EC::loadFormat('PKCS8', $key);
        $this->assertInstanceOf(PublicKey::class, $key);
    }

    public function testIEEESignatureCreate()
    {
        $key = PublicKeyLoader::load('-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg7+qVCtyt+tV2hTou
kbZNIHu+PaE0osExnxdlkiC+VYqhRANCAAS8yEueJvIAnCk++0rsD8X9dk3hAmyb
4lv6WkjCQU5iksxIG/E60L8IeDZX8+oNzHPjNN5/6MBk0ISrGKyFhlH1
-----END PRIVATE KEY-----');

        $priv = $key->withSignatureFormat('IEEE');
        $sig = $priv->sign('ddd');

        $this->assertTrue($key->getPublicKey()->withSignatureFormat('IEEE')->verify('ddd', $sig));
    }
}