summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2023-01-22 11:26:26 +0100
committerMichał Górny <mgorny@gentoo.org>2023-01-22 11:31:19 +0100
commit75d3b7abba57ed5099b302ccbba506d8f175bc9d (patch)
treef1bd3e1d23164967f5d4cf10e645a3e5a9ff71ac
parent5702581b9a92ea2fc02190d66ad9a274011eebe4 (diff)
downloadgemato-75d3b7abba57ed5099b302ccbba506d8f175bc9d.tar.gz
openpgp: Allow verifying a subset of signatures
Signed-off-by: Michał Górny <mgorny@gentoo.org>
-rw-r--r--gemato/openpgp.py17
-rw-r--r--tests/test_openpgp.py32
2 files changed, 49 insertions, 0 deletions
diff --git a/gemato/openpgp.py b/gemato/openpgp.py
index 8c1db59..16a369e 100644
--- a/gemato/openpgp.py
+++ b/gemato/openpgp.py
@@ -167,12 +167,18 @@ class SystemGPGEnvironment:
def verify_file(self,
f: typing.IO[str],
+ require_all_good: bool = True,
) -> OpenPGPSignatureList:
"""
Perform an OpenPGP verification of Manifest data in open file @f.
The file should be open in text mode and set at the beginning
(or start of signed part). Raises an exception if the verification
fails.
+
+ If require_all_good is True and the file contains multiple OpenPGP
+ signatures, all signatures have to be good and trusted in order
+ for the verificatin to succeed. Otherwise, a single good signature
+ is considered sufficient.
"""
exitst, out, err = self._spawn_gpg(
@@ -231,6 +237,17 @@ class SystemGPGEnvironment:
raise OpenPGPUnknownSigFailure(
err.decode('utf8', errors='backslashreplace'))
+ # bad signature causes failure even without require_all_good
+ for sig in sig_list:
+ if sig.sig_status == OpenPGPSignatureStatus.BAD:
+ raise OpenPGPVerificationFailure(
+ err.decode("utf8", errors="backslashreplace"), sig)
+
+ if not require_all_good:
+ if any(x.sig_status == OpenPGPSignatureStatus.GOOD and
+ x.valid_sig and x.trusted_sig for x in sig_list):
+ return sig_list
+
for sig in sig_list:
if sig.sig_status == OpenPGPSignatureStatus.GOOD:
pass
diff --git a/tests/test_openpgp.py b/tests/test_openpgp.py
index 6702471..22ef6cf 100644
--- a/tests/test_openpgp.py
+++ b/tests/test_openpgp.py
@@ -484,6 +484,38 @@ def test_verify_manifest(openpgp_env, manifest_var, key_var, expected):
pytest.skip(str(e))
+def test_verify_one_out_of_two():
+ try:
+ with MockedSystemGPGEnvironment() as openpgp_env:
+ with io.BytesIO(VALID_PUBLIC_KEY) as f:
+ openpgp_env.import_key(f)
+
+ with io.StringIO(TWO_SIGNATURE_MANIFEST) as f:
+ sig = openpgp_env.verify_file(f, require_all_good=False)
+
+ assert sig == [
+ OpenPGPSignatureData(
+ fingerprint="81E12C16BD8DCD60BE180845136880E72A7B1384",
+ timestamp=datetime.datetime(2023, 1, 21, 17, 14, 44),
+ expire_timestamp=None,
+ primary_key_fingerprint="81E12C16BD8DCD60BE18"
+ "0845136880E72A7B1384",
+ sig_status=OpenPGPSignatureStatus.GOOD,
+ valid_sig=True,
+ trusted_sig=True),
+ OpenPGPSignatureData(
+ fingerprint="",
+ timestamp=None,
+ expire_timestamp=None,
+ primary_key_fingerprint="",
+ sig_status=OpenPGPSignatureStatus.NO_PUBLIC_KEY,
+ valid_sig=False,
+ trusted_sig=False),
+ ]
+ except OpenPGPNoImplementation as e:
+ pytest.skip(str(e))
+
+
def test_verify_untrusted_key():
try:
with MockedSystemGPGEnvironment() as openpgp_env: