diff --git a/scripts/transparency_signing.py b/scripts/transparency_signing.py index f587bf9e2..95dcd5d40 100644 --- a/scripts/transparency_signing.py +++ b/scripts/transparency_signing.py @@ -20,6 +20,7 @@ from scripts.transparency_core import failure REQUIRED_MINISIGN_VERSION = "minisign 0.12" MISSING_MINISIGN_MESSAGE = "transparency-minisign: minisign 0.12 is required; install it with: sudo dnf install minisign" +TRUSTED_COMMENT_PREFIX = "trusted comment: " class TransparencySigner(Protocol): @@ -78,6 +79,21 @@ def check_minisign_binary(minisign: str = "minisign") -> str: return version +def _extract_trusted_comment(line: str, *, malformed_error: str, repair: str) -> str: + if not line.startswith(TRUSTED_COMMENT_PREFIX): + raise DriverError( + [ + failure( + malformed_error, + expected=f"{TRUSTED_COMMENT_PREFIX}", + actual=line, + repair=repair, + ) + ] + ) + return line[len(TRUSTED_COMMENT_PREFIX) :] + + @dataclass class LocalMinisignSigner: secret_key: Path @@ -180,7 +196,6 @@ class LocalMinisignSigner: text=True, check=False, ) - comment = result.stdout.strip() if result.returncode != 0: raise DriverError( [ @@ -194,6 +209,7 @@ class LocalMinisignSigner: ) ] ) + comment = result.stdout.strip() if comment != expected_trusted_comment: raise DriverError( [ @@ -219,7 +235,11 @@ class LocalMinisignSigner: ) ] ) - return lines[2] + return _extract_trusted_comment( + lines[2], + malformed_error="transparency minisign trusted comment line is malformed", + repair="re-sign the transparency object with minisign 0.12", + ) @dataclass(frozen=True) @@ -244,7 +264,7 @@ class FakeTransparencySigner: ( "untrusted comment: fake transparency signature", base64.b64encode(digest).decode("ascii"), - trusted_comment, + f"trusted comment: {trusted_comment}", f"trusted comment signature: {hashlib.sha256(digest).hexdigest()}", "", ) @@ -271,7 +291,7 @@ class FakeTransparencySigner: ) ] ) - comment = lines[2] + comment = self.trusted_comment(signature_path) if comment != expected_trusted_comment: raise DriverError( [ @@ -313,4 +333,8 @@ class FakeTransparencySigner: ) ] ) - return lines[2] + return _extract_trusted_comment( + lines[2], + malformed_error="fake transparency trusted comment line is malformed", + repair="re-sign the transparency object", + ) diff --git a/tests/test_transparency_signing.py b/tests/test_transparency_signing.py index 831edbd4a..9a72dbf51 100644 --- a/tests/test_transparency_signing.py +++ b/tests/test_transparency_signing.py @@ -5,7 +5,7 @@ from pathlib import Path import pytest from scripts.release_candidate_driver import DriverError -from scripts.transparency_signing import FakeTransparencySigner +from scripts.transparency_signing import TRUSTED_COMMENT_PREFIX, FakeTransparencySigner def test_fake_signer_verifies_body_and_trusted_comment(tmp_path: Path) -> None: @@ -39,7 +39,8 @@ def test_fake_signer_trusted_comment_is_line_three(tmp_path: Path) -> None: message.write_bytes(b'{"ok":1}\n') signer.sign_file(message, signature, trusted_comment=comment) lines = signature.read_text(encoding="utf-8").splitlines() - assert lines[2] == comment + assert len(lines) == 4 + assert lines[2] == f"{TRUSTED_COMMENT_PREFIX}{comment}" assert signer.trusted_comment(signature) == comment @@ -68,3 +69,26 @@ def test_fake_signer_rejects_trusted_comment_mismatch(tmp_path: Path) -> None: with pytest.raises(DriverError) as error: signer.verify_file(message, signature, expected_trusted_comment="two") assert error.value.failures[0].error == "fake transparency trusted comment mismatch" + + +def test_fake_signer_rejects_missing_trusted_comment_prefix(tmp_path: Path) -> None: + signer = FakeTransparencySigner() + signature = tmp_path / "latest.json.minisig" + signature.write_text( + "\n".join( + ( + "untrusted comment: fake transparency signature", + "ZmFrZQ==", + "raw trusted comment", + "trusted comment signature: fake", + "", + ) + ), + encoding="utf-8", + ) + with pytest.raises(DriverError) as error: + signer.trusted_comment(signature) + assert ( + error.value.failures[0].error + == "fake transparency trusted comment line is malformed" + )