github.com/boxboat/in-toto-golang@v0.0.3-0.20210303203820-2fa16ecbe6f6/in_toto/model_test.go (about) 1 package in_toto 2 3 import ( 4 "encoding/hex" 5 "errors" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "reflect" 10 "strings" 11 "testing" 12 ) 13 14 func TestMatchEcdsaScheme(t *testing.T) { 15 curveSize := 224 16 scheme := "ecdsa-sha2-nistp512" 17 if err := matchEcdsaScheme(curveSize, scheme); err == nil { 18 t.Errorf("matchEcdsaScheme should have failed with curveSize: %d and scheme: %s", curveSize, scheme) 19 } 20 } 21 22 func TestMetablockLoad(t *testing.T) { 23 // Create a bunch of tmp json files with invalid format and test load errors: 24 // - invalid json 25 // - missing signatures and signed field 26 // - invalid signatures field 27 // - invalid signed field 28 // - invalid signed type 29 // - invalid signed field for type link 30 // - invalid signed field for type layout 31 invalidJSONBytes := [][]byte{ 32 []byte("{"), 33 []byte("{}"), 34 []byte(`{"signatures": null, "signed": {}}`), 35 []byte(`{"signatures": "string", "signed": {}}`), 36 []byte(`{"signatures": [], "signed": []}`), 37 []byte(`{"signatures": [], "signed": {"_type": "something else"}}`), 38 []byte(`{"signatures": [], "signed": {"_type": "link", 39 "materials": "invalid", "name": "some name", "products": "invalid", 40 "byproducts": "invalid", "command": "some command", 41 "environment": "some list"}}`), 42 []byte(`{"signatures": [], "signed": {"_type": "layout", 43 "steps": "invalid", "inspect": "invalid", "readme": "some readme", 44 "keys": "some keys", "expires": "some date", "rootcas": [], "intermediatecas": []}}`), 45 []byte(`{"signatures": [], "signed": {"_type": "layout", 46 "inspect": "invalid", "readme": "some readme", "keys": "some keys", 47 "expires": "some date", "rootcas": [], "intermediatecas": []}}`), 48 []byte(`{"signatures": [], "signed": {"_type": "layout", 49 "steps": "invalid", "readme": "some readme", "keys": "some keys", 50 "expires": "some date", "rootcas": [], "intermediatecas": []}}`), 51 []byte(`{"signatures": [], "signed": {"_type": "layout", 52 "steps": "invalid", "inspect": "invalid", "readme": "some readme", 53 "expires": "some date", "rootcas": [], "intermediatecas": []}}`), 54 []byte(`{"signatures": [], "signed": {"_type": "layout", 55 "steps": "invalid", "inspect": "invalid", "readme": "some readme", 56 "keys": "some keys", "rootcas": [], "intermediatecas": []}}`), 57 []byte(`{"signatures": [], "signed": {"_type": "layout", 58 "steps": "invalid", "inspect": "invalid", 59 "keys": "some keys", "expires": "some date", "rootcas": [], "intermediatecas": []}}`), 60 []byte(`{"signatures": [], "signed": {"_type": "layout", "steps": [], 61 "inspect": [], "readme": "some readme", "keys": {}, 62 "expires": "some date", "foo": "bar", "rootcas": [], "intermediatecas": []}}`), 63 []byte(`{"signatures": [], "signed": {"_type": "link", 64 "materials": "invalid", "products": "invalid", 65 "byproducts": "invalid", "command": "some command", 66 "environment": "some list"}}`), 67 []byte(`{"signatures": [], "signed": {"_type": "link", 68 "name": "some name", "products": "invalid", 69 "byproducts": "invalid", "command": "some command", 70 "environment": "some list"}}`), 71 []byte(`{"signatures": [], "signed": {"_type": "link", 72 "materials": "invalid", "name": "some name", 73 "byproducts": "invalid", "command": "some command", 74 "environment": "some list"}}`), 75 []byte(`{"signatures": [], "signed": {"_type": "link", 76 "materials": "invalid", "name": "some name", "products": "invalid", 77 "command": "some command", 78 "environment": "some list"}}`), 79 []byte(`{"signatures": [], "signed": {"_type": "link", 80 "materials": "invalid", "name": "some name", "products": "invalid", 81 "byproducts": "invalid", "environment": "some list"}}`), 82 []byte(`{"signatures": [], "signed": {"_type": "link", 83 "materials": "invalid", "name": "some name", "products": "invalid", 84 "byproducts": "invalid", "command": "some command"}}`), 85 []byte(`{"signatures": [], "signed": {"_type": "link", "materials": {}, 86 "name": "some name", "products": {}, "byproducts": {}, 87 "command": [], "environment": {}, "foo": "bar"}}`), 88 } 89 90 expectedErrors := []string{ 91 "unexpected end", 92 "requires 'signed' and 'signatures' parts", 93 "requires 'signed' and 'signatures' parts", 94 "cannot unmarshal string into Go value of type []in_toto.Signature", 95 "cannot unmarshal array into Go value of type map[string]interface {}", 96 "metadata must be one of 'link' or 'layout'", 97 "cannot unmarshal string into Go struct field Link.materials", 98 "cannot unmarshal string into Go struct field Layout.steps", 99 "required field steps missing", 100 "required field inspect missing", 101 "required field keys missing", 102 "required field expires missing", 103 "required field readme missing", 104 "json: unknown field \"foo\"", 105 "required field name missing", 106 "required field materials missing", 107 "required field products missing", 108 "required field byproducts missing", 109 "required field command missing", 110 "required field environment missing", 111 "json: unknown field \"foo\"", 112 } 113 114 for i := 0; i < len(invalidJSONBytes); i++ { 115 fn := fmt.Sprintf("invalid-metadata-%v.tmp", i) 116 if err := ioutil.WriteFile(fn, invalidJSONBytes[i], 0644); err != nil { 117 fmt.Printf("Could not write file: %s", err) 118 } 119 var mb Metablock 120 err := mb.Load(fn) 121 if err == nil || !strings.Contains(err.Error(), expectedErrors[i]) { 122 t.Errorf("Metablock.Load returned '%s', expected '%s' error", err, 123 expectedErrors[i]) 124 } 125 if err := os.Remove(fn); err != nil { 126 t.Errorf("Unable to remove directory %s: %s", fn, err) 127 } 128 } 129 } 130 131 func TestMetablockDump(t *testing.T) { 132 // Test dump metablock errors: 133 // - invalid content 134 // - invalid path 135 mbs := []Metablock{ 136 {Signed: TestMetablockDump}, 137 {}, 138 } 139 paths := []string{ 140 "bad-metadata", 141 "bad/path", 142 } 143 expectedErrors := []string{ 144 "json: unsupported type", 145 "open bad/path", 146 } 147 148 for i := 0; i < len(mbs); i++ { 149 err := mbs[i].Dump(paths[i]) 150 fmt.Println(err) 151 if err == nil || !strings.Contains(err.Error(), expectedErrors[i]) { 152 t.Errorf("Metablock.Dump returned '%s', expected '%s'", 153 err, expectedErrors[i]) 154 } 155 } 156 } 157 158 func TestMetablockLoadDumpLoad(t *testing.T) { 159 // Dump, load and compare metablock, also compare with metablock loaded 160 // from existing equivalent JSON file, assert that they are equal. 161 mbMemory := Metablock{ 162 Signed: Link{ 163 Type: "link", 164 Name: "package", 165 Command: []string{ 166 "tar", 167 "zcvf", 168 "foo.tar.gz", 169 "foo.py", 170 }, 171 Materials: map[string]interface{}{ 172 "foo.py": map[string]interface{}{ 173 "sha256": "74dc3727c6e89308b39e4dfedf787e37841198b1fa165a27c013544a60502549", 174 }, 175 }, 176 Products: map[string]interface{}{ 177 "foo.tar.gz": map[string]interface{}{ 178 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355", 179 }, 180 }, 181 ByProducts: map[string]interface{}{ 182 "return-value": float64(0), 183 "stderr": "a foo.py\n", 184 "stdout": "", 185 }, 186 Environment: map[string]interface{}{}, 187 }, 188 Signatures: []Signature{ 189 { 190 KeyID: "2f89b9272acfc8f4a0a0f094d789fdb0ba798b0fe41f2f5f417c12f0085ff498", 191 Sig: "66365d379d66a2e76d39a1f048847826393127572ba43bead96419499b0256" + 192 "1a08e1cb06cf91f2addd87c30a01f776a8ccc599574bc9a2bd519558351f56cff" + 193 "a61ac4f994d0d491204ff54707937e15f9abfa97c5bda1ec1ae2a2afea63f8086" + 194 "13f4fb343b85a5a455b668b95fa3a11cb9b34219d4d6af2dd4e80a9af01023954" + 195 "a8813b510a6ff6041c3af52056d021fabbc975211b0d8ee7a429a6c22efde583d" + 196 "8ac0719fd657b398a3e02cc711897acbe8cadf32d54f47012aa44621728ede42c" + 197 "3bc95c662f9c1211df4e18da8e0f6b2de358700cea5db1e76fc61ef5a90bcebcc" + 198 "883eed2272e5ca1c8cbb09b868613b839266cd3ae346ce88439bdb5bb4c69dcb7" + 199 "398f4373f2b051adb3d44d11ef1b70c7189aa5c0e6906bf7be1228dc553390024" + 200 "c9c796316067fda7d63cf60bfac86ef2e13bbd8e4c3575683673f7cdf4639c3a5" + 201 "dc225fc0c040dbd9962a6ff51913b240544939ce2d32a5e84792c0acfa94ee07e" + 202 "88e474bf4937558d107c6ecdef5b5b3a7f3a44a657662bbc1046df3a", 203 }, 204 }, 205 } 206 207 fnExisting := "package.2f89b927.link" 208 fnTmp := fnExisting + ".tmp" 209 if err := mbMemory.Dump(fnTmp); err != nil { 210 t.Errorf("JSON serialization failed: %s", err) 211 } 212 for _, fn := range []string{fnExisting, fnTmp} { 213 var mbFile Metablock 214 if err := mbFile.Load(fn); err != nil { 215 t.Errorf("Could not parse Metablock: %s", err) 216 } 217 if !reflect.DeepEqual(mbMemory, mbFile) { 218 t.Errorf("Dumped and Loaded Metablocks are not equal: \n%s\n\n\n%s\n", 219 mbMemory, mbFile) 220 } 221 } 222 // Remove temporary metablock file (keep other for remaining tests) 223 if err := os.Remove(fnTmp); err != nil { 224 t.Errorf("Unable to remove directory %s: %s", fnTmp, err) 225 } 226 } 227 228 func TestMetablockGetSignableRepresentation(t *testing.T) { 229 // Test successful metadata canonicalization with encoding corner cases 230 // (unicode, escapes, non-string types, ...) and compare with reference 231 var mb Metablock 232 if err := mb.Load("canonical-test.link"); err != nil { 233 t.Errorf("Cannot parse link file: %s", err) 234 } 235 // Use hex representation for unambiguous assignment 236 referenceHex := "7b225f74797065223a226c696e6b222" + 237 "c22627970726f6475637473223a7b7d2c22636f6d6d616e64223a5b5d2" + 238 "c22656e7669726f6e6d656e74223a7b2261223a22575446222c2262223" + 239 "a747275652c2263223a66616c73652c2264223a6e756c6c2c2265223a3" + 240 "12c2266223a221befbfbf465c5c6e5c22227d2c226d6174657269616c7" + 241 "3223a7b7d2c226e616d65223a2274657374222c2270726f64756374732" + 242 "23a7b7d7d" 243 244 canonical, _ := mb.GetSignableRepresentation() 245 if fmt.Sprintf("%x", canonical) != referenceHex { 246 // Convert hex representation back to string for better error message 247 src := []byte(referenceHex) 248 reference := make([]byte, hex.DecodedLen(len(src))) 249 n, _ := hex.Decode(reference, src) 250 t.Errorf("Metablock.GetSignableRepresentation returned '%s', expected '%s'", 251 canonical, reference[:n]) 252 } 253 } 254 255 func TestMetablockVerifySignature(t *testing.T) { 256 // Test metablock signature verification errors: 257 // - no signature found 258 // - wrong signature for key 259 // - invalid metadata (can't canonicalize) 260 var key Key 261 if err := key.LoadKey("alice.pub", "rsassa-pss-sha256", []string{"sha256", "sha512"}); err != nil { 262 t.Errorf("Cannot load public key file: %s", err) 263 } 264 // Test missing key, bad signature and bad metadata 265 mbs := []Metablock{ 266 {}, 267 { 268 Signatures: []Signature{{KeyID: key.KeyID, Sig: "bad sig"}}, 269 }, 270 { 271 Signatures: []Signature{{KeyID: key.KeyID}}, 272 Signed: TestMetablockVerifySignature, 273 }, 274 } 275 expectedErrors := []string{ 276 "No signature found", 277 "encoding/hex: invalid byte: U+0020 ' '", 278 "json: unsupported type", 279 } 280 for i := 0; i < len(mbs); i++ { 281 err := mbs[i].VerifySignature(key) 282 if err == nil || !strings.Contains(err.Error(), expectedErrors[i]) { 283 t.Errorf("Metablock.VerifySignature returned '%s', expected '%s'", 284 err, expectedErrors[i]) 285 } 286 } 287 288 // Test successful metablock signature verification 289 var mb Metablock 290 if err := mb.Load("demo.layout"); err != nil { 291 t.Errorf("Cannot parse template file: %s", err) 292 } 293 err := mb.VerifySignature(key) 294 if err != nil { 295 t.Errorf("Metablock.VerifySignature returned '%s', expected nil", err) 296 } 297 } 298 299 func TestValidateLink(t *testing.T) { 300 var mb Metablock 301 if err := mb.Load("package.2f89b927.link"); err != nil { 302 t.Errorf("Metablock load returned '%s'", err) 303 } 304 if err := validateLink(mb.Signed.(Link)); err != nil { 305 t.Errorf("Link metadata validation failed, returned '%s'", err) 306 } 307 308 testMb := Metablock{ 309 Signed: Link{ 310 Type: "invalid", 311 Name: "test_type", 312 Command: []string{ 313 "tar", 314 "zcvf", 315 "foo.tar.gz", 316 "foo.py", 317 }, 318 Materials: map[string]interface{}{ 319 "foo.py": map[string]interface{}{ 320 "sha256": "74dc3727c6e89308b39e4dfedf787e37841198b1fa165a27c013544a60502549", 321 }, 322 }, 323 Products: map[string]interface{}{ 324 "foo.tar.gz": map[string]interface{}{ 325 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c1e5aabb7c98514f355", 326 }, 327 }, 328 ByProducts: map[string]interface{}{ 329 "return-value": float64(0), 330 "stderr": "a foo.py\n", 331 "stdout": "", 332 }, 333 Environment: map[string]interface{}{}, 334 }, 335 } 336 337 err := validateLink(testMb.Signed.(Link)) 338 if err.Error() != "invalid type for link 'test_type': should be 'link'" { 339 t.Error("validateLink error - incorrect type not detected") 340 } 341 342 testMb = Metablock{ 343 Signed: Link{ 344 Type: "link", 345 Name: "test_material_hash", 346 Command: []string{ 347 "tar", 348 "zcvf", 349 "foo.tar.gz", 350 "foo.py", 351 }, 352 Materials: map[string]interface{}{ 353 "foo.py": map[string]interface{}{ 354 "sha256": "!@#$%", 355 }, 356 }, 357 Products: map[string]interface{}{ 358 "foo.tar.gz": map[string]interface{}{ 359 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e69" + 360 "36c1e5aabb7c98514f355", 361 }, 362 }, 363 ByProducts: map[string]interface{}{ 364 "return-value": float64(0), 365 "stderr": "a foo.py\n", 366 "stdout": "", 367 }, 368 Environment: map[string]interface{}{}, 369 }, 370 } 371 372 err = validateLink(testMb.Signed.(Link)) 373 if err.Error() != "in materials of link 'test_material_hash': in artifact"+ 374 " 'foo.py', sha256 hash value: invalid hex string: !@#$%" { 375 t.Error("validateLink error - invalid hashes not detected") 376 } 377 378 testMb = Metablock{ 379 Signed: Link{ 380 Type: "link", 381 Name: "test_product_hash", 382 Command: []string{ 383 "tar", 384 "zcvf", 385 "foo.tar.gz", 386 "foo.py", 387 }, 388 Materials: map[string]interface{}{ 389 "foo.py": map[string]interface{}{ 390 "sha256": "74dc3727c6e89308b39e4dfedf787e37841198b1fa165a27c013544a60502549", 391 }, 392 }, 393 Products: map[string]interface{}{ 394 "foo.tar.gz": map[string]interface{}{ 395 "sha256": "!@#$%", 396 }, 397 }, 398 ByProducts: map[string]interface{}{ 399 "return-value": float64(0), 400 "stderr": "a foo.py\n", 401 "stdout": "", 402 }, 403 Environment: map[string]interface{}{}, 404 }, 405 } 406 407 err = validateLink(testMb.Signed.(Link)) 408 if err.Error() != "in products of link 'test_product_hash': in artifact "+ 409 "'foo.tar.gz', sha256 hash value: invalid hex string: !@#$%" { 410 t.Error("validateLink error - invalid hashes not detected") 411 } 412 } 413 414 func TestValidateLayout(t *testing.T) { 415 var mb Metablock 416 if err := mb.Load("demo.layout"); err != nil { 417 t.Errorf("Metablock load returned '%s'", err) 418 } 419 if err := validateLayout(mb.Signed.(Layout)); err != nil { 420 t.Errorf("Layout metadata validation failed, returned '%s'", err) 421 } 422 423 testMb := Metablock{ 424 Signed: Layout{ 425 Type: "invalid", 426 Expires: "2020-11-18T16:06:36Z", 427 Readme: "some readme text", 428 Steps: []Step{}, 429 Inspect: []Inspection{}, 430 Keys: map[string]Key{}, 431 }, 432 } 433 434 err := validateLayout(testMb.Signed.(Layout)) 435 if err.Error() != "invalid Type value for layout: should be 'layout'" { 436 t.Error("validateLayout error - invalid type not detected") 437 } 438 439 testMb = Metablock{ 440 Signed: Layout{ 441 Type: "layout", 442 Expires: "2020-02-31T18:03:43Z", 443 Readme: "some readme text", 444 Steps: []Step{}, 445 Inspect: []Inspection{}, 446 Keys: map[string]Key{}, 447 }, 448 } 449 450 err = validateLayout(testMb.Signed.(Layout)) 451 if err.Error() != "expiry time parsed incorrectly - date either invalid "+ 452 "or of incorrect format" { 453 t.Error("validateLayout error - invalid date not detected") 454 } 455 456 testMb = Metablock{ 457 Signed: Layout{ 458 Type: "layout", 459 Expires: "2020-02-27T18:03:43Zinvalid", 460 Readme: "some readme text", 461 Steps: []Step{}, 462 Inspect: []Inspection{}, 463 Keys: map[string]Key{}, 464 }, 465 } 466 467 err = validateLayout(testMb.Signed.(Layout)) 468 if err.Error() != "expiry time parsed incorrectly - date either invalid "+ 469 "or of incorrect format" { 470 t.Error("validateLayout error - invalid date not detected") 471 } 472 473 testMb = Metablock{ 474 Signed: Layout{ 475 Type: "layout", 476 Expires: "2020-02-27T18:03:43Z", 477 Readme: "some readme text", 478 Steps: []Step{ 479 { 480 Type: "step", 481 SupplyChainItem: SupplyChainItem{ 482 Name: "foo", 483 }, 484 }, 485 { 486 Type: "step", 487 SupplyChainItem: SupplyChainItem{ 488 Name: "foo", 489 }, 490 }, 491 }, 492 Inspect: []Inspection{}, 493 Keys: map[string]Key{}, 494 }, 495 } 496 497 err = validateLayout(testMb.Signed.(Layout)) 498 if err.Error() != "non unique step or inspection name found" { 499 t.Error("validateLayout error - duplicate step/inspection name not " + 500 "detected") 501 } 502 503 testMb = Metablock{ 504 Signed: Layout{ 505 Type: "layout", 506 Expires: "2020-02-27T18:03:43Z", 507 Readme: "some readme text", 508 Steps: []Step{ 509 { 510 Type: "step", 511 SupplyChainItem: SupplyChainItem{ 512 Name: "foo", 513 }, 514 }, 515 }, 516 Inspect: []Inspection{ 517 { 518 Type: "inspection", 519 SupplyChainItem: SupplyChainItem{ 520 Name: "foo", 521 }, 522 }, 523 }, 524 Keys: map[string]Key{}, 525 }, 526 } 527 528 err = validateLayout(testMb.Signed.(Layout)) 529 if err.Error() != "non unique step or inspection name found" { 530 t.Error("validateLayout error - duplicate step/inspection name not " + 531 "detected") 532 } 533 534 testMb = Metablock{ 535 Signed: Layout{ 536 Type: "layout", 537 Expires: "2020-02-27T18:03:43Z", 538 Readme: "some readme text", 539 Steps: []Step{}, 540 Inspect: []Inspection{ 541 { 542 Type: "inspection", 543 SupplyChainItem: SupplyChainItem{ 544 Name: "foo", 545 }, 546 }, 547 { 548 Type: "inspection", 549 SupplyChainItem: SupplyChainItem{ 550 Name: "foo", 551 }, 552 }, 553 }, 554 Keys: map[string]Key{}, 555 }, 556 } 557 558 err = validateLayout(testMb.Signed.(Layout)) 559 if err.Error() != "non unique step or inspection name found" { 560 t.Error("validateLayout error - duplicate step/inspection name not " + 561 "detected") 562 } 563 564 testMb = Metablock{ 565 Signed: Layout{ 566 Type: "layout", 567 Expires: "2020-02-27T18:03:43Z", 568 Readme: "some readme text", 569 Steps: []Step{ 570 { 571 Type: "invalid", 572 SupplyChainItem: SupplyChainItem{ 573 Name: "foo", 574 }, 575 }, 576 }, 577 Inspect: []Inspection{}, 578 Keys: map[string]Key{}, 579 }, 580 } 581 582 err = validateLayout(testMb.Signed.(Layout)) 583 if err.Error() != "invalid Type value for step 'foo': should be 'step'" { 584 t.Error("validateLayout - validateStep error - invalid step type not " + 585 "detected") 586 } 587 588 cases := map[string]struct { 589 Arg Layout 590 Expected string 591 }{ 592 "invalid key map": { 593 Layout{ 594 Type: "layout", 595 Expires: "2020-02-27T18:03:43Z", 596 Keys: map[string]Key{ 597 "deadbeef": Key{KeyID: "livebeef"}, 598 }, 599 }, 600 "invalid key found", 601 }, 602 "invalid rsa key": { 603 Layout{ 604 Type: "layout", 605 Expires: "2020-02-27T18:03:43Z", 606 Keys: map[string]Key{ 607 "deadbeef": Key{KeyID: "deadbeef"}, 608 }, 609 }, 610 "empty field in key: keytype", 611 }, 612 } 613 614 for name, tc := range cases { 615 err := validateLayout(tc.Arg) 616 if err == nil || !strings.Contains(err.Error(), tc.Expected) { 617 t.Errorf("%s: '%s' not in '%s'", name, tc.Expected, err) 618 } 619 } 620 } 621 622 func TestValidateStep(t *testing.T) { 623 testStep := Step{ 624 Type: "invalid", 625 SupplyChainItem: SupplyChainItem{ 626 Name: "foo", 627 }, 628 } 629 err := validateStep(testStep) 630 if err.Error() != "invalid Type value for step 'foo': should be 'step'" { 631 t.Error("validateStep error - invalid type not detected") 632 } 633 634 testStep = Step{ 635 Type: "step", 636 PubKeys: []string{"776a00e29f3559e0141b3b096f696abc6cfb0c657ab40f4Z" + 637 "41132b345b08453f5"}, 638 SupplyChainItem: SupplyChainItem{ 639 Name: "foo", 640 }, 641 } 642 err = validateStep(testStep) 643 if !errors.Is(err, ErrInvalidHexString) { 644 t.Error("validateStep - validateHexString error - invalid key ID not " + 645 "detected") 646 } 647 648 testStep = Step{ 649 Type: "step", 650 SupplyChainItem: SupplyChainItem{ 651 Name: "", 652 }, 653 } 654 err = validateStep(testStep) 655 if err.Error() != "step name cannot be empty" { 656 t.Error("validateStep error - empty name not detected") 657 } 658 } 659 660 func TestValidateInspection(t *testing.T) { 661 testInspection := Inspection{ 662 Type: "invalid", 663 SupplyChainItem: SupplyChainItem{ 664 Name: "foo", 665 }, 666 } 667 err := validateInspection(testInspection) 668 if err.Error() != "invalid Type value for inspection 'foo': should be "+ 669 "'inspection'" { 670 t.Error("validateInspection error - invalid type not detected") 671 } 672 testInspection = Inspection{ 673 Type: "inspection", 674 SupplyChainItem: SupplyChainItem{ 675 Name: "", 676 }, 677 } 678 err = validateInspection(testInspection) 679 if err.Error() != "inspection name cannot be empty" { 680 t.Error("validateInspection error - empty name not detected") 681 } 682 683 testInspection = Inspection{ 684 Type: "inspection", 685 SupplyChainItem: SupplyChainItem{ 686 Name: "inspect", 687 }, 688 } 689 err = validateInspection(testInspection) 690 if err != nil { 691 t.Error("validateInspection should successfully validate an inspection") 692 } 693 } 694 695 func TestValidateHexSchema(t *testing.T) { 696 testStr := "776a00e29f3559e0141b3b096f696abc6cfb0c657ab40f441132b345b" + 697 "08453f5" 698 if err := validateHexString(testStr); err != nil { 699 t.Errorf("validateHexString error - valid key ID flagged") 700 } 701 702 testStr = "Z776a00e29f3559e0141b3b096f696abc6cfb0c657ab40f441132b345b" + 703 "08453f5" 704 if err := validateHexString(testStr); err == nil { 705 t.Errorf("validateHexString error - invalid key ID not detected") 706 } 707 } 708 709 func TestValidatePubKey(t *testing.T) { 710 testKey := Key{ 711 KeyID: "776a00e29f3559e0141b3b096f696abc6cfb0c657ab40f441132b345b08453f5", 712 KeyType: "rsa", 713 KeyVal: KeyVal{ 714 Private: "", 715 Public: "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAO" + 716 "CAY8AMIIBigKCAYEAzgLBsMFSgwBiWTBmVsyW\n5KbJwLFSodAzdUhU2Bq6" + 717 "SdRz/W6UOBGdojZXibxupjRtAaEQW/eXDe+1CbKg6ENZ\nGt2D9HGFCQZgQ" + 718 "S8ONgNDQGiNxgApMA0T21AaUhru0vEofzdN1DfEF4CAGv5AkcgK\nsalhTy" + 719 "ONervFIjFEdXGelFZ7dVMV3Pp5WkZPG0jFQWjnmDZhUrtSxEtqbVghc3kK" + 720 "\nAUj9Ll/3jyi2wS92Z1j5ueN8X62hWX2xBqQ6nViOMzdujkoiYCRSwuMLR" + 721 "qzW2CbT\nL8hF1+S5KWKFzxl5sCVfpPe7V5HkgEHjwCILXTbCn2fCMKlaSb" + 722 "J/MG2lW7qSY2Ro\nwVXWkp1wDrsJ6Ii9f2dErv9vJeOVZeO9DsooQ5EuzLC" + 723 "fQLEU5mn7ul7bU7rFsb8J\nxYOeudkNBatnNCgVMAkmDPiNA7E33bmL5ARR" + 724 "wU0iZicsqLQR32pmwdap8PjofxqQ\nk7Gtvz/iYzaLrZv33cFWWTsEOqK1g" + 725 "KqigSqgW9T26wO9AgMBAAE=\n-----END PUBLIC KEY-----", 726 }, 727 Scheme: "rsassa-pss-sha256", 728 } 729 730 err := validatePublicKey(testKey) 731 if !errors.Is(err, nil) { 732 t.Errorf("error validating public key: %s", err) 733 } 734 735 testKey = Key{ 736 KeyID: "Z776a00e29f3559e0141b3b096f696abc6cfb0c657ab40f441132b345b08453f5", 737 KeyType: "rsa", 738 KeyVal: KeyVal{ 739 Private: "", 740 Public: "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAO" + 741 "CAY8AMIIBigKCAYEAzgLBsMFSgwBiWTBmVsyW\n5KbJwLFSodAzdUhU2Bq6" + 742 "SdRz/W6UOBGdojZXibxupjRtAaEQW/eXDe+1CbKg6ENZ\nGt2D9HGFCQZgQ" + 743 "S8ONgNDQGiNxgApMA0T21AaUhru0vEofzdN1DfEF4CAGv5AkcgK\nsalhTy" + 744 "ONervFIjFEdXGelFZ7dVMV3Pp5WkZPG0jFQWjnmDZhUrtSxEtqbVghc3kK" + 745 "\nAUj9Ll/3jyi2wS92Z1j5ueN8X62hWX2xBqQ6nViOMzdujkoiYCRSwuMLR" + 746 "qzW2CbT\nL8hF1+S5KWKFzxl5sCVfpPe7V5HkgEHjwCILXTbCn2fCMKlaSb" + 747 "J/MG2lW7qSY2Ro\nwVXWkp1wDrsJ6Ii9f2dErv9vJeOVZeO9DsooQ5EuzLC" + 748 "fQLEU5mn7ul7bU7rFsb8J\nxYOeudkNBatnNCgVMAkmDPiNA7E33bmL5ARR" + 749 "wU0iZicsqLQR32pmwdap8PjofxqQ\nk7Gtvz/iYzaLrZv33cFWWTsEOqK1g" + 750 "KqigSqgW9T26wO9AgMBAAE=\n-----END PUBLIC KEY-----", 751 }, 752 Scheme: "rsassa-pss-sha256", 753 } 754 755 err = validateKey(testKey) 756 if !errors.Is(err, ErrInvalidHexString) { 757 t.Error("validateKey error - invalid key ID not detected") 758 } 759 760 testKey = Key{ 761 KeyID: "776a00e29f3559e0141b3b096f696abc6cfb0c657ab40f441132b345b08453f5", 762 KeyType: "rsa", 763 KeyVal: KeyVal{ 764 Private: "invalid", 765 Public: "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAO" + 766 "CAY8AMIIBigKCAYEAzgLBsMFSgwBiWTBmVsyW\n5KbJwLFSodAzdUhU2Bq6" + 767 "SdRz/W6UOBGdojZXibxupjRtAaEQW/eXDe+1CbKg6ENZ\nGt2D9HGFCQZgQ" + 768 "S8ONgNDQGiNxgApMA0T21AaUhru0vEofzdN1DfEF4CAGv5AkcgK\nsalhTy" + 769 "ONervFIjFEdXGelFZ7dVMV3Pp5WkZPG0jFQWjnmDZhUrtSxEtqbVghc3kK" + 770 "\nAUj9Ll/3jyi2wS92Z1j5ueN8X62hWX2xBqQ6nViOMzdujkoiYCRSwuMLR" + 771 "qzW2CbT\nL8hF1+S5KWKFzxl5sCVfpPe7V5HkgEHjwCILXTbCn2fCMKlaSb" + 772 "J/MG2lW7qSY2Ro\nwVXWkp1wDrsJ6Ii9f2dErv9vJeOVZeO9DsooQ5EuzLC" + 773 "fQLEU5mn7ul7bU7rFsb8J\nxYOeudkNBatnNCgVMAkmDPiNA7E33bmL5ARR" + 774 "wU0iZicsqLQR32pmwdap8PjofxqQ\nk7Gtvz/iYzaLrZv33cFWWTsEOqK1g" + 775 "KqigSqgW9T26wO9AgMBAAE=\n-----END PUBLIC KEY-----", 776 }, 777 Scheme: "rsassa-pss-sha256", 778 } 779 780 err = validatePublicKey(testKey) 781 if !errors.Is(err, ErrNoPublicKey) { 782 t.Error("validateKey error - private key not detected") 783 } 784 785 testKey = Key{ 786 KeyID: "776a00e29f3559e0141b3b096f696abc6cfb0c657ab40f441132b345b08453f5", 787 KeyType: "rsa", 788 KeyVal: KeyVal{ 789 Private: "", 790 Public: "", 791 }, 792 Scheme: "rsassa-pss-sha256", 793 } 794 795 err = validateKey(testKey) 796 if !errors.Is(err, ErrEmptyKeyField) { 797 t.Error("validateKey error - empty public key not detected") 798 } 799 } 800 801 func TestValidateMetablock(t *testing.T) { 802 testMetablock := Metablock{ 803 Signatures: []Signature{ 804 { 805 KeyID: "556caebdc0877eed53d419b60eddb1e57fa773e4e31d70698b58" + 806 "8f3e9cc48b35", 807 Sig: "02813858670c66647c17802d84f06453589f41850013a544609e9d" + 808 "33ba21fa19280e8371701f8274fb0c56bd95ff4f34c418456b002af" + 809 "9836ca218b584f51eb0eaacbb1c9bb57448101b07d058dec04d5255" + 810 "51d157f6ae5e3679701735b1b8f52430f9b771d5476db1a2053cd93" + 811 "e2354f20061178a01705f2fa9ac82c7aeca4dd830e2672eb2271271" + 812 "78d52328747ac819e50ec8ff52c662d7a4c58f5040d8f655fe59580" + 813 "4f3e47c4fc98434c44e914445f7cb773439ebf813de8849dd1b5339" + 814 "58f99f671d4e023d34c110d4b169cc02c12a3755ebe537147ff2479" + 815 "d244daaf719e24cf6b2fa6f47d0410d52d67217bcf4d4d4c2c7c0b9" + 816 "2cd2bcd321edc69bc1430f78a188e712b8cb1fff0c14550cd01c41d" + 817 "ae377256f31211fd249c5031bfee86e638bce6aa36aca349b787cef" + 818 "48255b0ef04bd0a21adb37b2a3da888d1530ca6ddeae5261e6fd65a" + 819 "a626d5caebbfae2986f842bd2ce94bcefe5dd0ae9c5b2028a15bd63" + 820 "bbea61be732207f0f5b58d056f118c830981747cb2b245d1377e17", 821 }, 822 }, 823 Signed: Layout{ 824 Type: "layout", 825 Expires: "2020-11-18T16:06:36Z", 826 Readme: "some readme text", 827 Steps: []Step{}, 828 Inspect: []Inspection{}, 829 Keys: map[string]Key{}, 830 }, 831 } 832 833 if err := validateMetablock(testMetablock); err != nil { 834 t.Error("validateMetablock error: valid metablock failed") 835 } 836 837 testMetablock = Metablock{ 838 Signatures: []Signature{ 839 { 840 KeyID: "556caebdc0877eed53d419b60eddb1e57fa773e4e31d70698b58" + 841 "8f3e9cc48b35", 842 Sig: "02813858670c66647c17802d84f06453589f41850013a544609e9d" + 843 "33ba21fa19280e8371701f8274fb0c56bd95ff4f34c418456b002af" + 844 "9836ca218b584f51eb0eaacbb1c9bb57448101b07d058dec04d5255" + 845 "51d157f6ae5e3679701735b1b8f52430f9b771d5476db1a2053cd93" + 846 "e2354f20061178a01705f2fa9ac82c7aeca4dd830e2672eb2271271" + 847 "78d52328747ac819e50ec8ff52c662d7a4c58f5040d8f655fe59580" + 848 "4f3e47c4fc98434c44e914445f7cb773439ebf813de8849dd1b5339" + 849 "58f99f671d4e023d34c110d4b169cc02c12a3755ebe537147ff2479" + 850 "d244daaf719e24cf6b2fa6f47d0410d52d67217bcf4d4d4c2c7c0b9" + 851 "2cd2bcd321edc69bc1430f78a188e712b8cb1fff0c14550cd01c41d" + 852 "ae377256f31211fd249c5031bfee86e638bce6aa36aca349b787cef" + 853 "48255b0ef04bd0a21adb37b2a3da888d1530ca6ddeae5261e6fd65a" + 854 "a626d5caebbfae2986f842bd2ce94bcefe5dd0ae9c5b2028a15bd63" + 855 "bbea61be732207f0f5b58d056f118c830981747cb2b245d1377e17", 856 }, 857 }, 858 Signed: Link{ 859 Type: "link", 860 Name: "test_type", 861 Command: []string{ 862 "tar", 863 "zcvf", 864 "foo.tar.gz", 865 "foo.py", 866 }, 867 Materials: map[string]interface{}{ 868 "foo.py": map[string]interface{}{ 869 "sha256": "74dc3727c6e89308b39e4dfedf787e37841198b1fa165a" + 870 "27c013544a60502549", 871 }, 872 }, 873 Products: map[string]interface{}{ 874 "foo.tar.gz": map[string]interface{}{ 875 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c" + 876 "1e5aabb7c98514f355", 877 }, 878 }, 879 ByProducts: map[string]interface{}{ 880 "return-value": float64(0), 881 "stderr": "a foo.py\n", 882 "stdout": "", 883 }, 884 Environment: map[string]interface{}{}, 885 }, 886 } 887 888 if err := validateMetablock(testMetablock); err != nil { 889 t.Error("validateMetablock error: valid metablock failed") 890 } 891 892 testMetablock = Metablock{ 893 Signatures: []Signature{ 894 { 895 KeyID: "556caebdc0877eed53d419b60eddb1e57fa773e4e31d70698b58" + 896 "8f3e9cc48b35", 897 Sig: "02813858670c66647c17802d84f06453589f41850013a544609e9d" + 898 "33ba21fa19280e8371701f8274fb0c56bd95ff4f34c418456b002af" + 899 "9836ca218b584f51eb0eaacbb1c9bb57448101b07d058dec04d5255" + 900 "51d157f6ae5e3679701735b1b8f52430f9b771d5476db1a2053cd93" + 901 "e2354f20061178a01705f2fa9ac82c7aeca4dd830e2672eb2271271" + 902 "78d52328747ac819e50ec8ff52c662d7a4c58f5040d8f655fe59580" + 903 "4f3e47c4fc98434c44e914445f7cb773439ebf813de8849dd1b5339" + 904 "58f99f671d4e023d34c110d4b169cc02c12a3755ebe537147ff2479" + 905 "d244daaf719e24cf6b2fa6f47d0410d52d67217bcf4d4d4c2c7c0b9" + 906 "2cd2bcd321edc69bc1430f78a188e712b8cb1fff0c14550cd01c41d" + 907 "ae377256f31211fd249c5031bfee86e638bce6aa36aca349b787cef" + 908 "48255b0ef04bd0a21adb37b2a3da888d1530ca6ddeae5261e6fd65a" + 909 "a626d5caebbfae2986f842bd2ce94bcefe5dd0ae9c5b2028a15bd63" + 910 "bbea61be732207f0f5b58d056f118c830981747cb2b245d1377e17", 911 }, 912 }, 913 Signed: Layout{ 914 Type: "invalid", 915 Expires: "2020-11-18T16:06:36Z", 916 Readme: "some readme text", 917 Steps: []Step{}, 918 Inspect: []Inspection{}, 919 Keys: map[string]Key{}, 920 }, 921 } 922 923 if err := validateMetablock(testMetablock); err.Error() != 924 "invalid Type value for layout: should be 'layout'" { 925 t.Error("validateMetablock Error: invalid Type not detected") 926 } 927 928 testMetablock = Metablock{ 929 Signatures: []Signature{ 930 { 931 KeyID: "556caebdc0877eed53d419b60eddb1e57fa773e4e31d70698b58" + 932 "8f3e9cc48b35", 933 Sig: "02813858670c66647c17802d84f06453589f41850013a544609e9d" + 934 "33ba21fa19280e8371701f8274fb0c56bd95ff4f34c418456b002af" + 935 "9836ca218b584f51eb0eaacbb1c9bb57448101b07d058dec04d5255" + 936 "51d157f6ae5e3679701735b1b8f52430f9b771d5476db1a2053cd93" + 937 "e2354f20061178a01705f2fa9ac82c7aeca4dd830e2672eb2271271" + 938 "78d52328747ac819e50ec8ff52c662d7a4c58f5040d8f655fe59580" + 939 "4f3e47c4fc98434c44e914445f7cb773439ebf813de8849dd1b5339" + 940 "58f99f671d4e023d34c110d4b169cc02c12a3755ebe537147ff2479" + 941 "d244daaf719e24cf6b2fa6f47d0410d52d67217bcf4d4d4c2c7c0b9" + 942 "2cd2bcd321edc69bc1430f78a188e712b8cb1fff0c14550cd01c41d" + 943 "ae377256f31211fd249c5031bfee86e638bce6aa36aca349b787cef" + 944 "48255b0ef04bd0a21adb37b2a3da888d1530ca6ddeae5261e6fd65a" + 945 "a626d5caebbfae2986f842bd2ce94bcefe5dd0ae9c5b2028a15bd63" + 946 "bbea61be732207f0f5b58d056f118c830981747cb2b245d1377e17", 947 }, 948 }, 949 Signed: Link{ 950 Type: "invalid", 951 Name: "test_type", 952 Command: []string{ 953 "tar", 954 "zcvf", 955 "foo.tar.gz", 956 "foo.py", 957 }, 958 Materials: map[string]interface{}{ 959 "foo.py": map[string]interface{}{ 960 "sha256": "74dc3727c6e89308b39e4dfedf787e37841198b1fa165a" + 961 "27c013544a60502549", 962 }, 963 }, 964 Products: map[string]interface{}{ 965 "foo.tar.gz": map[string]interface{}{ 966 "sha256": "52947cb78b91ad01fe81cd6aef42d1f6817e92b9e6936c" + 967 "1e5aabb7c98514f355", 968 }, 969 }, 970 ByProducts: map[string]interface{}{ 971 "return-value": float64(0), 972 "stderr": "a foo.py\n", 973 "stdout": "", 974 }, 975 Environment: map[string]interface{}{}, 976 }, 977 } 978 979 if err := validateMetablock(testMetablock); err.Error() != 980 "invalid type for link 'test_type': should be 'link'" { 981 t.Error("validateMetablock Error: invalid Type not detected") 982 } 983 984 testMetablock = Metablock{ 985 Signatures: []Signature{ 986 { 987 KeyID: "Z556caebdc0877eed53d419b60eddb1e57fa773e4e31d70698b5" + 988 "8f3e9cc48b35", 989 Sig: "02813858670c66647c17802d84f06453589f41850013a544609e9d" + 990 "33ba21fa19280e8371701f8274fb0c56bd95ff4f34c418456b002af" + 991 "9836ca218b584f51eb0eaacbb1c9bb57448101b07d058dec04d5255" + 992 "51d157f6ae5e3679701735b1b8f52430f9b771d5476db1a2053cd93" + 993 "e2354f20061178a01705f2fa9ac82c7aeca4dd830e2672eb2271271" + 994 "78d52328747ac819e50ec8ff52c662d7a4c58f5040d8f655fe59580" + 995 "4f3e47c4fc98434c44e914445f7cb773439ebf813de8849dd1b5339" + 996 "58f99f671d4e023d34c110d4b169cc02c12a3755ebe537147ff2479" + 997 "d244daaf719e24cf6b2fa6f47d0410d52d67217bcf4d4d4c2c7c0b9" + 998 "2cd2bcd321edc69bc1430f78a188e712b8cb1fff0c14550cd01c41d" + 999 "ae377256f31211fd249c5031bfee86e638bce6aa36aca349b787cef" + 1000 "48255b0ef04bd0a21adb37b2a3da888d1530ca6ddeae5261e6fd65a" + 1001 "a626d5caebbfae2986f842bd2ce94bcefe5dd0ae9c5b2028a15bd63" + 1002 "bbea61be732207f0f5b58d056f118c830981747cb2b245d1377e17", 1003 }, 1004 }, 1005 Signed: Layout{ 1006 Type: "layout", 1007 Expires: "2020-11-18T16:06:36Z", 1008 Readme: "some readme text", 1009 Steps: []Step{}, 1010 Inspect: []Inspection{}, 1011 Keys: map[string]Key{}, 1012 }, 1013 } 1014 1015 err := validateMetablock(testMetablock) 1016 if !errors.Is(err, ErrInvalidHexString) { 1017 t.Error("validateMetablock Error: invalid key ID not detected") 1018 } 1019 1020 testMetablock = Metablock{ 1021 Signatures: []Signature{ 1022 { 1023 KeyID: "556caebdc0877eed53d419b60eddb1e57fa773e4e31d70698b58" + 1024 "8f3e9cc48b35", 1025 Sig: "02813858670c66647c17802d84f06453589f41850013a544609e9z" + 1026 "33ba21fa19280e8371701f8274fb0c56bd95ff4f34c418456b002af" + 1027 "9836ca218b584f51eb0eaacbb1c9bb57448101b07d058dec04d5255" + 1028 "51d157f6ae5e3679701735b1b8f52430f9b771d5476db1a2053cd93" + 1029 "e2354f20061178a01705f2fa9ac82c7aeca4dd830e2672eb2271271" + 1030 "78d52328747ac819e50ec8ff52c662d7a4c58f5040d8f655fe59580" + 1031 "4f3e47c4fc98434c44e914445f7cb773439ebf813de8849dd1b5339" + 1032 "58f99f671d4e023d34c110d4b169cc02c12a3755ebe537147ff2479" + 1033 "d244daaf719e24cf6b2fa6f47d0410d52d67217bcf4d4d4c2c7c0b9" + 1034 "2cd2bcd321edc69bc1430f78a188e712b8cb1fff0c14550cd01c41d" + 1035 "ae377256f31211fd249c5031bfee86e638bce6aa36aca349b787cef" + 1036 "48255b0ef04bd0a21adb37b2a3da888d1530ca6ddeae5261e6fd65a" + 1037 "a626d5caebbfae2986f842bd2ce94bcefe5dd0ae9c5b2028a15bd63" + 1038 "bbea61be732207f0f5b58d056f118c830981747cb2b245d1377e17", 1039 }, 1040 }, 1041 Signed: Layout{ 1042 Type: "layout", 1043 Expires: "2020-11-18T16:06:36Z", 1044 Readme: "some readme text", 1045 Steps: []Step{}, 1046 Inspect: []Inspection{}, 1047 Keys: map[string]Key{}, 1048 }, 1049 } 1050 1051 err = validateMetablock(testMetablock) 1052 if !errors.Is(err, ErrInvalidHexString) { 1053 t.Error("validateMetablock error: invalid signature not detected") 1054 } 1055 1056 cases := map[string]struct { 1057 Arg Metablock 1058 Expected string 1059 }{ 1060 "invalid type": { 1061 Metablock{Signed: "invalid"}, 1062 "unknown type 'invalid', should be 'layout' or 'link'", 1063 }, 1064 } 1065 for name, tc := range cases { 1066 err := validateMetablock(tc.Arg) 1067 if err == nil || !strings.Contains(err.Error(), tc.Expected) { 1068 t.Errorf("%s: '%s' not in '%s'", name, tc.Expected, err) 1069 } 1070 } 1071 } 1072 1073 func TestValidateSupplyChainItem(t *testing.T) { 1074 cases := map[string]struct { 1075 Arg SupplyChainItem 1076 Expected string 1077 }{ 1078 "empty name": {SupplyChainItem{Name: ""}, "name cannot be empty"}, 1079 "material rule": { 1080 SupplyChainItem{ 1081 Name: "test", 1082 ExpectedMaterials: [][]string{{"invalid"}}}, 1083 "invalid material rule"}, 1084 "product rule": { 1085 SupplyChainItem{ 1086 Name: "test", 1087 ExpectedProducts: [][]string{{"invalid"}}}, 1088 "invalid product rule"}, 1089 } 1090 1091 for name, tc := range cases { 1092 err := validateSupplyChainItem(tc.Arg) 1093 if err == nil || !strings.Contains(err.Error(), tc.Expected) { 1094 t.Errorf("%s: '%s' not in '%s'", name, tc.Expected, err) 1095 } 1096 } 1097 } 1098 1099 func TestMetablockSignWithRSA(t *testing.T) { 1100 var mb Metablock 1101 if err := mb.Load("demo.layout"); err != nil { 1102 t.Errorf("Cannot parse template file: %s", err) 1103 } 1104 invalidKey := Key{ 1105 KeyID: "test", 1106 KeyIDHashAlgorithms: nil, 1107 KeyType: "rsa", 1108 KeyVal: KeyVal{}, 1109 Scheme: "rsassa-pss-sha256", 1110 } 1111 1112 if err := mb.Sign(invalidKey); err == nil { 1113 t.Errorf("signing with an invalid RSA key should fail") 1114 } 1115 } 1116 1117 func TestMetablockSignWithEd25519(t *testing.T) { 1118 var mb Metablock 1119 if err := mb.Load("demo.layout"); err != nil { 1120 t.Errorf("Cannot parse template file: %s", err) 1121 } 1122 invalidKey := Key{ 1123 KeyID: "invalid", 1124 KeyIDHashAlgorithms: nil, 1125 KeyType: "ed25519", 1126 KeyVal: KeyVal{ 1127 Private: "BAD", 1128 Public: "BAD", 1129 }, 1130 Scheme: "ed25519", 1131 } 1132 1133 if err := mb.Sign(invalidKey); err == nil { 1134 t.Errorf("signing with an invalid ed25519 key should fail") 1135 } 1136 } 1137 1138 func TestMetaBlockSignWithEcdsa(t *testing.T) { 1139 var mb Metablock 1140 if err := mb.Load("demo.layout"); err != nil { 1141 t.Errorf("Cannot parse template file: %s", err) 1142 } 1143 invalidKey := Key{ 1144 KeyID: "invalid", 1145 KeyIDHashAlgorithms: nil, 1146 KeyType: "ecdsa", 1147 KeyVal: KeyVal{ 1148 Private: "BAD", 1149 Public: "BAD", 1150 }, 1151 Scheme: "ecdsa", 1152 } 1153 if err := mb.Sign(invalidKey); err == nil { 1154 t.Errorf("signing with an invalid ecdsa key should fail") 1155 } 1156 } 1157 1158 func TestValidateKeyErrors(t *testing.T) { 1159 invalidTables := []struct { 1160 name string 1161 key Key 1162 err error 1163 }{ 1164 {"empty key", Key{ 1165 KeyID: "", 1166 KeyIDHashAlgorithms: nil, 1167 KeyType: "", 1168 KeyVal: KeyVal{}, 1169 Scheme: "", 1170 }, ErrInvalidHexString}, 1171 {"keytype missing", Key{ 1172 KeyID: "bad", 1173 KeyIDHashAlgorithms: []string{"sha256"}, 1174 KeyType: "", 1175 KeyVal: KeyVal{ 1176 Private: "", 1177 Public: "", 1178 }, 1179 Scheme: "rsassa-psa-sha256", 1180 }, ErrEmptyKeyField}, 1181 {"key scheme missing", Key{ 1182 KeyID: "bad", 1183 KeyIDHashAlgorithms: []string{"sha256"}, 1184 KeyType: "ed25519", 1185 KeyVal: KeyVal{ 1186 Private: "bad", 1187 Public: "bad", 1188 }, 1189 Scheme: "", 1190 }, ErrEmptyKeyField}, 1191 { 1192 name: "invalid key type", 1193 key: Key{ 1194 KeyID: "bad", 1195 KeyIDHashAlgorithms: []string{"sha256"}, 1196 KeyType: "invalid", 1197 KeyVal: KeyVal{ 1198 Private: "invalid", 1199 Public: "393e671b200f964c49083d34a867f5d989ec1c69df7b66758fe471c8591b139c", 1200 }, 1201 Scheme: "ed25519", 1202 }, 1203 err: ErrUnsupportedKeyType, 1204 }, 1205 { 1206 name: "keytype scheme mismatch", 1207 key: Key{ 1208 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6", 1209 KeyIDHashAlgorithms: []string{"sha256"}, 1210 KeyType: "ed25519", 1211 KeyVal: KeyVal{ 1212 Private: "29ad59693fe94c9d623afbb66554b4f6bb248c47761689ada4875ebda94840ae393e671b200f964c49083d34a867f5d989ec1c69df7b66758fe471c8591b139c", 1213 Public: "393e671b200f964c49083d34a867f5d989ec1c69df7b66758fe471c8591b139c", 1214 }, 1215 Scheme: "rsassa-pss-sha256", 1216 }, 1217 err: ErrSchemeKeyTypeMismatch, 1218 }, 1219 { 1220 name: "unsupported KeyIDHashAlgorithms", 1221 key: Key{ 1222 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6", 1223 KeyIDHashAlgorithms: []string{"sha128"}, 1224 KeyType: "ed25519", 1225 KeyVal: KeyVal{ 1226 Private: "29ad59693fe94c9d623afbb66554b4f6bb248c47761689ada4875ebda94840ae393e671b200f964c49083d34a867f5d989ec1c69df7b66758fe471c8591b139c", 1227 Public: "393e671b200f964c49083d34a867f5d989ec1c69df7b66758fe471c8591b139c", 1228 }, 1229 Scheme: "ed25519", 1230 }, 1231 err: ErrUnsupportedKeyIDHashAlgorithms, 1232 }, 1233 } 1234 1235 for _, table := range invalidTables { 1236 err := validateKey(table.key) 1237 if !errors.Is(err, table.err) { 1238 t.Errorf("test '%s' failed, expected error: '%s', got '%s'", table.name, table.err, err) 1239 } 1240 } 1241 } 1242 1243 func TestValidateKeyVal(t *testing.T) { 1244 tables := []struct { 1245 name string 1246 key Key 1247 err error 1248 }{ 1249 { 1250 name: "invalid rsa private key", 1251 key: Key{ 1252 KeyID: "bad", 1253 KeyIDHashAlgorithms: []string{"sha256"}, 1254 KeyType: "rsa", 1255 KeyVal: KeyVal{ 1256 Private: "invalid", 1257 Public: "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAxPX3kFs/z645x4UOC3KF\nY3V80YQtKrp6YS3qU+Jlvx/XzK53lb4sCDRU9jqBBx3We45TmFUibroMd8tQXCUS\ne8gYCBUBqBmmz0dEHJYbW0tYF7IoapMIxhRYn76YqNdl1JoRTcmzIaOJ7QrHxQrS\nGpivvTm6kQ9WLeApG1GLYJ3C3Wl4bnsI1bKSv55Zi45/JawHzTzYUAIXX9qCd3Io\nHzDucz9IAj9Ookw0va/q9FjoPGrRB80IReVxLVnbo6pYJfu/O37jvEobHFa8ckHd\nYxUIg8wvkIOy1O3M74lBDm6CVI0ZO25xPlDB/4nHAE1PbA3aF3lw8JGuxLDsetxm\nfzgAleVt4vXLQiCrZaLf+0cM97JcT7wdHcbIvRLsij9LNP+2tWZgeZ/hIAOEdaDq\ncYANPDIAxfTvbe9I0sXrCtrLer1SS7GqUmdFCdkdun8erXdNF0ls9Rp4cbYhjdf3\nyMxdI/24LUOOQ71cHW3ITIDImm6I8KmrXFM2NewTARKfAgMBAAE=\n-----END PUBLIC KEY-----", 1258 }, 1259 Scheme: "rsassa-pss-sha256", 1260 }, 1261 err: ErrNoPEMBlock, 1262 }, 1263 { 1264 name: "invalid rsa pub key", 1265 key: Key{ 1266 KeyID: "bad", 1267 KeyIDHashAlgorithms: []string{"sha256"}, 1268 KeyType: "rsa", 1269 KeyVal: KeyVal{ 1270 Private: "", 1271 Public: "invalid", 1272 }, 1273 Scheme: "rsassa-pss-sha256", 1274 }, 1275 err: ErrNoPEMBlock, 1276 }, 1277 { 1278 name: "invalid ed25519 public key", 1279 key: Key{ 1280 KeyID: "bad", 1281 KeyIDHashAlgorithms: []string{"sha256"}, 1282 KeyType: "ed25519", 1283 KeyVal: KeyVal{ 1284 Private: "invalid", 1285 Public: "invalid", 1286 }, 1287 Scheme: "ed25519", 1288 }, 1289 err: ErrInvalidHexString, 1290 }, 1291 { 1292 name: "invalid ed25519 private key", 1293 key: Key{ 1294 KeyID: "bad", 1295 KeyIDHashAlgorithms: []string{"sha256"}, 1296 KeyType: "ed25519", 1297 KeyVal: KeyVal{ 1298 Private: "invalid", 1299 Public: "393e671b200f964c49083d34a867f5d989ec1c69df7b66758fe471c8591b139c", 1300 }, 1301 Scheme: "ed25519", 1302 }, 1303 err: ErrInvalidHexString, 1304 }, 1305 { 1306 name: "valid rsa public, but bad private key", 1307 key: Key{ 1308 KeyID: "b7d643dec0a051096ee5d87221b5d91a33daa658699d30903e1cefb90c418401", 1309 KeyIDHashAlgorithms: []string{"sha256"}, 1310 KeyType: "rsa", 1311 KeyVal: KeyVal{ 1312 Private: "-----BEGIN PRIVATE KEY-----\nMIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB6fQnV71xKx6kFgJv\nYTMq0ytvWi2mDlYu6aNm1761c1OSInbBxBNb0ligpM65KyaeeRce6JR9eQW6TB6R\n+5pNzvOhgYkDgYYABAFy0CeDAyV/2mY1NqxLLgqEXSxaqM3fM8gYn/ZWzrLnO+1h\nK2QAanID3JuPff1NdhehhL/U1prXdyyaItA5X4ChkQHMTsiS/3HkWRuLR8L22SGs\nB+7KqOeO5ELkqHO5tsy4kvsNrmersCGRQGY6A5V/0JFhP1u1JUvAVVhfRbdQXuu3\nrw==\n-----END PRIVATE KEY-----\n", 1313 Public: "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyCTik98953hKl6+B6n5l\n8DVIDwDnvrJfpasbJ3+Rw66YcawOZinRpMxPTqWBKs7sRop7jqsQNcslUoIZLrXP\nr3foPHF455TlrqPVfCZiFQ+O4CafxWOB4mL1NddvpFXTEjmUiwFrrL7PcvQKMbYz\neUHH4tH9MNzqKWbbJoekBsDpCDIxp1NbgivGBKwjRGa281sClKgpd0Q0ebl+RTcT\nvpfZVDbXazQ7VqZkidt7geWq2BidOXZp/cjoXyVneKx/gYiOUv8x94svQMzSEhw2\nLFMQ04A1KnGn1jxO35/fd6/OW32njyWs96RKu9UQVacYHsQfsACPWwmVqgnX/sp5\nujlvSDjyfZu7c5yUQ2asYfQPLvnjG+u7QcBukGf8hAfVgsezzX9QPiK35BKDgBU/\nVk43riJs165TJGYGVuLUhIEhHgiQtwo8pUTJS5npEe5XMDuZoighNdzoWY2nfsBf\np8348k6vJtDMB093/t6V9sTGYQcSbgKPyEQo5Pk6Wd4ZAgMBAAE=\n-----END PUBLIC KEY-----", 1314 }, 1315 Scheme: "rsassa-pss-sha256", 1316 }, 1317 err: ErrKeyKeyTypeMismatch, 1318 }, 1319 { 1320 name: "valid ecdsa public key, but invalid ecdsa private key", 1321 key: Key{ 1322 KeyID: "b7d643dec0a051096ee5d87221b5d91a33daa658699d30903e1cefb90c418401", 1323 KeyIDHashAlgorithms: []string{"sha256"}, 1324 KeyType: "ecdsa", 1325 KeyVal: KeyVal{ 1326 Private: "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----", 1327 Public: "-----BEGIN PUBLIC KEY-----\nMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBctAngwMlf9pmNTasSy4KhF0sWqjN\n3zPIGJ/2Vs6y5zvtYStkAGpyA9ybj339TXYXoYS/1Naa13csmiLQOV+AoZEBzE7I\nkv9x5Fkbi0fC9tkhrAfuyqjnjuRC5KhzubbMuJL7Da5nq7AhkUBmOgOVf9CRYT9b\ntSVLwFVYX0W3UF7rt68=\n-----END PUBLIC KEY-----\n", 1328 }, 1329 Scheme: "ecdsa", 1330 }, 1331 err: ErrKeyKeyTypeMismatch, 1332 }, 1333 { 1334 name: "rsa key, but with ed25519 private key", 1335 key: Key{ 1336 KeyID: "b7d643dec0a051096ee5d87221b5d91a33daa658699d30903e1cefb90c418401", 1337 KeyIDHashAlgorithms: []string{"sha256"}, 1338 KeyType: "rsa", 1339 KeyVal: KeyVal{ 1340 Private: "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEICmtWWk/6UydYjr7tmVUtPa7JIxHdhaJraSHXr2pSECu\n-----END PRIVATE KEY-----\n", 1341 Public: "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyCTik98953hKl6+B6n5l\n8DVIDwDnvrJfpasbJ3+Rw66YcawOZinRpMxPTqWBKs7sRop7jqsQNcslUoIZLrXP\nr3foPHF455TlrqPVfCZiFQ+O4CafxWOB4mL1NddvpFXTEjmUiwFrrL7PcvQKMbYz\neUHH4tH9MNzqKWbbJoekBsDpCDIxp1NbgivGBKwjRGa281sClKgpd0Q0ebl+RTcT\nvpfZVDbXazQ7VqZkidt7geWq2BidOXZp/cjoXyVneKx/gYiOUv8x94svQMzSEhw2\nLFMQ04A1KnGn1jxO35/fd6/OW32njyWs96RKu9UQVacYHsQfsACPWwmVqgnX/sp5\nujlvSDjyfZu7c5yUQ2asYfQPLvnjG+u7QcBukGf8hAfVgsezzX9QPiK35BKDgBU/\nVk43riJs165TJGYGVuLUhIEhHgiQtwo8pUTJS5npEe5XMDuZoighNdzoWY2nfsBf\np8348k6vJtDMB093/t6V9sTGYQcSbgKPyEQo5Pk6Wd4ZAgMBAAE=\n-----END PUBLIC KEY-----", 1342 }, 1343 Scheme: "rsassa-pss-sha256", 1344 }, 1345 err: ErrInvalidKey, 1346 }, 1347 { 1348 name: "unsupported key type", 1349 key: Key{ 1350 KeyID: "", 1351 KeyIDHashAlgorithms: nil, 1352 KeyType: "invalid", 1353 KeyVal: KeyVal{}, 1354 Scheme: "", 1355 }, 1356 err: ErrUnsupportedKeyType, 1357 }, 1358 { 1359 name: "rsa key type, but ed25519 key", 1360 key: Key{ 1361 KeyID: "b7d643dec0a051096ee5d87221b5d91a33daa658699d30903e1cefb90c418401", 1362 KeyIDHashAlgorithms: []string{"sha256"}, 1363 KeyType: "rsa", 1364 KeyVal: KeyVal{ 1365 Private: "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEICmtWWk/6UydYjr7tmVUtPa7JIxHdhaJraSHXr2pSECu\n-----END PRIVATE KEY-----\n", 1366 Public: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAOT5nGyAPlkxJCD00qGf12YnsHGnfe2Z1j+RxyFkbE5w=\n-----END PUBLIC KEY-----\n", 1367 }, 1368 Scheme: "rsassa-pss-sha256", 1369 }, 1370 err: ErrInvalidKey, 1371 }, 1372 { 1373 name: "rsa key, but not ecdsa key type", 1374 key: Key{ 1375 KeyID: "b7d643dec0a051096ee5d87221b5d91a33daa658699d30903e1cefb90c418401", 1376 KeyIDHashAlgorithms: []string{"sha256"}, 1377 KeyType: "ecdsa", 1378 KeyVal: KeyVal{ 1379 Private: "", 1380 Public: "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyCTik98953hKl6+B6n5l\n8DVIDwDnvrJfpasbJ3+Rw66YcawOZinRpMxPTqWBKs7sRop7jqsQNcslUoIZLrXP\nr3foPHF455TlrqPVfCZiFQ+O4CafxWOB4mL1NddvpFXTEjmUiwFrrL7PcvQKMbYz\neUHH4tH9MNzqKWbbJoekBsDpCDIxp1NbgivGBKwjRGa281sClKgpd0Q0ebl+RTcT\nvpfZVDbXazQ7VqZkidt7geWq2BidOXZp/cjoXyVneKx/gYiOUv8x94svQMzSEhw2\nLFMQ04A1KnGn1jxO35/fd6/OW32njyWs96RKu9UQVacYHsQfsACPWwmVqgnX/sp5\nujlvSDjyfZu7c5yUQ2asYfQPLvnjG+u7QcBukGf8hAfVgsezzX9QPiK35BKDgBU/\nVk43riJs165TJGYGVuLUhIEhHgiQtwo8pUTJS5npEe5XMDuZoighNdzoWY2nfsBf\np8348k6vJtDMB093/t6V9sTGYQcSbgKPyEQo5Pk6Wd4ZAgMBAAE=\n-----END PUBLIC KEY-----", 1381 }, 1382 Scheme: "ecdsa", 1383 }, 1384 err: ErrKeyKeyTypeMismatch, 1385 }, 1386 { 1387 name: "ecdsa key, but rsa key type", 1388 key: Key{ 1389 KeyID: "b7d643dec0a051096ee5d87221b5d91a33daa658699d30903e1cefb90c418401", 1390 KeyIDHashAlgorithms: []string{"sha256"}, 1391 KeyType: "rsa", 1392 KeyVal: KeyVal{ 1393 Private: "-----BEGIN PRIVATE KEY-----\nMIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB6fQnV71xKx6kFgJv\nYTMq0ytvWi2mDlYu6aNm1761c1OSInbBxBNb0ligpM65KyaeeRce6JR9eQW6TB6R\n+5pNzvOhgYkDgYYABAFy0CeDAyV/2mY1NqxLLgqEXSxaqM3fM8gYn/ZWzrLnO+1h\nK2QAanID3JuPff1NdhehhL/U1prXdyyaItA5X4ChkQHMTsiS/3HkWRuLR8L22SGs\nB+7KqOeO5ELkqHO5tsy4kvsNrmersCGRQGY6A5V/0JFhP1u1JUvAVVhfRbdQXuu3\nrw==\n-----END PRIVATE KEY-----\n", 1394 Public: "-----BEGIN PUBLIC KEY-----\nMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBctAngwMlf9pmNTasSy4KhF0sWqjN\n3zPIGJ/2Vs6y5zvtYStkAGpyA9ybj339TXYXoYS/1Naa13csmiLQOV+AoZEBzE7I\nkv9x5Fkbi0fC9tkhrAfuyqjnjuRC5KhzubbMuJL7Da5nq7AhkUBmOgOVf9CRYT9b\ntSVLwFVYX0W3UF7rt68=\n-----END PUBLIC KEY-----\n", 1395 }, 1396 Scheme: "rsassa-pss-sha256", 1397 }, 1398 err: ErrKeyKeyTypeMismatch, 1399 }, 1400 { 1401 name: "ecdsa key, but rsa key type", 1402 key: Key{ 1403 KeyID: "b7d643dec0a051096ee5d87221b5d91a33daa658699d30903e1cefb90c418401", 1404 KeyIDHashAlgorithms: []string{"sha256"}, 1405 KeyType: "ecdsa", 1406 KeyVal: KeyVal{ 1407 Private: "-----BEGIN PRIVATE KEY-----\nMIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB6fQnV71xKx6kFgJv\nYTMq0ytvWi2mDlYu6aNm1761c1OSInbBxBNb0ligpM65KyaeeRce6JR9eQW6TB6R\n+5pNzvOhgYkDgYYABAFy0CeDAyV/2mY1NqxLLgqEXSxaqM3fM8gYn/ZWzrLnO+1h\nK2QAanID3JuPff1NdhehhL/U1prXdyyaItA5X4ChkQHMTsiS/3HkWRuLR8L22SGs\nB+7KqOeO5ELkqHO5tsy4kvsNrmersCGRQGY6A5V/0JFhP1u1JUvAVVhfRbdQXuu3\nrw==\n-----END PRIVATE KEY-----\n", 1408 Public: "-----BEGIN PUBLIC KEY-----\nMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBctAngwMlf9pmNTasSy4KhF0sWqjN\n3zPIGJ/2Vs6y5zvtYStkAGpyA9ybj339TXYXoYS/1Naa13csmiLQOV+AoZEBzE7I\nkv9x5Fkbi0fC9tkhrAfuyqjnjuRC5KhzubbMuJL7Da5nq7AhkUBmOgOVf9CRYT9b\ntSVLwFVYX0W3UF7rt68=\n-----END PUBLIC KEY-----\n", 1409 }, 1410 Scheme: "ecdsa", 1411 }, 1412 err: nil, 1413 }, 1414 } 1415 for _, table := range tables { 1416 err := validateKeyVal(table.key) 1417 if !errors.Is(err, table.err) { 1418 t.Errorf("test '%s' failed, expected error: '%s', got '%s'", table.name, table.err, err) 1419 } 1420 } 1421 } 1422 1423 func TestMatchKeyTypeScheme(t *testing.T) { 1424 tables := []struct { 1425 name string 1426 key Key 1427 err error 1428 }{ 1429 {name: "test for unsupported key type", 1430 key: Key{ 1431 KeyID: "", 1432 KeyIDHashAlgorithms: nil, 1433 KeyType: "invalid", 1434 KeyVal: KeyVal{}, 1435 Scheme: "", 1436 }, 1437 err: ErrUnsupportedKeyType, 1438 }, 1439 { 1440 name: "test for scheme key type mismatch", 1441 key: Key{ 1442 KeyID: "", 1443 KeyIDHashAlgorithms: nil, 1444 KeyType: "rsa", 1445 KeyVal: KeyVal{}, 1446 Scheme: "ed25519", 1447 }, 1448 err: ErrSchemeKeyTypeMismatch, 1449 }, 1450 } 1451 for _, table := range tables { 1452 err := matchKeyTypeScheme(table.key) 1453 if !errors.Is(err, table.err) { 1454 t.Errorf("%s returned wrong error. We got: %s, we should have got: %s", table.name, err, table.err) 1455 } 1456 } 1457 } 1458 1459 func TestValidatePublicKey(t *testing.T) { 1460 validTables := []struct { 1461 name string 1462 key Key 1463 }{ 1464 { 1465 name: "test with valid key", 1466 key: Key{ 1467 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6", 1468 KeyIDHashAlgorithms: []string{"sha512"}, 1469 KeyType: "ed25519", 1470 KeyVal: KeyVal{ 1471 Private: "", 1472 Public: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAOT5nGyAPlkxJCD00qGf12YnsHGnfe2Z1j+RxyFkbE5w=\n-----END PUBLIC KEY-----\n", 1473 }, 1474 Scheme: "ed25519", 1475 }, 1476 }, 1477 } 1478 for _, table := range validTables { 1479 err := validatePublicKey(table.key) 1480 if err != nil { 1481 t.Errorf("%s returned error %s, instead of nil", table.name, err) 1482 } 1483 } 1484 1485 invalidTables := []struct { 1486 name string 1487 key Key 1488 err error 1489 }{ 1490 { 1491 name: "test with valid key", 1492 key: Key{ 1493 KeyID: "be6371bc627318218191ce0780fd3183cce6c36da02938a477d2e4dfae1804a6", 1494 KeyIDHashAlgorithms: []string{"sha512"}, 1495 KeyType: "ed25519", 1496 KeyVal: KeyVal{ 1497 Private: "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEICmtWWk/6UydYjr7tmVUtPa7JIxHdhaJraSHXr2pSECu\n-----END PRIVATE KEY-----\n", 1498 Public: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAOT5nGyAPlkxJCD00qGf12YnsHGnfe2Z1j+RxyFkbE5w=\n-----END PUBLIC KEY-----\n", 1499 }, 1500 Scheme: "ed25519", 1501 }, 1502 err: ErrNoPublicKey, 1503 }, 1504 } 1505 for _, table := range invalidTables { 1506 err := validatePublicKey(table.key) 1507 if err != table.err { 1508 t.Errorf("%s returned unexpected error %s, we should got: %s", table.name, err, table.err) 1509 } 1510 } 1511 }