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));
}
}
|