diff --git a/dev-requirements.txt b/dev-requirements.txt index 3e7d5f16..46427b1e 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -42,7 +42,7 @@ pylint==1.9.3 ; python_version < "3.0" # pyup: ignore pynacl==1.3.0 pyyaml==5.1.2 requests==2.22.0 -securesystemslib[crypto,pynacl]==0.11.3 +securesystemslib[crypto,pynacl]==0.12.0 singledispatch==3.4.0.3 six==1.12.0 smmap2==2.0.5 diff --git a/requirements.txt b/requirements.txt index 72eda1e2..ffc70db2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -119,7 +119,7 @@ pynacl==1.3.0 \ requests==2.22.0 \ --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 \ --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31 -securesystemslib==0.11.3 \ +securesystemslib==0.12.0 \ --hash=sha256:368ef6f6cc40d3636e271485c7adb21c53c22200bab44a2fe8af62886a01c3d5 \ --hash=sha256:cbd1f7f1af2f2921be33b9fd17384705f5f4147d3a8b5d95b33ec3ce2213f176 six==1.12.0 \ diff --git a/setup.py b/setup.py index 13da03e1..fb623a0f 100755 --- a/setup.py +++ b/setup.py @@ -114,7 +114,7 @@ 'iso8601>=0.1.12', 'requests>=2.19.1', 'six>=1.11.0', - 'securesystemslib>=0.11.3' + 'securesystemslib>=0.12.0' ], packages = find_packages(exclude=['tests']), scripts = [ diff --git a/tests/test_download.py b/tests/test_download.py index 672e70d7..951c8633 100755 --- a/tests/test_download.py +++ b/tests/test_download.py @@ -111,9 +111,11 @@ def test_download_url_to_tempfileobj(self): download_file = download.safe_download temp_fileobj = download_file(self.url, self.target_data_length) - self.assertEqual(self.target_data, temp_fileobj.read().decode('utf-8')) - self.assertEqual(self.target_data_length, len(temp_fileobj.read())) - temp_fileobj.close_temp_file() + temp_fileobj.seek(0) + temp_file_data = temp_fileobj.read().decode('utf-8') + self.assertEqual(self.target_data, temp_file_data) + self.assertEqual(self.target_data_length, len(temp_file_data)) + temp_fileobj.close() @@ -158,7 +160,7 @@ def test_download_url_to_tempfileobj_and_performance(self): self.assertEqual(self.target_data, temp_fileobj.read()) self.assertEqual(self.target_data_length, len(temp_fileobj.read())) - temp_fileobj.close_temp_file() + temp_fileobj.close() print "Performance cpu time: "+str(end_cpu - star_cpu) print "Performance real time: "+str(end_real - star_real) diff --git a/tests/test_repository_lib.py b/tests/test_repository_lib.py index 044b4555..557427ed 100755 --- a/tests/test_repository_lib.py +++ b/tests/test_repository_lib.py @@ -906,8 +906,9 @@ def test__remove_invalid_and_duplicate_signatures(self): # Append the new valid, but duplicate PSS signature, and test that # duplicates are removed. create_signature() generates a key for the # key type of the first argument (i.e., root_rsa_key). + data = securesystemslib.formats.encode_canonical(root_signable['signed']).encode('utf-8') new_pss_signature = securesystemslib.keys.create_signature(root_rsa_key, - root_signable['signed']) + data) root_signable['signatures'].append(new_pss_signature) expected_number_of_signatures = len(root_signable['signatures']) diff --git a/tests/test_sig.py b/tests/test_sig.py index 7ebd7623..14ce25f0 100755 --- a/tests/test_sig.py +++ b/tests/test_sig.py @@ -82,8 +82,9 @@ def test_get_signature_status_no_role(self): # Should verify we are not adding a duplicate signature # when doing the following action. Here we know 'signable' # has only one signature so it's okay. + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) tuf.keydb.add_key(KEYS[0]) @@ -101,9 +102,10 @@ def test_get_signature_status_no_role(self): def test_get_signature_status_bad_sig(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) signable['signed'] += 'signature no longer matches signed data' tuf.keydb.add_key(KEYS[0]) @@ -133,9 +135,10 @@ def test_get_signature_status_bad_sig(self): def test_get_signature_status_unknown_signing_scheme(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) valid_scheme = KEYS[0]['scheme'] KEYS[0]['scheme'] = 'unknown_signing_scheme' @@ -168,9 +171,10 @@ def test_get_signature_status_unknown_signing_scheme(self): def test_get_signature_status_single_key(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) threshold = 1 @@ -209,9 +213,10 @@ def test_get_signature_status_single_key(self): def test_get_signature_status_below_threshold(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) tuf.keydb.add_key(KEYS[0]) threshold = 2 @@ -243,12 +248,13 @@ def test_get_signature_status_below_threshold(self): def test_get_signature_status_below_threshold_unrecognized_sigs(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') # Two keys sign it, but only one of them will be trusted. signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[2], signable['signed'])) + KEYS[2], signed)) tuf.keydb.add_key(KEYS[0]) tuf.keydb.add_key(KEYS[1]) @@ -282,13 +288,13 @@ def test_get_signature_status_below_threshold_unrecognized_sigs(self): def test_get_signature_status_below_threshold_unauthorized_sigs(self): signable = {'signed' : 'test', 'signatures' : []} - + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') # Two keys sign it, but one of them is only trusted for a different # role. signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[1], signable['signed'])) + KEYS[1], signed)) tuf.keydb.add_key(KEYS[0]) tuf.keydb.add_key(KEYS[1]) @@ -334,9 +340,10 @@ def test_get_signature_status_below_threshold_unauthorized_sigs(self): def test_check_signatures_no_role(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) tuf.keydb.add_key(KEYS[0]) @@ -353,8 +360,10 @@ def test_check_signatures_no_role(self): def test_verify_single_key(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') + signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) tuf.keydb.add_key(KEYS[0]) threshold = 1 @@ -377,12 +386,13 @@ def test_verify_single_key(self): def test_verify_unrecognized_sig(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') # Two keys sign it, but only one of them will be trusted. signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[2], signable['signed'])) + KEYS[2], signed)) tuf.keydb.add_key(KEYS[0]) tuf.keydb.add_key(KEYS[1]) @@ -408,9 +418,10 @@ def test_verify_unrecognized_sig(self): def test_generate_rsa_signature(self): signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) self.assertEqual(1, len(signable['signatures'])) signature = signable['signatures'][0] @@ -420,7 +431,7 @@ def test_generate_rsa_signature(self): self.assertTrue(securesystemslib.formats.SIGNATURE_SCHEMA.matches(returned_signature)) signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[1], signable['signed'])) + KEYS[1], signed)) self.assertEqual(2, len(signable['signatures'])) signature = signable['signatures'][1] @@ -431,9 +442,10 @@ def test_generate_rsa_signature(self): def test_may_need_new_keys(self): # One untrusted key in 'signable'. signable = {'signed' : 'test', 'signatures' : []} + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signable['signatures'].append(securesystemslib.keys.create_signature( - KEYS[0], signable['signed'])) + KEYS[0], signed)) tuf.keydb.add_key(KEYS[1]) threshold = 1 diff --git a/tests/test_updater.py b/tests/test_updater.py index 944623c6..08999047 100644 --- a/tests/test_updater.py +++ b/tests/test_updater.py @@ -1568,7 +1568,7 @@ def test_9__get_target_hash(self): def test_10__hard_check_file_length(self): # Test for exception if file object is not equal to trusted file length. - temp_file_object = securesystemslib.util.TempFile() + temp_file_object = tempfile.TemporaryFile() temp_file_object.write(b'X') temp_file_object.seek(0) self.assertRaises(tuf.exceptions.DownloadLengthMismatchError, @@ -1581,7 +1581,7 @@ def test_10__hard_check_file_length(self): def test_10__soft_check_file_length(self): # Test for exception if file object is not equal to trusted file length. - temp_file_object = securesystemslib.util.TempFile() + temp_file_object = tempfile.TemporaryFile() temp_file_object.write(b'XXX') temp_file_object.seek(0) self.assertRaises(tuf.exceptions.DownloadLengthMismatchError, @@ -1704,7 +1704,7 @@ def test_10__visit_child_role(self): def test_11__verify_uncompressed_metadata_file(self): # Test for invalid metadata content. - metadata_file_object = securesystemslib.util.TempFile() + metadata_file_object = tempfile.TemporaryFile() metadata_file_object.write(b'X') metadata_file_object.seek(0) diff --git a/tuf/client/updater.py b/tuf/client/updater.py index c3cba73a..62229421 100755 --- a/tuf/client/updater.py +++ b/tuf/client/updater.py @@ -1192,9 +1192,7 @@ def _check_hashes(self, file_object, trusted_hashes): file_object: - A 'securesystemslib.util.TempFile' file-like object. 'file_object' - ensures that a read() without a size argument properly reads the entire - file. + A file object. trusted_hashes: A dictionary with hash-algorithm names as keys and hashes as dict values. @@ -1206,6 +1204,7 @@ def _check_hashes(self, file_object, trusted_hashes): Hash digest object is created using the 'securesystemslib.hash' module. + Position within file_object is changed. None. @@ -1215,6 +1214,10 @@ def _check_hashes(self, file_object, trusted_hashes): # return. for algorithm, trusted_hash in six.iteritems(trusted_hashes): digest_object = securesystemslib.hash.digest(algorithm) + # Ensure we read from the beginning of the file object + # TODO: should we store file position (before the loop) and reset after we + # seek about? + file_object.seek(0) digest_object.update(file_object.read()) computed_hash = digest_object.hexdigest() @@ -1241,9 +1244,7 @@ def _hard_check_file_length(self, file_object, trusted_file_length): file_object: - A 'securesystemslib.util.TempFile' file-like object. 'file_object' - ensures that a read() without a size argument properly reads the entire - file. + A file object. trusted_file_length: A non-negative integer that is the trusted length of the file. @@ -1254,14 +1255,13 @@ def _hard_check_file_length(self, file_object, trusted_file_length): Reads the contents of 'file_object' and logs a message if 'file_object' matches the trusted length. + Position within file_object is changed. None. """ - # Read the entire contents of 'file_object', a - # 'securesystemslib.util.TempFile' file-like object that ensures the entire - # file is read. + file_object.seek(0) observed_length = len(file_object.read()) # Return and log a message if the length 'file_object' is equal to @@ -1283,17 +1283,14 @@ def _hard_check_file_length(self, file_object, trusted_file_length): def _soft_check_file_length(self, file_object, trusted_file_length): """ - Non-public method that checks the trusted file length of a - 'securesystemslib.util.TempFile' file-like object. The length of the file - must be less than or equal to the expected length. This is a deliberately - redundant implementation designed to complement - tuf.download._check_downloaded_length(). + Non-public method that checks the trusted file length of a file object. + The length of the file must be less than or equal to the expected + length. This is a deliberately redundant implementation designed to + complement tuf.download._check_downloaded_length(). file_object: - A 'securesystemslib.util.TempFile' file-like object. 'file_object' - ensures that a read() without a size argument properly reads the entire - file. + A file object. trusted_file_length: A non-negative integer that is the trusted length of the file. @@ -1305,14 +1302,14 @@ def _soft_check_file_length(self, file_object, trusted_file_length): Reads the contents of 'file_object' and logs a message if 'file_object' is less than or equal to the trusted length. + Position within file_object is changed. None. """ # Read the entire contents of 'file_object', a - # 'securesystemslib.util.TempFile' file-like object that ensures the entire - # file is read. + file_object.seek(0) observed_length = len(file_object.read()) # Return and log a message if 'file_object' is less than or equal to @@ -1360,7 +1357,7 @@ def _get_target_file(self, target_filepath, file_length, file_hashes): a temporary file and returned. - A 'securesystemslib.util.TempFile' file-like object containing the target. + A file object containing the target. """ # Define a callable function that is passed as an argument to _get_file() @@ -1396,9 +1393,7 @@ def _verify_uncompressed_metadata_file(self, metadata_file_object, metadata_file_object: - A 'securesystemslib.util.TempFile' instance containing the metadata - file. 'metadata_file_object' ensures the entire file is returned with - read(). + A file object containing the metadata file. metadata_role: The role name of the metadata (e.g., 'root', 'targets', @@ -1422,12 +1417,14 @@ def _verify_uncompressed_metadata_file(self, metadata_file_object, In case the metadata file does not have a valid signature. - The content of 'metadata_file_object' is read and loaded. + The content of 'metadata_file_object' is read and loaded, the current + position within the file is changed. None. """ + metadata_file_object.seek(0) metadata = metadata_file_object.read().decode('utf-8') try: @@ -1494,8 +1491,7 @@ def _get_metadata_file(self, metadata_role, remote_filename, file and returned. - A 'securesystemslib.util.TempFile' file-like object containing the - metadata. + A file object containing the metadata. """ file_mirrors = tuf.mirrors.get_list_of_mirrors('meta', remote_filename, @@ -1509,6 +1505,7 @@ def _get_metadata_file(self, metadata_role, remote_filename, try: file_object = tuf.download.unsafe_download(file_mirror, upperbound_filelength) + file_object.seek(0) # Verify 'file_object' according to the callable function. # 'file_object' is also verified if decompressed above (i.e., the @@ -1639,8 +1636,8 @@ def _get_file(self, filepath, verify_file_function, file_type, file_length, The relative metadata or target filepath. verify_file_function: - A callable function that expects a 'securesystemslib.util.TempFile' - file-like object and raises an exception if the file is invalid. + A callable function that expects a file object and raises an exception + if the file is invalid. Target files and uncompressed versions of metadata may be verified with 'verify_file_function'. @@ -1668,8 +1665,7 @@ def _get_file(self, filepath, verify_file_function, file_type, file_length, file and returned. - A 'securesystemslib.util.TempFile' file-like object containing the - metadata or target. + A file object containing the metadata or target. """ file_mirrors = tuf.mirrors.get_list_of_mirrors(file_type, filepath, @@ -1807,12 +1803,11 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None): shutil.move(current_filepath, previous_filepath) # Next, move the verified updated metadata file to the 'current' directory. - # Note that the 'move' method comes from securesystemslib.util's TempFile class. - # 'metadata_file_object' is an instance of securesystemslib.util.TempFile. + metadata_file_object.seek(0) metadata_signable = \ securesystemslib.util.load_json_string(metadata_file_object.read().decode('utf-8')) - metadata_file_object.move(current_filepath) + securesystemslib.util.persist_temp_file(metadata_file_object, current_filepath) # Extract the metadata object so we can store it to the metadata store. # 'current_metadata_object' set to 'None' if there is not an object @@ -3279,4 +3274,4 @@ def download_target(self, target, destination_directory): else: raise - target_file_object.move(destination) + securesystemslib.util.persist_temp_file(target_file_object, destination) diff --git a/tuf/download.py b/tuf/download.py index cf7aac06..7f193927 100755 --- a/tuf/download.py +++ b/tuf/download.py @@ -20,10 +20,7 @@ Download metadata and target files and check their validity. The hash and length of a downloaded file has to match the hash and length supplied by the - metadata of that file. The downloaded file is technically a file-like - object that will automatically destroys itself once closed. Note that the - file-like object, 'securesystemslib.util.TempFile', is returned by the - '_download_file()' function. + metadata of that file. """ # Help with Python 3 compatibility, where the print statement is a function, an @@ -37,6 +34,7 @@ import logging import time import timeit +import tempfile import tuf import requests @@ -76,11 +74,6 @@ def safe_download(url, required_length): tuf.download.unsafe_download() may be called if an upper download limit is preferred. - 'securesystemslib.util.TempFile', the file-like object returned, is used - instead of regular tempfile object because of additional functionality - provided, such as handling compressed metadata and automatically closing - files after moving to final destination. - url: A URL string that represents the location of the file. @@ -90,8 +83,7 @@ def safe_download(url, required_length): limit. - A 'securesystemslib.util.TempFile' object is created on disk to store the - contents of 'url'. + A file object is created on disk to store the contents of 'url'. tuf.ssl_commons.exceptions.DownloadLengthMismatchError, if there was a @@ -103,8 +95,7 @@ def safe_download(url, required_length): Any other unforeseen runtime exception. - A 'securesystemslib.util.TempFile' file-like object that points to the - contents of 'url'. + A file object that points to the contents of 'url'. """ # Do all of the arguments have the appropriate format? @@ -127,11 +118,6 @@ def unsafe_download(url, required_length): tuf.download.safe_download() may be called if an exact download limit is preferred. - 'securesystemslib.util.TempFile', the file-like object returned, is used - instead of regular tempfile object because of additional functionality - provided, such as handling compressed metadata and automatically closing - files after moving to final destination. - url: A URL string that represents the location of the file. @@ -141,8 +127,7 @@ def unsafe_download(url, required_length): limit. - A 'securesystemslib.util.TempFile' object is created on disk to store the - contents of 'url'. + A file object is created on disk to store the contents of 'url'. tuf.ssl_commons.exceptions.DownloadLengthMismatchError, if there was a @@ -154,8 +139,7 @@ def unsafe_download(url, required_length): Any other unforeseen runtime exception. - A 'securesystemslib.util.TempFile' file-like object that points to the - contents of 'url'. + A file object that points to the contents of 'url'. """ # Do all of the arguments have the appropriate format? @@ -178,10 +162,6 @@ def _download_file(url, required_length, STRICT_REQUIRED_LENGTH=True): the file's length is not checked and a slow retrieval exception is raised if the downloaded rate falls below the acceptable rate). - securesystemslib.util.TempFile is used instead of regular tempfile object - because of additional functionality provided by - 'securesystemslib.util.TempFile'. - url: A URL string that represents the location of the file. @@ -196,8 +176,7 @@ def _download_file(url, required_length, STRICT_REQUIRED_LENGTH=True): timestamp metadata, which has no signed required_length. - A 'securesystemslib.util.TempFile' object is created on disk to store the - contents of 'url'. + A file object is created on disk to store the contents of 'url'. tuf.exceptions.DownloadLengthMismatchError, if there was a @@ -209,8 +188,7 @@ def _download_file(url, required_length, STRICT_REQUIRED_LENGTH=True): Any other unforeseen runtime exception. - A 'securesystemslib.util.TempFile' file-like object that points to the - contents of 'url'. + A file object that points to the contents of 'url'. """ # Do all of the arguments have the appropriate format? @@ -228,7 +206,7 @@ def _download_file(url, required_length, STRICT_REQUIRED_LENGTH=True): # This is the temporary file that we will return to contain the contents of # the downloaded file. - temp_file = securesystemslib.util.TempFile() + temp_file = tempfile.TemporaryFile() try: # Use a different requests.Session per schema+hostname combination, to @@ -304,7 +282,7 @@ def _download_file(url, required_length, STRICT_REQUIRED_LENGTH=True): except Exception: # Close 'temp_file'. Any written data is lost. - temp_file.close_temp_file() + temp_file.close() logger.exception('Could not download URL: ' + repr(url)) raise diff --git a/tuf/repository_lib.py b/tuf/repository_lib.py index 6d57fa04..3ca381ec 100755 --- a/tuf/repository_lib.py +++ b/tuf/repository_lib.py @@ -38,6 +38,7 @@ import shutil import json import platform +import tempfile import tuf import tuf.formats @@ -51,6 +52,7 @@ import securesystemslib import securesystemslib.hash import securesystemslib.interface +import securesystemslib.util import iso8601 import six @@ -353,7 +355,7 @@ def _remove_invalid_and_duplicate_signatures(signable, repository_name): signature_keyids = [] for signature in signable['signatures']: - signed = signable['signed'] + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') keyid = signature['keyid'] key = None @@ -1621,7 +1623,7 @@ def sign_metadata(metadata_object, keyids, filename, repository_name): # Generate the signature using the appropriate signing method. if key['keytype'] in SUPPORTED_KEY_TYPES: if 'private' in key['keyval']: - signed = signable['signed'] + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') try: signature = securesystemslib.keys.create_signature(key, signed) signable['signatures'].append(signature) @@ -1712,12 +1714,11 @@ def write_metadata_file(metadata, filename, version_number, consistent_snapshot) # The 'metadata' object is written to 'file_object'. To avoid partial # metadata from being written, 'metadata' is first written to a temporary # location (i.e., 'file_object') and then moved to 'filename'. - file_object = securesystemslib.util.TempFile() + file_object = tempfile.TemporaryFile() # Serialize 'metadata' to the file-like object and then write 'file_object' # to disk. The dictionary keys of 'metadata' are sorted and indentation is - # used. The 'securesystemslib.util.TempFile' file-like object is automically - # closed after the final move. + # used. file_object.write(file_content) if consistent_snapshot: @@ -1732,7 +1733,7 @@ def write_metadata_file(metadata, filename, version_number, consistent_snapshot) # the consistent snapshot and point 'written_filename' to it. logger.debug('Creating a consistent file for ' + repr(written_filename)) logger.debug('Saving ' + repr(written_consistent_filename)) - file_object.move(written_consistent_filename) + securesystemslib.util.persist_temp_file(file_object, written_consistent_filename) # For GitHub issue #374 https://github.com/theupdateframework/tuf/issues/374 # We provide the option of either (1) creating a link via os.link() to the @@ -1764,7 +1765,7 @@ def write_metadata_file(metadata, filename, version_number, consistent_snapshot) else: logger.debug('Not creating a consistent snapshot for ' + repr(written_filename)) logger.debug('Saving ' + repr(written_filename)) - file_object.move(written_filename) + securesystemslib.util.persist_temp_file(file_object, written_filename) return written_filename diff --git a/tuf/repository_tool.py b/tuf/repository_tool.py index b7950731..ef20c19e 100755 --- a/tuf/repository_tool.py +++ b/tuf/repository_tool.py @@ -50,6 +50,7 @@ import securesystemslib.keys import securesystemslib.formats +import securesystemslib.util import iso8601 import six @@ -3175,13 +3176,13 @@ def append_signature(signature, metadata_filepath): signable['signatures'].append(signature) - file_object = securesystemslib.util.TempFile() + file_object = tempfile.TemporaryFile() written_metadata_content = json.dumps(signable, indent=1, separators=(',', ': '), sort_keys=True).encode('utf-8') file_object.write(written_metadata_content) - file_object.move(metadata_filepath) + securesystemslib.util.persist_temp_file(file_object, metadata_filepath) diff --git a/tuf/sig.py b/tuf/sig.py index 5a38a9ce..ae9bae15 100755 --- a/tuf/sig.py +++ b/tuf/sig.py @@ -157,7 +157,7 @@ def get_signature_status(signable, role=None, repository_name='default', # Extract the relevant fields from 'signable' that will allow us to identify # the different classes of keys (i.e., good_sigs, bad_sigs, etc.). - signed = signable['signed'] + signed = securesystemslib.formats.encode_canonical(signable['signed']).encode('utf-8') signatures = signable['signatures'] # Iterate the signatures and enumerate the signature_status fields. @@ -389,7 +389,7 @@ def generate_rsa_signature(signed, rsakey_dict): # We need 'signed' in canonical JSON format to generate # the 'method' and 'sig' fields of the signature. - signed = securesystemslib.formats.encode_canonical(signed) + signed = securesystemslib.formats.encode_canonical(signed).encode('utf-8') # Generate the RSA signature. # Raises securesystemslib.exceptions.FormatError and TypeError.