Skip to content

Commit

Permalink
Add initial poc for RSA Accumulator snapshots: repo side
Browse files Browse the repository at this point in the history
This commit uses a custom python implementation of Miller-Rabin
that we will want to replace with a well-maintained library.

It does not include efficient updates to the RSA Accumulator

Signed-off-by: Marina Moore <[email protected]>
  • Loading branch information
mnm678 committed Jul 27, 2021
1 parent 2045e6a commit 1e0d3f1
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 211 deletions.
42 changes: 8 additions & 34 deletions tests/test_repository_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,62 +467,36 @@ def test_generate_targets_metadata(self):
False, use_existing_fileinfo=True)


def test_build_merkle_tree(self):
def test_build_rsa_acc(self):
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
storage_backend = securesystemslib.storage.FilesystemBackend()
version = 1

# Test building the tree one node at a time to verify the hashes
# Test an rsa accumulator with a few nodes to verify the output

test_nodes = {}
test_nodes['file1'] = tuf.formats.make_metadata_fileinfo(5, None, None)

root_1, leaves = repo_lib._build_merkle_tree(test_nodes)
repo_lib._write_merkle_paths(root_1, leaves, storage_backend,
temporary_directory, version)

file_path = os.path.join(temporary_directory, 'file1-snapshot.json')
self.assertTrue(os.path.exists(file_path))

file_path = os.path.join(temporary_directory, '1.file1-snapshot.json')
self.assertTrue(os.path.exists(file_path))

test_nodes['file2'] = tuf.formats.make_metadata_fileinfo(5, None, None)
root_2, leaves = repo_lib._build_merkle_tree(test_nodes)

self.assertEqual(root_2.left.digest, root_1.digest)

test_nodes['file3'] = tuf.formats.make_metadata_fileinfo(5, None, None)
test_nodes['file4'] = tuf.formats.make_metadata_fileinfo(5, None, None)

root_3, leaves = repo_lib._build_merkle_tree(test_nodes)

self.assertEqual(root_3.left.digest, root_2.digest)

test_nodes['file5'] = tuf.formats.make_metadata_fileinfo(5, None, None)

root_4, leaves = repo_lib._build_merkle_tree(test_nodes)

repo_lib._write_merkle_paths(root_4, leaves, storage_backend,
temporary_directory, version + 1)

self.assertEqual(root_4.left.digest, root_3.digest)
root_1, leaves = repo_lib._build_rsa_acc(test_nodes)
repo_lib._write_rsa_leaves(root_1, leaves, storage_backend,
temporary_directory, version)

# Ensure that the paths are written to the directory
file_path = os.path.join(temporary_directory, 'file1-snapshot.json')
self.assertTrue(os.path.exists(file_path))

file_path = os.path.join(temporary_directory, '2.file1-snapshot.json')
file_path = os.path.join(temporary_directory, '1.file1-snapshot.json')
self.assertTrue(os.path.exists(file_path))

# repo_lib.print_merkle_tree(root_4)
self.assertEqual(root_1, 5)

test_nodes = {}
test_nodes['targets'] = tuf.formats.make_metadata_fileinfo(1, None, None)
test_nodes['role1'] = tuf.formats.make_metadata_fileinfo(1, None, None)
test_nodes['role2'] = tuf.formats.make_metadata_fileinfo(1, None, None)

root, leaves = repo_lib._build_merkle_tree(test_nodes)
root, leaves = repo_lib._build_rsa_acc(test_nodes)



Expand Down
12 changes: 6 additions & 6 deletions tests/test_repository_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,20 +255,20 @@ def test_writeall(self):
# Verify that status() does not raise an exception.
repository.status()

# Test writeall with generating a snapshot merkle tree
# Test writeall with generating a snapshot RSA accumulator
repository.mark_dirty(['role1', 'targets', 'root', 'snapshot', 'timestamp'])
repository.writeall(snapshot_merkle=True)
repository.writeall(rsa_acc=True)

# Were the merkle snapshots written?
# Were the RSA proof snapshots written?
targets_snapshot_filepath = os.path.join(metadata_directory,
'targets-snapshot.json')
targets_snapshot = securesystemslib.util.load_json_file(targets_snapshot_filepath)
tuf.formats.SNAPSHOT_MERKLE_SCHEMA.check_match(targets_snapshot)
tuf.formats.SNAPSHOT_RSA_ACC_SCHEMA.check_match(targets_snapshot)

# Does timestamp have the root hash?
timestamp_filepath = os.path.join(metadata_directory, 'timestamp.json')
timestamp = securesystemslib.util.load_json_file(timestamp_filepath)
timestamp['signed']['merkle_root']
timestamp['signed']['rsa_acc']

# Verify that status() does not raise
# 'tuf.exceptions.InsufficientKeysError' if a top-level role
Expand Down Expand Up @@ -512,7 +512,7 @@ def test_get_filepaths_in_directory(self):
expected_files = []
for filepath in ['1.root.json', 'root.json', 'targets.json',
'snapshot.json', 'timestamp.json', 'role1.json', 'role2.json',
'targets-snapshot.json', 'timestamp-merkle.json',
'targets-snapshot.json', 'timestamp-rsa.json',
'role1-snapshot.json', 'role2-snapshot.json']:
expected_files.append(os.path.abspath(os.path.join(
'repository_data', 'repository', 'metadata', filepath)))
Expand Down
7 changes: 3 additions & 4 deletions tuf/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,10 @@
targets = FILEDICT_SCHEMA,
delegations = SCHEMA.Optional(DELEGATIONS_SCHEMA))

SNAPSHOT_MERKLE_SCHEMA = SCHEMA.Object(
SNAPSHOT_RSA_ACC_SCHEMA = SCHEMA.Object(
leaf_contents = SCHEMA.OneOf([VERSIONINFO_SCHEMA,
METADATA_FILEINFO_SCHEMA]),
merkle_path = SCHEMA.DictOf(key_schema=SCHEMA.AnyString(), value_schema=HASH_SCHEMA),
path_directions = SCHEMA.DictOf(key_schema=SCHEMA.AnyString(), value_schema=SCHEMA.Integer()))
rsa_acc_proof = SCHEMA.AnyString())

# Snapshot role: indicates the latest versions of all metadata (except
# timestamp).
Expand All @@ -390,7 +389,7 @@
version = METADATAVERSION_SCHEMA,
expires = securesystemslib.formats.ISO8601_DATETIME_SCHEMA,
meta = FILEINFODICT_SCHEMA,
merkle_root = SCHEMA.Optional(HASH_SCHEMA))
rsa_acc = SCHEMA.Optional(HASH_SCHEMA))


# project.cfg file: stores information about the project in a json dictionary
Expand Down
Loading

0 comments on commit 1e0d3f1

Please sign in to comment.