github.com/opentofu/opentofu@v1.7.1/internal/lang/funcs/crypto_test.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package funcs 7 8 import ( 9 "fmt" 10 "testing" 11 12 "github.com/zclconf/go-cty/cty" 13 "golang.org/x/crypto/bcrypt" 14 ) 15 16 func TestUUID(t *testing.T) { 17 result, err := UUID() 18 if err != nil { 19 t.Fatal(err) 20 } 21 22 resultStr := result.AsString() 23 if got, want := len(resultStr), 36; got != want { 24 t.Errorf("wrong result length %d; want %d", got, want) 25 } 26 } 27 28 func TestUUIDV5(t *testing.T) { 29 tests := []struct { 30 Namespace cty.Value 31 Name cty.Value 32 Want cty.Value 33 Err bool 34 }{ 35 { 36 cty.StringVal("dns"), 37 cty.StringVal("tada"), 38 cty.StringVal("faa898db-9b9d-5b75-86a9-149e7bb8e3b8"), 39 false, 40 }, 41 { 42 cty.StringVal("url"), 43 cty.StringVal("tada"), 44 cty.StringVal("2c1ff6b4-211f-577e-94de-d978b0caa16e"), 45 false, 46 }, 47 { 48 cty.StringVal("oid"), 49 cty.StringVal("tada"), 50 cty.StringVal("61eeea26-5176-5288-87fc-232d6ed30d2f"), 51 false, 52 }, 53 { 54 cty.StringVal("x500"), 55 cty.StringVal("tada"), 56 cty.StringVal("7e12415e-f7c9-57c3-9e43-52dc9950d264"), 57 false, 58 }, 59 { 60 cty.StringVal("6ba7b810-9dad-11d1-80b4-00c04fd430c8"), 61 cty.StringVal("tada"), 62 cty.StringVal("faa898db-9b9d-5b75-86a9-149e7bb8e3b8"), 63 false, 64 }, 65 { 66 cty.StringVal("tada"), 67 cty.StringVal("tada"), 68 cty.UnknownVal(cty.String), 69 true, 70 }, 71 } 72 73 for _, test := range tests { 74 t.Run(fmt.Sprintf("uuidv5(%#v, %#v)", test.Namespace, test.Name), func(t *testing.T) { 75 got, err := UUIDV5(test.Namespace, test.Name) 76 77 if test.Err { 78 if err == nil { 79 t.Fatal("succeeded; want error") 80 } 81 return 82 } else if err != nil { 83 t.Fatalf("unexpected error: %s", err) 84 } 85 86 if !got.RawEquals(test.Want) { 87 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 88 } 89 }) 90 } 91 } 92 93 func TestBase64Sha256(t *testing.T) { 94 tests := []struct { 95 String cty.Value 96 Want cty.Value 97 Err bool 98 }{ 99 { 100 cty.StringVal("test"), 101 cty.StringVal("n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="), 102 false, 103 }, 104 // This would differ because we're base64-encoding hex represantiation, not raw bytes. 105 // base64encode(sha256("test")) = 106 // "OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZjMTViMGYwMGEwOA==" 107 } 108 109 for _, test := range tests { 110 t.Run(fmt.Sprintf("base64sha256(%#v)", test.String), func(t *testing.T) { 111 got, err := Base64Sha256(test.String) 112 113 if test.Err { 114 if err == nil { 115 t.Fatal("succeeded; want error") 116 } 117 return 118 } else if err != nil { 119 t.Fatalf("unexpected error: %s", err) 120 } 121 122 if !got.RawEquals(test.Want) { 123 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 124 } 125 }) 126 } 127 } 128 129 func TestFileBase64Sha256(t *testing.T) { 130 tests := []struct { 131 Path cty.Value 132 Want cty.Value 133 Err bool 134 }{ 135 { 136 cty.StringVal("testdata/hello.txt"), 137 cty.StringVal("pZGm1Av0IEBKARczz7exkNYsZb8LzaMrV7J32a2fFG4="), 138 false, 139 }, 140 { 141 cty.StringVal("testdata/icon.png"), 142 cty.StringVal("bun9+lNwoWcTxEze5pVIDfsf+mPDMtVUKZp04RCLHTc="), 143 false, 144 }, 145 { 146 cty.StringVal("testdata/missing"), 147 cty.NilVal, 148 true, // no file exists 149 }, 150 } 151 152 fileSHA256 := MakeFileBase64Sha256Func(".") 153 154 for _, test := range tests { 155 t.Run(fmt.Sprintf("filebase64sha256(%#v)", test.Path), func(t *testing.T) { 156 got, err := fileSHA256.Call([]cty.Value{test.Path}) 157 158 if test.Err { 159 if err == nil { 160 t.Fatal("succeeded; want error") 161 } 162 return 163 } else if err != nil { 164 t.Fatalf("unexpected error: %s", err) 165 } 166 167 if !got.RawEquals(test.Want) { 168 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 169 } 170 }) 171 } 172 } 173 174 func TestBase64Sha512(t *testing.T) { 175 tests := []struct { 176 String cty.Value 177 Want cty.Value 178 Err bool 179 }{ 180 { 181 cty.StringVal("test"), 182 cty.StringVal("7iaw3Ur350mqGo7jwQrpkj9hiYB3Lkc/iBml1JQODbJ6wYX4oOHV+E+IvIh/1nsUNzLDBMxfqa2Ob1f1ACio/w=="), 183 false, 184 }, 185 // This would differ because we're base64-encoding hex represantiation, not raw bytes 186 // base64encode(sha512("test")) = 187 // "OZWUyNmIwZGQ0YWY3ZTc0OWFhMWE4ZWUzYzEwYWU5OTIzZjYxODk4MDc3MmU0NzNmODgxOWE1ZDQ5NDBlMGRiMjdhYzE4NWY4YTBlMWQ1Zjg0Zjg4YmM4ODdmZDY3YjE0MzczMmMzMDRjYzVmYTlhZDhlNmY1N2Y1MDAyOGE4ZmY=" 188 } 189 190 for _, test := range tests { 191 t.Run(fmt.Sprintf("base64sha512(%#v)", test.String), func(t *testing.T) { 192 got, err := Base64Sha512(test.String) 193 194 if test.Err { 195 if err == nil { 196 t.Fatal("succeeded; want error") 197 } 198 return 199 } else if err != nil { 200 t.Fatalf("unexpected error: %s", err) 201 } 202 203 if !got.RawEquals(test.Want) { 204 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 205 } 206 }) 207 } 208 } 209 210 func TestFileBase64Sha512(t *testing.T) { 211 tests := []struct { 212 Path cty.Value 213 Want cty.Value 214 Err bool 215 }{ 216 { 217 cty.StringVal("testdata/hello.txt"), 218 cty.StringVal("LHT9F+2v2A6ER7DUZ0HuJDt+t03SFJoKsbkkb7MDgvJ+hT2FhXGeDmfL2g2qj1FnEGRhXWRa4nrLFb+xRH9Fmw=="), 219 false, 220 }, 221 { 222 cty.StringVal("testdata/icon.png"), 223 cty.StringVal("9FcRPvMPKG/8OO+zJpVnl3NZXBQEwOh3bBfrSh0boTkYvo6pq3xidR6ZuG/6rPnE0p7+rTYRfD3AVxdst62n9g=="), 224 false, 225 }, 226 { 227 cty.StringVal("testdata/missing"), 228 cty.NilVal, 229 true, // no file exists 230 }, 231 } 232 233 fileSHA512 := MakeFileBase64Sha512Func(".") 234 235 for _, test := range tests { 236 t.Run(fmt.Sprintf("filebase64sha512(%#v)", test.Path), func(t *testing.T) { 237 got, err := fileSHA512.Call([]cty.Value{test.Path}) 238 239 if test.Err { 240 if err == nil { 241 t.Fatal("succeeded; want error") 242 } 243 return 244 } else if err != nil { 245 t.Fatalf("unexpected error: %s", err) 246 } 247 248 if !got.RawEquals(test.Want) { 249 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 250 } 251 }) 252 } 253 } 254 255 func TestBcrypt(t *testing.T) { 256 // single variable test 257 p, err := Bcrypt(cty.StringVal("test")) 258 if err != nil { 259 t.Fatalf("err: %s", err) 260 } 261 262 err = bcrypt.CompareHashAndPassword([]byte(p.AsString()), []byte("test")) 263 if err != nil { 264 t.Fatalf("Error comparing hash and password: %s", err) 265 } 266 267 // testing with two parameters 268 p, err = Bcrypt(cty.StringVal("test"), cty.NumberIntVal(5)) 269 if err != nil { 270 t.Fatalf("err: %s", err) 271 } 272 273 err = bcrypt.CompareHashAndPassword([]byte(p.AsString()), []byte("test")) 274 if err != nil { 275 t.Fatalf("Error comparing hash and password: %s", err) 276 } 277 278 // Negative test for more than two parameters 279 _, err = Bcrypt(cty.StringVal("test"), cty.NumberIntVal(10), cty.NumberIntVal(11)) 280 if err == nil { 281 t.Fatal("succeeded; want error") 282 } 283 } 284 285 func TestMd5(t *testing.T) { 286 tests := []struct { 287 String cty.Value 288 Want cty.Value 289 Err bool 290 }{ 291 { 292 cty.StringVal("tada"), 293 cty.StringVal("ce47d07243bb6eaf5e1322c81baf9bbf"), 294 false, 295 }, 296 { // Confirm that we're not trimming any whitespaces 297 cty.StringVal(" tada "), 298 cty.StringVal("aadf191a583e53062de2d02c008141c4"), 299 false, 300 }, 301 { // We accept empty string too 302 cty.StringVal(""), 303 cty.StringVal("d41d8cd98f00b204e9800998ecf8427e"), 304 false, 305 }, 306 } 307 308 for _, test := range tests { 309 t.Run(fmt.Sprintf("md5(%#v)", test.String), func(t *testing.T) { 310 got, err := Md5(test.String) 311 312 if test.Err { 313 if err == nil { 314 t.Fatal("succeeded; want error") 315 } 316 return 317 } else if err != nil { 318 t.Fatalf("unexpected error: %s", err) 319 } 320 321 if !got.RawEquals(test.Want) { 322 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 323 } 324 }) 325 } 326 } 327 328 func TestFileMD5(t *testing.T) { 329 tests := []struct { 330 Path cty.Value 331 Want cty.Value 332 Err bool 333 }{ 334 { 335 cty.StringVal("testdata/hello.txt"), 336 cty.StringVal("b10a8db164e0754105b7a99be72e3fe5"), 337 false, 338 }, 339 { 340 cty.StringVal("testdata/icon.png"), 341 cty.StringVal("a18e1dd95427740ff7c7654ecc0280ad"), 342 false, 343 }, 344 { 345 cty.StringVal("testdata/missing"), 346 cty.NilVal, 347 true, // no file exists 348 }, 349 } 350 351 fileMD5 := MakeFileMd5Func(".") 352 353 for _, test := range tests { 354 t.Run(fmt.Sprintf("filemd5(%#v)", test.Path), func(t *testing.T) { 355 got, err := fileMD5.Call([]cty.Value{test.Path}) 356 357 if test.Err { 358 if err == nil { 359 t.Fatal("succeeded; want error") 360 } 361 return 362 } else if err != nil { 363 t.Fatalf("unexpected error: %s", err) 364 } 365 366 if !got.RawEquals(test.Want) { 367 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 368 } 369 }) 370 } 371 } 372 373 func TestRsaDecrypt(t *testing.T) { 374 tests := []struct { 375 Ciphertext cty.Value 376 Privatekey cty.Value 377 Want cty.Value 378 Err string 379 }{ 380 // Base-64 encoded cipher decrypts correctly 381 { 382 cty.StringVal(CipherBase64), 383 cty.StringVal(PrivateKey), 384 cty.StringVal("message"), 385 "", 386 }, 387 // OpenSSH key format 388 { 389 cty.StringVal(CipherBase64), 390 cty.StringVal(OpenSSHPrivateKey), 391 cty.StringVal("message"), 392 "", 393 }, 394 // Wrong key 395 { 396 cty.StringVal(CipherBase64), 397 cty.StringVal(WrongPrivateKey), 398 cty.UnknownVal(cty.String), 399 "failed to decrypt: crypto/rsa: decryption error", 400 }, 401 // Bad key 402 { 403 cty.StringVal(CipherBase64), 404 cty.StringVal(BadPrivateKey), 405 cty.UnknownVal(cty.String), 406 "invalid ASN1 data in the given private key: data truncated", 407 }, 408 // Empty key 409 { 410 cty.StringVal(CipherBase64), 411 cty.StringVal(""), 412 cty.UnknownVal(cty.String), 413 "invalid private key: ssh: no key found", 414 }, 415 // Bad ciphertext 416 { 417 cty.StringVal("bad"), 418 cty.StringVal(PrivateKey), 419 cty.UnknownVal(cty.String), 420 `failed to decode input "bad": cipher text must be base64-encoded`, 421 }, 422 // Empty ciphertext 423 { 424 cty.StringVal(""), 425 cty.StringVal(PrivateKey), 426 cty.UnknownVal(cty.String), 427 "failed to decrypt: crypto/rsa: decryption error", 428 }, 429 } 430 for _, test := range tests { 431 t.Run(fmt.Sprintf("RsaDecrypt(%#v, %#v)", test.Ciphertext, test.Privatekey), func(t *testing.T) { 432 got, err := RsaDecrypt(test.Ciphertext, test.Privatekey) 433 434 if test.Err != "" { 435 if err == nil { 436 t.Fatal("succeeded; want error") 437 } else if err.Error() != test.Err { 438 t.Fatalf("wrong error\ngot: %s\nwant: %s", err.Error(), test.Err) 439 } 440 return 441 } else if err != nil { 442 t.Fatalf("unexpected error: %s", err) 443 } 444 445 if !got.RawEquals(test.Want) { 446 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 447 } 448 }) 449 } 450 } 451 452 func TestSha1(t *testing.T) { 453 tests := []struct { 454 String cty.Value 455 Want cty.Value 456 Err bool 457 }{ 458 { 459 cty.StringVal("test"), 460 cty.StringVal("a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"), 461 false, 462 }, 463 } 464 465 for _, test := range tests { 466 t.Run(fmt.Sprintf("sha1(%#v)", test.String), func(t *testing.T) { 467 got, err := Sha1(test.String) 468 469 if test.Err { 470 if err == nil { 471 t.Fatal("succeeded; want error") 472 } 473 return 474 } else if err != nil { 475 t.Fatalf("unexpected error: %s", err) 476 } 477 478 if !got.RawEquals(test.Want) { 479 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 480 } 481 }) 482 } 483 } 484 485 func TestFileSHA1(t *testing.T) { 486 tests := []struct { 487 Path cty.Value 488 Want cty.Value 489 Err bool 490 }{ 491 { 492 cty.StringVal("testdata/hello.txt"), 493 cty.StringVal("0a4d55a8d778e5022fab701977c5d840bbc486d0"), 494 false, 495 }, 496 { 497 cty.StringVal("testdata/icon.png"), 498 cty.StringVal("90ecc70d12bc0bca6efa8d5cc8b35091fb087686"), 499 false, 500 }, 501 { 502 cty.StringVal("testdata/missing"), 503 cty.NilVal, 504 true, // no file exists 505 }, 506 } 507 508 fileSHA1 := MakeFileSha1Func(".") 509 510 for _, test := range tests { 511 t.Run(fmt.Sprintf("filesha1(%#v)", test.Path), func(t *testing.T) { 512 got, err := fileSHA1.Call([]cty.Value{test.Path}) 513 514 if test.Err { 515 if err == nil { 516 t.Fatal("succeeded; want error") 517 } 518 return 519 } else if err != nil { 520 t.Fatalf("unexpected error: %s", err) 521 } 522 523 if !got.RawEquals(test.Want) { 524 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 525 } 526 }) 527 } 528 } 529 530 func TestSha256(t *testing.T) { 531 tests := []struct { 532 String cty.Value 533 Want cty.Value 534 Err bool 535 }{ 536 { 537 cty.StringVal("test"), 538 cty.StringVal("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"), 539 false, 540 }, 541 } 542 543 for _, test := range tests { 544 t.Run(fmt.Sprintf("sha256(%#v)", test.String), func(t *testing.T) { 545 got, err := Sha256(test.String) 546 547 if test.Err { 548 if err == nil { 549 t.Fatal("succeeded; want error") 550 } 551 return 552 } else if err != nil { 553 t.Fatalf("unexpected error: %s", err) 554 } 555 556 if !got.RawEquals(test.Want) { 557 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 558 } 559 }) 560 } 561 } 562 563 func TestFileSHA256(t *testing.T) { 564 tests := []struct { 565 Path cty.Value 566 Want cty.Value 567 Err bool 568 }{ 569 { 570 cty.StringVal("testdata/hello.txt"), 571 cty.StringVal("a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"), 572 false, 573 }, 574 { 575 cty.StringVal("testdata/icon.png"), 576 cty.StringVal("6ee9fdfa5370a16713c44cdee695480dfb1ffa63c332d554299a74e1108b1d37"), 577 false, 578 }, 579 { 580 cty.StringVal("testdata/missing"), 581 cty.NilVal, 582 true, // no file exists 583 }, 584 } 585 586 fileSHA256 := MakeFileSha256Func(".") 587 588 for _, test := range tests { 589 t.Run(fmt.Sprintf("filesha256(%#v)", test.Path), func(t *testing.T) { 590 got, err := fileSHA256.Call([]cty.Value{test.Path}) 591 592 if test.Err { 593 if err == nil { 594 t.Fatal("succeeded; want error") 595 } 596 return 597 } else if err != nil { 598 t.Fatalf("unexpected error: %s", err) 599 } 600 601 if !got.RawEquals(test.Want) { 602 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 603 } 604 }) 605 } 606 } 607 608 func TestSha512(t *testing.T) { 609 tests := []struct { 610 String cty.Value 611 Want cty.Value 612 Err bool 613 }{ 614 { 615 cty.StringVal("test"), 616 cty.StringVal("ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"), 617 false, 618 }, 619 } 620 621 for _, test := range tests { 622 t.Run(fmt.Sprintf("sha512(%#v)", test.String), func(t *testing.T) { 623 got, err := Sha512(test.String) 624 625 if test.Err { 626 if err == nil { 627 t.Fatal("succeeded; want error") 628 } 629 return 630 } else if err != nil { 631 t.Fatalf("unexpected error: %s", err) 632 } 633 634 if !got.RawEquals(test.Want) { 635 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 636 } 637 }) 638 } 639 } 640 641 func TestFileSHA512(t *testing.T) { 642 tests := []struct { 643 Path cty.Value 644 Want cty.Value 645 Err bool 646 }{ 647 { 648 cty.StringVal("testdata/hello.txt"), 649 cty.StringVal("2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b"), 650 false, 651 }, 652 { 653 cty.StringVal("testdata/icon.png"), 654 cty.StringVal("f457113ef30f286ffc38efb32695679773595c1404c0e8776c17eb4a1d1ba13918be8ea9ab7c62751e99b86ffaacf9c4d29efead36117c3dc057176cb7ada7f6"), 655 false, 656 }, 657 { 658 cty.StringVal("testdata/missing"), 659 cty.NilVal, 660 true, // no file exists 661 }, 662 } 663 664 fileSHA512 := MakeFileSha512Func(".") 665 666 for _, test := range tests { 667 t.Run(fmt.Sprintf("filesha512(%#v)", test.Path), func(t *testing.T) { 668 got, err := fileSHA512.Call([]cty.Value{test.Path}) 669 670 if test.Err { 671 if err == nil { 672 t.Fatal("succeeded; want error") 673 } 674 return 675 } else if err != nil { 676 t.Fatalf("unexpected error: %s", err) 677 } 678 679 if !got.RawEquals(test.Want) { 680 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 681 } 682 }) 683 } 684 } 685 686 const ( 687 CipherBase64 = "eczGaDhXDbOFRZGhjx2etVzWbRqWDlmq0bvNt284JHVbwCgObiuyX9uV0LSAMY707IEgMkExJqXmsB4OWKxvB7epRB9G/3+F+pcrQpODlDuL9oDUAsa65zEpYF0Wbn7Oh7nrMQncyUPpyr9WUlALl0gRWytOA23S+y5joa4M34KFpawFgoqTu/2EEH4Xl1zo+0fy73fEto+nfkUY+meuyGZ1nUx/+DljP7ZqxHBFSlLODmtuTMdswUbHbXbWneW51D7Jm7xB8nSdiA2JQNK5+Sg5x8aNfgvFTt/m2w2+qpsyFa5Wjeu6fZmXSl840CA07aXbk9vN4I81WmJyblD/ZA==" 688 PrivateKey = ` 689 -----BEGIN RSA PRIVATE KEY----- 690 MIIEowIBAAKCAQEAgUElV5mwqkloIrM8ZNZ72gSCcnSJt7+/Usa5G+D15YQUAdf9 691 c1zEekTfHgDP+04nw/uFNFaE5v1RbHaPxhZYVg5ZErNCa/hzn+x10xzcepeS3KPV 692 Xcxae4MR0BEegvqZqJzN9loXsNL/c3H/B+2Gle3hTxjlWFb3F5qLgR+4Mf4ruhER 693 1v6eHQa/nchi03MBpT4UeJ7MrL92hTJYLdpSyCqmr8yjxkKJDVC2uRrr+sTSxfh7 694 r6v24u/vp/QTmBIAlNPgadVAZw17iNNb7vjV7Gwl/5gHXonCUKURaV++dBNLrHIZ 695 pqcAM8wHRph8mD1EfL9hsz77pHewxolBATV+7QIDAQABAoIBAC1rK+kFW3vrAYm3 696 +8/fQnQQw5nec4o6+crng6JVQXLeH32qXShNf8kLLG/Jj0vaYcTPPDZw9JCKkTMQ 697 0mKj9XR/5DLbBMsV6eNXXuvJJ3x4iKW5eD9WkLD4FKlNarBRyO7j8sfPTqXW7uat 698 NxWdFH7YsSRvNh/9pyQHLWA5OituidMrYbc3EUx8B1GPNyJ9W8Q8znNYLfwYOjU4 699 Wv1SLE6qGQQH9Q0WzA2WUf8jklCYyMYTIywAjGb8kbAJlKhmj2t2Igjmqtwt1PYc 700 pGlqbtQBDUiWXt5S4YX/1maIQ/49yeNUajjpbJiH3DbhJbHwFTzP3pZ9P9GHOzlG 701 kYR+wSECgYEAw/Xida8kSv8n86V3qSY/I+fYQ5V+jDtXIE+JhRnS8xzbOzz3v0WS 702 Oo5H+o4nJx5eL3Ghb3Gcm0Jn46dHrxinHbm+3RjXv/X6tlbxIYjRSQfHOTSMCTvd 703 qcliF5vC6RCLXuc7R+IWR1Ky6eDEZGtrvt3DyeYABsp9fRUFR/6NluUCgYEAqNsw 704 1aSl7WJa27F0DoJdlU9LWerpXcazlJcIdOz/S9QDmSK3RDQTdqfTxRmrxiYI9LEs 705 mkOkvzlnnOBMpnZ3ZOU5qIRfprecRIi37KDAOHWGnlC0EWGgl46YLb7/jXiWf0AG 706 Y+DfJJNd9i6TbIDWu8254/erAS6bKMhW/3q7f2kCgYAZ7Id/BiKJAWRpqTRBXlvw 707 BhXoKvjI2HjYP21z/EyZ+PFPzur/lNaZhIUlMnUfibbwE9pFggQzzf8scM7c7Sf+ 708 mLoVSdoQ/Rujz7CqvQzi2nKSsM7t0curUIb3lJWee5/UeEaxZcmIufoNUrzohAWH 709 BJOIPDM4ssUTLRq7wYM9uQKBgHCBau5OP8gE6mjKuXsZXWUoahpFLKwwwmJUp2vQ 710 pOFPJ/6WZOlqkTVT6QPAcPUbTohKrF80hsZqZyDdSfT3peFx4ZLocBrS56m6NmHR 711 UYHMvJ8rQm76T1fryHVidz85g3zRmfBeWg8yqT5oFg4LYgfLsPm1gRjOhs8LfPvI 712 OLlRAoGBAIZ5Uv4Z3s8O7WKXXUe/lq6j7vfiVkR1NW/Z/WLKXZpnmvJ7FgxN4e56 713 RXT7GwNQHIY8eDjDnsHxzrxd+raOxOZeKcMHj3XyjCX3NHfTscnsBPAGYpY/Wxzh 714 T8UYnFu6RzkixElTf2rseEav7rkdKkI3LAeIZy7B0HulKKsmqVQ7 715 -----END RSA PRIVATE KEY----- 716 ` 717 OpenSSHPrivateKey = ` 718 -----BEGIN OPENSSH PRIVATE KEY----- 719 b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn 720 NhAAAAAwEAAQAAAQEAgUElV5mwqkloIrM8ZNZ72gSCcnSJt7+/Usa5G+D15YQUAdf9c1zE 721 ekTfHgDP+04nw/uFNFaE5v1RbHaPxhZYVg5ZErNCa/hzn+x10xzcepeS3KPVXcxae4MR0B 722 EegvqZqJzN9loXsNL/c3H/B+2Gle3hTxjlWFb3F5qLgR+4Mf4ruhER1v6eHQa/nchi03MB 723 pT4UeJ7MrL92hTJYLdpSyCqmr8yjxkKJDVC2uRrr+sTSxfh7r6v24u/vp/QTmBIAlNPgad 724 VAZw17iNNb7vjV7Gwl/5gHXonCUKURaV++dBNLrHIZpqcAM8wHRph8mD1EfL9hsz77pHew 725 xolBATV+7QAAA7jbhEFk24RBZAAAAAdzc2gtcnNhAAABAQCBQSVXmbCqSWgiszxk1nvaBI 726 JydIm3v79Sxrkb4PXlhBQB1/1zXMR6RN8eAM/7TifD+4U0VoTm/VFsdo/GFlhWDlkSs0Jr 727 +HOf7HXTHNx6l5Lco9VdzFp7gxHQER6C+pmonM32Whew0v9zcf8H7YaV7eFPGOVYVvcXmo 728 uBH7gx/iu6ERHW/p4dBr+dyGLTcwGlPhR4nsysv3aFMlgt2lLIKqavzKPGQokNULa5Guv6 729 xNLF+Huvq/bi7++n9BOYEgCU0+Bp1UBnDXuI01vu+NXsbCX/mAdeicJQpRFpX750E0usch 730 mmpwAzzAdGmHyYPUR8v2GzPvukd7DGiUEBNX7tAAAAAwEAAQAAAQAtayvpBVt76wGJt/vP 731 30J0EMOZ3nOKOvnK54OiVUFy3h99ql0oTX/JCyxvyY9L2mHEzzw2cPSQipEzENJio/V0f+ 732 Qy2wTLFenjV17rySd8eIiluXg/VpCw+BSpTWqwUcju4/LHz06l1u7mrTcVnRR+2LEkbzYf 733 /ackBy1gOTorbonTK2G3NxFMfAdRjzcifVvEPM5zWC38GDo1OFr9UixOqhkEB/UNFswNll 734 H/I5JQmMjGEyMsAIxm/JGwCZSoZo9rdiII5qrcLdT2HKRpam7UAQ1Ill7eUuGF/9ZmiEP+ 735 PcnjVGo46WyYh9w24SWx8BU8z96WfT/Rhzs5RpGEfsEhAAAAgQCGeVL+Gd7PDu1il11Hv5 736 auo+734lZEdTVv2f1iyl2aZ5ryexYMTeHuekV0+xsDUByGPHg4w57B8c68Xfq2jsTmXinD 737 B4918owl9zR307HJ7ATwBmKWP1sc4U/FGJxbukc5IsRJU39q7HhGr+65HSpCNywHiGcuwd 738 B7pSirJqlUOwAAAIEAw/Xida8kSv8n86V3qSY/I+fYQ5V+jDtXIE+JhRnS8xzbOzz3v0WS 739 Oo5H+o4nJx5eL3Ghb3Gcm0Jn46dHrxinHbm+3RjXv/X6tlbxIYjRSQfHOTSMCTvdqcliF5 740 vC6RCLXuc7R+IWR1Ky6eDEZGtrvt3DyeYABsp9fRUFR/6NluUAAACBAKjbMNWkpe1iWtux 741 dA6CXZVPS1nq6V3Gs5SXCHTs/0vUA5kit0Q0E3an08UZq8YmCPSxLJpDpL85Z5zgTKZ2d2 742 TlOaiEX6a3nESIt+ygwDh1hp5QtBFhoJeOmC2+/414ln9ABmPg3ySTXfYuk2yA1rvNueP3 743 qwEumyjIVv96u39pAAAAAAEC 744 -----END OPENSSH PRIVATE KEY----- 745 ` 746 WrongPrivateKey = ` 747 -----BEGIN RSA PRIVATE KEY----- 748 MIIEowIBAAKCAQEAlrCgnEVgmNKCq7KPc+zUU5IrxPu1ClMNJS7RTsTPEkbwe5SB 749 p+6V6WtCbD/X/lDRRGbOENChh1Phulb7lViqgrdpHydgsrKoS5ah3DfSIxLFLE00 750 9Yo4TCYwgw6+s59j16ZAFVinaQ9l6Kmrb2ll136hMrz8QKh+qw+onOLd38WFgm+W 751 ZtUqSXf2LANzfzzy4OWFNyFqKaCAolSkPdTS9Nz+svtScvp002DQp8OdP1AgPO+l 752 o5N3M38Fftapwg0pCtJ5Zq0NRWIXEonXiTEMA6zy3gEZVOmDxoIFUWnmrqlMJLFy 753 5S6LDrHSdqJhCxDK6WRZj43X9j8spktk3eGhMwIDAQABAoIBAAem8ID/BOi9x+Tw 754 LFi2rhGQWqimH4tmrEQ3HGnjlKBY+d1MrUjZ1MMFr1nP5CgF8pqGnfA8p/c3Sz8r 755 K5tp5T6+EZiDZ2WrrOApxg5ox0MAsQKO6SGO40z6o3wEQ6rbbTaGOrraxaWQIpyu 756 AQanU4Sd6ZGqByVBaS1GnklZO+shCHqw73b7g1cpLEmFzcYnKHYHlUUIsstMe8E1 757 BaCY0CH7JbWBjcbiTnBVwIRZuu+EjGiQuhTilYL2OWqoMVg1WU0L2IFpR8lkf/2W 758 SBx5J6xhwbBGASOpM+qidiN580GdPzGhWYSqKGroHEzBm6xPSmV1tadNA26WFG4p 759 pthLiAECgYEA5BsPRpNYJAQLu5B0N7mj9eEp0HABVEgL/MpwiImjaKdAwp78HM64 760 IuPvJxs7r+xESiIz4JyjR8zrQjYOCKJsARYkmNlEuAz0SkHabCw1BdEBwUhjUGVB 761 efoERK6GxfAoNqmSDwsOvHFOtsmDIlbHmg7G2rUxNVpeou415BSB0B8CgYEAqR4J 762 YHKk2Ibr9rU+rBU33TcdTGw0aAkFNAVeqM9j0haWuFXmV3RArgoy09lH+2Ha6z/g 763 fTX2xSDAWV7QUlLOlBRIhurPAo2jO2yCrGHPZcWiugstrR2hTTInigaSnCmK3i7F 764 6sYmL3S7K01IcVNxSlWvGijtClT92Cl2WUCTfG0CgYAiEjyk4QtQTd5mxLvnOu5X 765 oqs5PBGmwiAwQRiv/EcRMbJFn7Oupd3xMDSflbzDmTnWDOfMy/jDl8MoH6TW+1PA 766 kcsjnYhbKWwvz0hN0giVdtOZSDO1ZXpzOrn6fEsbM7T9/TQY1SD9WrtUKCNTNL0Z 767 sM1ZC6lu+7GZCpW4HKwLJwKBgQCRT0yxQXBg1/UxwuO5ynV4rx2Oh76z0WRWIXMH 768 S0MyxdP1SWGkrS/SGtM3cg/GcHtA/V6vV0nUcWK0p6IJyjrTw2XZ/zGluPuTWJYi 769 9dvVT26Vunshrz7kbH7KuwEICy3V4IyQQHeY+QzFlR70uMS0IVFWAepCoWqHbIDT 770 CYhwNQKBgGPcLXmjpGtkZvggl0aZr9LsvCTckllSCFSI861kivL/rijdNoCHGxZv 771 dfDkLTLcz9Gk41rD9Gxn/3sqodnTAc3Z2PxFnzg1Q/u3+x6YAgBwI/g/jE2xutGW 772 H7CurtMwALQ/n/6LUKFmjRZjqbKX9SO2QSaC3grd6sY9Tu+bZjLe 773 -----END RSA PRIVATE KEY----- 774 ` 775 BadPrivateKey = ` 776 -----BEGIN RSA PRIVATE KEY----- 777 MIIEowIBAAKCAQEAgUElV5mwqkloIrM8ZNZ72gSCcnSJt7+/Usa5G+D15YQUAdf9 778 c1zEekTfHgDP+04nw/uFNFaE5v1RbHaPxhZYVg5ZErNCa/hzn+x10xzcepeS3KPV 779 Xcxae4MR0BEegvqZqJzN9loXsNL/c3H/B+2Gle3hTxjlWFb3F5qLgR+4Mf4ruhER 780 1v6eHQa/nchi03MBpT4UeJ7MrL92hTJYLdpSyCqmr8yjxkKJDVC2uRrr+sTSxfh7 781 r6v24u/vp/QTmBIAlNPgadVAZw17iNNb7vjV7Gwl/5gHXonCUKURaV++dBNLrHIZ 782 pqcAM8wHRph8mD1EfL9hsz77pHewxolBATV+7QIDAQABAoIBAC1rK+kFW3vrAYm3 783 +8/fQnQQw5nec4o6+crng6JVQXLeH32qXShNf8kLLG/Jj0vaYcTPPDZw9JCKkTMQ 784 0mKj9XR/5DLbBMsV6eNXXuvJJ3x4iKW5eD9WkLD4FKlNarBRyO7j8sfPTqXW7uat 785 NxWdFH7YsSRvNh/9pyQHLWA5OituidMrYbc3EUx8B1GPNyJ9W8Q8znNYLfwYOjU4 786 Wv1SLE6qGQQH9Q0WzA2WUf8jklCYyMYTIywAjGb8kbAJlKhmj2t2Igjmqtwt1PYc 787 pGlqbtQBDUiWXt5S4YX/1maIQ/49yeNUajjpbJiH3DbhJbHwFTzP3pZ9P9GHOzlG 788 kYR+wSECgYEAw/Xida8kSv8n86V3qSY/I+fYQ5V+jDtXIE+JhRnS8xzbOzz3v0WS 789 Oo5H+o4nJx5eL3Ghb3Gcm0Jn46dHrxinHbm+3RjXv/X6tlbxIYjRSQfHOTSMCTvd 790 qcliF5vC6RCLXuc7R+IWR1Ky6eDEZGtrvt3DyeYABsp9fRUFR/6NluUCgYEAqNsw 791 1aSl7WJa27F0DoJdlU9LWerpXcazlJcIdOz/S9QDmSK3RDQTdqfTxRmrxiYI9LEs 792 mkOkvzlnnOBMpnZ3ZOU5qIRfprecRIi37KDAOHWGnlC0EWGgl46YLb7/jXiWf0AG 793 BhXoKvjI2HjYP21z/EyZ+PFPzur/lNaZhIUlMnUfibbwE9pFggQzzf8scM7c7Sf+ 794 mLoVSdoQ/Rujz7CqvQzi2nKSsM7t0curUIb3lJWee5/UeEaxZcmIufoNUrzohAWH 795 BJOIPDM4ssUTLRq7wYM9uQKBgHCBau5OP8gE6mjKuXsZXWUoahpFLKwwwmJUp2vQ 796 pOFPJ/6WZOlqkTVT6QPAcPUbTohKrF80hsZqZyDdSfT3peFx4ZLocBrS56m6NmHR 797 UYHMvJ8rQm76T1fryHVidz85g3zRmfBeWg8yqT5oFg4LYgfLsPm1gRjOhs8LfPvI 798 OLlRAoGBAIZ5Uv4Z3s8O7WKXXUe/lq6j7vfiVkR1NW/Z/WLKXZpnmvJ7FgxN4e56 799 RXT7GwNQHIY8eDjDnsHxzrxd+raOxOZeKcMHj3XyjCX3NHfTscnsBPAGYpY/Wxzh 800 T8UYnFu6RzkixElTf2rseEav7rkdKkI3LAeIZy7B0HulKKsmqVQ7 801 -----END RSA PRIVATE KEY----- 802 ` 803 )