Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snapshot RSA Accumulator #1510

Closed
wants to merge 4 commits into from

Conversation

mnm678
Copy link
Contributor

@mnm678 mnm678 commented Jul 27, 2021

This is an early PoC

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]>
This is missing test data for the client

Signed-off-by: Marina Moore <[email protected]>
Copy link

@znewman01 znewman01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey! Sorry for the long lag on this.

I'm a thorough (AKA annoying 😄) code reviewer so feel free to ignore most of what I said. The comments in repository_lib.py are probably the important ones.

If anything's confusing, feel free to ask for clarification or we can set up a time to (video) call about it.

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_rsa_acc(test_nodes)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what's going on here -- above, there's a whole build/write/check files/check for specific value cycle, whereas here you just seem to be verifying that it doesn't crash?

snapshot_info = repository_updater.verify_rsa_acc_proof('role1')
self.assertEqual(snapshot_info['version'], 1)

# verify RSA accumulator with invalid role

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would like to also see a test for verifying an existing role against an invalid accumulator

if 'rsa_acc' not in self.metadata['current']['timestamp']:
# If an RSA Accumulator is defined, do not update snapshot metadata. Instead,
# we will download the relevant proof files later when downloading
# a target.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Merkle stuff isn't merged yet, right? You'd have to do the same thing there too.

Which is actually making me think there's room for abstraction here: one interface for "full manifest"/"rsa"/"merkle" so that not every user of the metadata has to interact with something called "rsa"

@@ -1616,6 +1620,206 @@ def _get_metadata_file(self, metadata_role, remote_filename,



def signable_verification(self, metadata_role, file_object, expected_version):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use a doc comment.

Also, naming nitpick: I tend to like all functions/methods to be verbs, so it's clearer what they do (e.g., "make_signable_verification" over "signable_verification" but even better "attest", "prove", etc. (if those are accurate))

@@ -1616,6 +1620,206 @@ def _get_metadata_file(self, metadata_role, remote_filename,



def signable_verification(self, metadata_role, file_object, expected_version):
# Verify 'file_object' according to the callable function.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What callable function?




def _build_rsa_acc(fileinfodict):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're eventually going to want to separate out:

  • initial build
  • update
  • removal (possibly)

leaves = []
primes = []
acc_exp = 1
for name, contents in sorted(fileinfodict.items()):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a preference for splitting all format-specific operations from all number-theoretic operations, which makes testing/understanding a lot easier.

So maybe a method like build(values) which takes a list of things to be hashed?

json_contents = securesystemslib.formats.encode_canonical(contents)
prime = hash_to_prime(json_contents)
primes.append(prime)
acc_exp = acc_exp * prime

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a hidden O(n^2) algorithm: acc_exp is O(n) in each iteration!

I think there's ways to do this O(n lg n) but need to think about it/dredge them up.

Best trick (O(n)) is to reduce acc_exp mod the order of the group---but that only works if you know the group order (which means knowing the RSA factors---we can think about whether that works in our setting. e.g., if you sign manifests we're kinda implicitly trusting you -- except then we lose a little bit of auditability because you can forge proofs if you know the RSA factors. we should discuss).

class acc_contents(object):
contents = None
name = None
proof = None

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this so we can hold precomputed proofs for each element?

cont = acc_contents(name, contents)
leaves.append(cont)

json_contents = securesystemslib.formats.encode_canonical(contents)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above, you say acc_contents needs name, but here we're encoding without name!

Signed-off-by: Marina Moore <[email protected]>
@lukpueh
Copy link
Member

lukpueh commented Feb 17, 2022

Ping @mnm678, same questions as in #1113 (comment).

@mnm678
Copy link
Contributor Author

mnm678 commented Feb 17, 2022

Closing in favor of writing this on top of the new Metadata api.

@mnm678 mnm678 closed this Feb 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants