Skip to content

Commit 88e64a1

Browse files
committed
Raise on bad signature count in Metadata.verify
Change Metadata.verify(key) behavior to raise an exception if none or multiple signatures for the passed key are found on the Metadata object. Signed-off-by: Lukas Puehringer <[email protected]>
1 parent 520bc20 commit 88e64a1

File tree

2 files changed

+29
-25
lines changed

2 files changed

+29
-25
lines changed

tests/test_api.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def setUpModule():
2828

2929
# Since setUpModule is called after imports we need to import conditionally.
3030
if IS_PY_VERSION_SUPPORTED:
31+
import tuf.exceptions
3132
from tuf.api.metadata import (
3233
Metadata,
3334
Snapshot,
@@ -152,12 +153,9 @@ def test_sign_verify(self):
152153

153154
# ... it has a single existing signature,
154155
self.assertTrue(len(metadata_obj.signatures) == 1)
155-
# ... valid for the correct key, but
156+
# ... which is valid for the correct key.
156157
self.assertTrue(metadata_obj.verify(
157158
self.keystore['targets']['public']))
158-
# ... invalid for an unrelated key.
159-
self.assertFalse(metadata_obj.verify(
160-
self.keystore['snapshot']['public']))
161159

162160
# Append a new signature with the unrelated key and assert that ...
163161
metadata_obj.sign(self.keystore['snapshot']['private'], append=True)
@@ -177,15 +175,20 @@ def test_sign_verify(self):
177175
self.assertTrue(metadata_obj.verify(
178176
self.keystore['timestamp']['public']))
179177

180-
181-
# Update the metadata, invalidating the existing signature, append
182-
# a new signature with the same key, and assert that ...
183-
metadata_obj.signed.bump_version()
178+
# Assert exception if there are more than one signatures for a key
184179
metadata_obj.sign(self.keystore['timestamp']['private'], append=True)
185-
# ... verify returns False, because all signatures identified by a
186-
# keyid must be valid
187-
self.assertFalse(metadata_obj.verify(
188-
self.keystore['timestamp']['public']))
180+
with self.assertRaises(tuf.exceptions.Error) as ctx:
181+
metadata_obj.verify(self.keystore['timestamp']['public'])
182+
self.assertTrue(
183+
'2 signatures for key' in str(ctx.exception),
184+
str(ctx.exception))
185+
186+
# Assert exception if there is no signature for a key
187+
with self.assertRaises(tuf.exceptions.Error) as ctx:
188+
metadata_obj.verify(self.keystore['targets']['public'])
189+
self.assertTrue(
190+
'no signature for' in str(ctx.exception),
191+
str(ctx.exception))
189192

190193

191194
def test_metadata_base(self):

tuf/api/metadata.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
import iso8601
4747
import tuf.formats
48+
import tuf.exceptions
4849

4950

5051
# Types
@@ -242,33 +243,33 @@ def verify(self, key: JsonDict) -> bool:
242243
key: A securesystemslib-style public key object.
243244
244245
Raises:
246+
# TODO: Revise exception taxonomy
247+
tuf.exceptions.Error: None or multiple signatures found for key.
245248
securesystemslib.exceptions.FormatError: Key argument is malformed.
246249
securesystemslib.exceptions.CryptoError, \
247250
securesystemslib.exceptions.UnsupportedAlgorithmError:
248251
Signing errors.
249252
250253
Returns:
251-
A boolean indicating if all identified signatures are valid. False
252-
if no signature was found for the keyid or any of the found
253-
signatures is invalid.
254-
255-
FIXME: Is this behavior expected? An alternative approach would be
256-
to raise an exception if no signature is found for the keyid,
257-
and/or if more than one sigantures are found for the keyid.
254+
A boolean indicating if the signature is valid for the passed key.
258255
259256
"""
260257
signatures_for_keyid = list(filter(
261258
lambda sig: sig['keyid'] == key['keyid'], self.signatures))
262259

263260
if not signatures_for_keyid:
264-
return False
261+
raise tuf.exceptions.Error(
262+
f'no signature for key {key["keyid"]}.')
265263

266-
for signature in signatures_for_keyid:
267-
if not verify_signature(
268-
key, signature, self.signed.to_canonical_bytes()):
269-
return False
264+
elif len(signatures_for_keyid) > 1:
265+
raise tuf.exceptions.Error(
266+
f'{len(signatures_for_keyid)} signatures for key '
267+
f'{key["keyid"]}, not sure which one to verify.')
268+
else:
269+
return verify_signature(
270+
key, signatures_for_keyid[0],
271+
self.signed.to_canonical_bytes())
270272

271-
return True
272273

273274

274275
class Signed:

0 commit comments

Comments
 (0)