tests/test_signer.py
3.2 KB · 91 lines · python Raw
1 """Tests for ManifestSigner: sign + verify flows."""
2
3 from __future__ import annotations
4
5 import pytest
6
7 from pqc_content_provenance import (
8 ContentManifest,
9 ManifestSigner,
10 )
11 from pqc_content_provenance.errors import ContentHashMismatchError
12
13
14 def test_sign_populates_signature_fields(signer, sample_manifest: ContentManifest) -> None:
15 signed = signer.sign(sample_manifest)
16 assert signed.signer_did != ""
17 assert signed.signer_did.startswith("did:pqaid:")
18 assert signed.algorithm != ""
19 assert signed.signature != ""
20 assert signed.public_key != ""
21 assert signed.signed_at != ""
22
23
24 def test_verify_valid_manifest_returns_valid(signer, sample_manifest: ContentManifest) -> None:
25 signed = signer.sign(sample_manifest)
26 result = ManifestSigner.verify(signed)
27 assert result.valid is True
28 assert result.signature_match is True
29 assert result.content_hash_match is True
30 assert result.signer_did == signed.signer_did
31 assert result.error is None
32
33
34 def test_verify_with_content_passes_when_match(
35 signer, sample_manifest: ContentManifest, sample_content: bytes
36 ) -> None:
37 signed = signer.sign(sample_manifest)
38 result = ManifestSigner.verify(signed, sample_content)
39 assert result.valid is True
40 assert result.content_hash_match is True
41
42
43 def test_verify_with_content_fails_when_mismatch(
44 signer, sample_manifest: ContentManifest
45 ) -> None:
46 signed = signer.sign(sample_manifest)
47 tampered_content = b"A totally different piece of text, not the original."
48 result = ManifestSigner.verify(signed, tampered_content)
49 assert result.valid is False
50 assert result.content_hash_match is False
51 # Signature itself is still valid (only the content-hash check fails)
52 assert result.signature_match is True
53 assert result.error is not None
54 assert "content hash" in result.error
55
56
57 def test_verify_tampered_manifest_fails(signer, sample_manifest: ContentManifest) -> None:
58 signed = signer.sign(sample_manifest)
59 # Tamper: change the content_type after signing
60 signed.content_type = "application/malicious"
61 result = ManifestSigner.verify(signed)
62 assert result.valid is False
63 assert result.signature_match is False
64
65
66 def test_verify_wrong_algorithm_returns_error(signer, sample_manifest: ContentManifest) -> None:
67 signed = signer.sign(sample_manifest)
68 signed.algorithm = "NOT-A-REAL-ALG"
69 result = ManifestSigner.verify(signed)
70 assert result.valid is False
71 assert result.signature_match is False
72 assert result.error is not None
73 assert "unknown algorithm" in result.error
74
75
76 def test_sign_and_raise_on_mismatch_raises_when_content_diff(
77 signer, sample_manifest: ContentManifest
78 ) -> None:
79 different_content = b"This content is not what the manifest claims."
80 with pytest.raises(ContentHashMismatchError):
81 signer.sign_and_raise_on_mismatch(sample_manifest, different_content)
82
83
84 def test_sign_and_raise_on_mismatch_succeeds_when_match(
85 signer, sample_manifest: ContentManifest, sample_content: bytes
86 ) -> None:
87 signed = signer.sign_and_raise_on_mismatch(sample_manifest, sample_content)
88 assert signed.signature != ""
89 result = ManifestSigner.verify(signed, sample_content)
90 assert result.valid is True
91