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