|
47 | 47 | TargetFile, |
48 | 48 | Targets, |
49 | 49 | Timestamp, |
| 50 | + VerificationResult, |
50 | 51 | ) |
51 | 52 | from tuf.api.serialization import DeserializationError, SerializationError |
52 | 53 | from tuf.api.serialization.json import JSONSerializer |
@@ -470,6 +471,96 @@ def test_signed_verify_delegate(self) -> None: |
470 | 471 | Snapshot.type, snapshot_md.signed_bytes, snapshot_md.signatures |
471 | 472 | ) |
472 | 473 |
|
| 474 | + def test_signed_get_verification_result(self) -> None: |
| 475 | + # Setup: Load test metadata and keys |
| 476 | + root_path = os.path.join(self.repo_dir, "metadata", "root.json") |
| 477 | + root = Metadata[Root].from_file(root_path) |
| 478 | + initial_root_keyids = root.signed.roles[Root.type].keyids |
| 479 | + self.assertEqual(len(initial_root_keyids), 1) |
| 480 | + key1_id = initial_root_keyids[0] |
| 481 | + key2 = self.keystore[Timestamp.type] |
| 482 | + key2_id = key2["keyid"] |
| 483 | + key3_id = "123456789abcdefg" |
| 484 | + key4 = self.keystore[Snapshot.type] |
| 485 | + key4_id = key4["keyid"] |
| 486 | + |
| 487 | + # Test: 1 authorized key, 1 valid signature |
| 488 | + result = root.signed.get_verification_result( |
| 489 | + Root.type, root.signed_bytes, root.signatures |
| 490 | + ) |
| 491 | + self.assertTrue(result.verified) |
| 492 | + self.assertEqual(result.signed, {key1_id}) |
| 493 | + self.assertEqual(result.unsigned, set()) |
| 494 | + |
| 495 | + # Test: 2 authorized keys, 1 invalid signature |
| 496 | + # Adding a key, i.e. metadata change, invalidates existing signature |
| 497 | + root.signed.add_key( |
| 498 | + SSlibKey.from_securesystemslib_key(key2), |
| 499 | + Root.type, |
| 500 | + ) |
| 501 | + result = root.signed.get_verification_result( |
| 502 | + Root.type, root.signed_bytes, root.signatures |
| 503 | + ) |
| 504 | + self.assertFalse(result.verified) |
| 505 | + self.assertEqual(result.signed, set()) |
| 506 | + self.assertEqual(result.unsigned, {key1_id, key2_id}) |
| 507 | + |
| 508 | + # Test: 3 authorized keys, 1 invalid signature, 1 key missing key data |
| 509 | + # Adding a keyid w/o key, fails verification the same as no signature |
| 510 | + # or an invalid signature for that key |
| 511 | + root.signed.roles[Root.type].keyids.append(key3_id) |
| 512 | + result = root.signed.get_verification_result( |
| 513 | + Root.type, root.signed_bytes, root.signatures |
| 514 | + ) |
| 515 | + self.assertFalse(result.verified) |
| 516 | + self.assertEqual(result.signed, set()) |
| 517 | + self.assertEqual(result.unsigned, {key1_id, key2_id, key3_id}) |
| 518 | + |
| 519 | + # Test: 3 authorized keys, 1 valid signature, 1 invalid signature, 1 |
| 520 | + # key missing key data |
| 521 | + root.sign(SSlibSigner(key2), append=True) |
| 522 | + result = root.signed.get_verification_result( |
| 523 | + Root.type, root.signed_bytes, root.signatures |
| 524 | + ) |
| 525 | + self.assertTrue(result.verified) |
| 526 | + self.assertEqual(result.signed, {key2_id}) |
| 527 | + self.assertEqual(result.unsigned, {key1_id, key3_id}) |
| 528 | + |
| 529 | + # Test: 3 authorized keys, 1 valid signature, 1 invalid signature, 1 |
| 530 | + # key missing key data, 1 ignored unrelated signature |
| 531 | + root.sign(SSlibSigner(key4), append=True) |
| 532 | + self.assertEqual( |
| 533 | + set(root.signatures.keys()), {key1_id, key2_id, key4_id} |
| 534 | + ) |
| 535 | + self.assertTrue(result.verified) |
| 536 | + self.assertEqual(result.signed, {key2_id}) |
| 537 | + self.assertEqual(result.unsigned, {key1_id, key3_id}) |
| 538 | + |
| 539 | + # See test_signed_verify_delegate for more related tests ... |
| 540 | + |
| 541 | + def test_signed_verification_result_union(self) -> None: |
| 542 | + # Test all possible "unions" (AND) of "verified" field |
| 543 | + data = [ |
| 544 | + (True, True, True), |
| 545 | + (True, False, False), |
| 546 | + (False, True, False), |
| 547 | + (False, False, False), |
| 548 | + ] |
| 549 | + |
| 550 | + for a_part, b_part, ab_part in data: |
| 551 | + self.assertEqual( |
| 552 | + VerificationResult(a_part, set(), set()).union( |
| 553 | + VerificationResult(b_part, set(), set()) |
| 554 | + ), |
| 555 | + VerificationResult(ab_part, set(), set()), |
| 556 | + ) |
| 557 | + |
| 558 | + # Test exemplary union (|) of "signed" and "unsigned" fields |
| 559 | + a = VerificationResult(True, {"1"}, {"2"}) |
| 560 | + b = VerificationResult(True, {"3"}, {"4"}) |
| 561 | + ab = VerificationResult(True, {"1", "3"}, {"2", "4"}) |
| 562 | + self.assertEqual(a.union(b), ab) |
| 563 | + |
473 | 564 | def test_key_class(self) -> None: |
474 | 565 | # Test if from_securesystemslib_key removes the private key from keyval |
475 | 566 | # of a securesystemslib key dictionary. |
|
0 commit comments