diff --git a/setup.py b/setup.py index 7984d2d662..10aa219248 100755 --- a/setup.py +++ b/setup.py @@ -113,7 +113,7 @@ python_requires="~=3.6", install_requires = [ 'requests>=2.19.1', - 'securesystemslib>=0.18.0', + 'securesystemslib>=0.20.0', 'six>=1.11.0' ], packages = find_packages(exclude=['tests']), diff --git a/tests/test_api.py b/tests/test_api.py index ec7d182b79..606e62997e 100755 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -37,6 +37,10 @@ format_keyval_to_metadata ) +from securesystemslib.signer import ( + SSlibSigner +) + logger = logging.getLogger(__name__) @@ -153,8 +157,9 @@ def test_sign_verify(self): self.assertTrue(metadata_obj.verify( self.keystore['targets']['public'])) + sslib_signer = SSlibSigner(self.keystore['snapshot']['private']) # Append a new signature with the unrelated key and assert that ... - metadata_obj.sign(self.keystore['snapshot']['private'], append=True) + metadata_obj.sign(sslib_signer, append=True) # ... there are now two signatures, and self.assertTrue(len(metadata_obj.signatures) == 2) # ... both are valid for the corresponding keys. @@ -163,8 +168,9 @@ def test_sign_verify(self): self.assertTrue(metadata_obj.verify( self.keystore['snapshot']['public'])) + sslib_signer.key_dict = self.keystore['timestamp']['private'] # Create and assign (don't append) a new signature and assert that ... - metadata_obj.sign(self.keystore['timestamp']['private'], append=False) + metadata_obj.sign(sslib_signer, append=False) # ... there now is only one signature, self.assertTrue(len(metadata_obj.signatures) == 1) # ... valid for that key. @@ -172,7 +178,7 @@ def test_sign_verify(self): self.keystore['timestamp']['public'])) # Assert exception if there are more than one signatures for a key - metadata_obj.sign(self.keystore['timestamp']['private'], append=True) + metadata_obj.sign(sslib_signer, append=True) with self.assertRaises(tuf.exceptions.Error) as ctx: metadata_obj.verify(self.keystore['timestamp']['public']) self.assertTrue( diff --git a/tuf/api/metadata.py b/tuf/api/metadata.py index a747be6d13..73280db1e4 100644 --- a/tuf/api/metadata.py +++ b/tuf/api/metadata.py @@ -19,7 +19,8 @@ persist_temp_file ) from securesystemslib.storage import StorageBackendInterface -from securesystemslib.keys import create_signature, verify_signature +from securesystemslib.keys import verify_signature +from securesystemslib.signer import Signer, Signature import tuf.formats import tuf.exceptions @@ -92,12 +93,14 @@ class also that has a 'from_dict' factory method. (Currently this is else: raise ValueError(f'unrecognized metadata type "{_type}"') - # NOTE: If Signature becomes a class, we should iterate over - # metadata['signatures'], call Signature.from_dict for each item, and - # pass a list of Signature objects to the Metadata constructor intead. + signatures = [] + for signature in metadata['signatures']: + signature_obj = Signature.from_dict(signature) + signatures.append(signature_obj) + return cls( signed=inner_cls.from_dict(metadata['signed']), - signatures=metadata['signatures']) + signatures=signatures) @classmethod @@ -146,8 +149,13 @@ def from_json_file( # Serialization. def to_dict(self) -> JsonDict: """Returns the JSON-serializable dictionary representation of self. """ + + signatures = [] + for sig in self.signatures: + signatures.append(sig.to_dict()) + return { - 'signatures': self.signatures, + 'signatures': signatures, 'signed': self.signed.to_dict() } @@ -184,11 +192,12 @@ def to_json_file( # Signatures. - def sign(self, key: JsonDict, append: bool = False) -> JsonDict: + def sign(self, signer: Signer, append: bool = False) -> JsonDict: """Creates signature over 'signed' and assigns it to 'signatures'. Arguments: - key: A securesystemslib-style private key object used for signing. + singer: An object implementing the securesystemslib.signer.Signer + interface. append: A boolean indicating if the signature should be appended to the list of signatures or replace any existing signatures. The default behavior is to replace signatures. @@ -203,7 +212,7 @@ def sign(self, key: JsonDict, append: bool = False) -> JsonDict: A securesystemslib-style signature object. """ - signature = create_signature(key, self.signed.to_canonical_bytes()) + signature = signer.sign(self.signed.to_canonical_bytes()) if append: self.signatures.append(signature) @@ -232,7 +241,7 @@ def verify(self, key: JsonDict) -> bool: """ signatures_for_keyid = list(filter( - lambda sig: sig['keyid'] == key['keyid'], self.signatures)) + lambda sig: sig.keyid == key['keyid'], self.signatures)) if not signatures_for_keyid: raise tuf.exceptions.Error( @@ -244,7 +253,7 @@ def verify(self, key: JsonDict) -> bool: f'{key["keyid"]}, not sure which one to verify.') return verify_signature( - key, signatures_for_keyid[0], + key, signatures_for_keyid[0].to_dict(), self.signed.to_canonical_bytes())