-
Notifications
You must be signed in to change notification settings - Fork 30
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
Vrf integration #19
Vrf integration #19
Conversation
@@ -81,7 +83,8 @@ func (m *MerkleTree) Get(key string) (MerkleNode, []ProofNode) { | |||
} | |||
|
|||
func (m *MerkleTree) Set(key string, value []byte) error { | |||
index := computePrivateIndex(key) | |||
vrfPriv := m.policies.vrfPrivate() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be vrfPrivKey
for consistency?
There were quite some changes on master hence the merge conflicts. I wonder if it wasn't actually possible to remove the need of the actual Hope I didn't mix up things here (and sorry for so many questions). |
In our original design, we were more concerned with protecting a user's privacy against other users, and less with also protecting the user's privacy against the server. Maybe this is a bad assumption in practice. Another reason we left the actual usernames in the userLeafNodes is to allow the server to change |
I will add that you're definitely right about the actual usernames not being necessary to support lookups and auth path verifications. But I think supporting |
Thanks @masomel! OK, makes sense. So to keep it that way we need to either
and the Get signature to
I think 3) is the best option. |
It is exactly what I was thinking! I think it makes sense to go with option 3), and |
@liamsi ce91df5 looks good to me! |
} | ||
|
||
func (pad *PAD) LookupInEpoch(key string, epoch uint64) (*AuthenticationPath, error) { | ||
str := pad.GetSTR(epoch) | ||
if str == nil { | ||
return nil, ErrorSTRNotFound | ||
} | ||
ap := str.tree.Get(key) | ||
lookupIndex := pad.computePrivateIndex(key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look like it's using the right private key. If possible, we should add a test for this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean. Maybe the key
variable name is a little misleading here? The (private-)key which is used to compute the priv. is this one: https://github.com/coniks-sys/libmerkleprefixtree-go/pull/19/files#diff-9c53128bbf22cd8275aacdbf0ae82035R18
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look at the implementation of computePrivateIndex
,
vrfPivKey := pad.currentSTR.policies.vrfPrivate()
meaning that it gets the private key from the current epoch.
But this is a lookup in a specific epoch (the str := pad.GetSTR(epoch)
)
So, it seems like it needs to be,
str.policies.vrfPrivate()
And I'm assuming that the private key change in the policy means we need to recompute all the indices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I see. You're right. Thanks for the clarification! Will fix that (and add a test).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I'm assuming that the private key change in the policy means we need to recompute all the indices.
Will dig into that tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I'm assuming that the private key change in the policy means we need to recompute all the indices.
Yes. This would be a good feature to expose to the developer as this also has the nice side-effect of re-randomizing the order of leaves in the tree (as discussed in #19 (comment)).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But this is a lookup in a specific epoch (the str := pad.GetSTR(epoch))
So, it seems like it needs to be, str.policies.vrfPrivate()
I think it makes sense to make computePrivateIndex
a method of STR
, thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense.
The approach here looks good. Just a few comments to address. |
TODOs (for myself)
|
I agree with all your comments! |
OK. I'll merge your branch and do the changes. |
@@ -114,8 +114,9 @@ func (pad *PAD) GetSTR(epoch uint64) *SignedTreeRoot { | |||
func (pad *PAD) TB(key string, value []byte) (*TemporaryBinding, error) { | |||
//FIXME: compute private index twice | |||
//it would be refactored after merging VRF integration branch | |||
index, _ := pad.computePrivateIndex(key) | |||
tb := pad.currentSTR.sig | |||
cStr := pad.currentSTR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Help me think this through, because this looks problematic.
Currently, when you call pad.Update(policies)
it generates the next STR as if the passed in policies
were the ones being used. But, if the private key changes, all these temporary bindings being handed out no longer have the right index.
I think PAD
needs a policies
field reflecting the current policies in place. currentSTR
may be badly named in that it is really just the most recently signed tree root, whereas pad.tree
is what's current and will be reflected in the next STR. Then, when you call Update(policies)
, it should generate the STR with the policies that were actually used (pad.policies
), and then swap the pad.policies
with the ones being passed in to be used going forward. It can then reshuffle the pad.tree
if the private key changed.
Hopefully that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, when you call pad.Update(policies) it generates the next STR as if the passed in policies were the ones being used. But, if the private key changes, all these temporary bindings being handed out no longer have the right index.
Makes sense. Will change that.
I think PAD needs a policies field reflecting the current policies in place. currentSTR may
OK, I have to think about that (hopefully after the talks/program finished). But on first sight it makes sense to add a policies field to PAD
.
currentSTR may be badly named in that it is really just the most recently signed tree root, whereas pad.tree is what's current and will be reflected in the next STR.
What do you think about renaming it to lastSTR
or latestSTR
?
Then, when you call Update(policies), it should generate the STR with the policies that were actually used (pad.policies), and then swap the pad.policies with the ones being passed in to be used going forward. It can then reshuffle the pad.tree if the private key changed.
Hopefully that makes sense.
Sounds reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally makes sense, it's a very good point. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about lastSTR or latestSTR?
latestSTR
sounds ok. While we're at it, maybe do s/generateNextSTR/SignTreeRoot/
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think PAD needs a policies field reflecting the current policies in place. currentSTR may
OK, I have to think about that (hopefully after the talks/program finished). But on first sight it makes sense to add a policies field to PAD.
Didn't have the time to think it through (yet). But do we still need the policies field in STR
then (for serializing, or sth else)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But do we still need the policies field in STR then (for serializing, or sth else)?
I think we do. Anything that gets signed needs to remain so that it can be verified later. But also, in this case, when you do the lookup from a previous epoch, you still need to use the key from the old policy.
So, I should have mentioned, computePrivateIndex
should probably stay on the pad
but we'll need a computePrivateIndexInEpoch
as well. Or, something like that. You get the idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, in this case, when you do the lookup from a previous epoch, you still need to use the key from the old policy.
I think this is done in e82f666f1930a475550a8c3eb00194932c003a19
Then, when you call Update(policies), it should generate the STR with the policies that were actually used (pad.policies), and then swap the pad.policies with the ones being passed in to be used going forward. It can then reshuffle the pad.tree if the private key changed.
Besides the reshuffling part this is also done in the latest commit. Please review. I have some questions regarding the design of the reshuffling (below).
Currently, the reshuffling of the To make this work @arlolra suggested a re-computation of the indices (#19 (comment)). As far as I understand it the only way to re-shuffle the pad.tree (from outside the package @c633 @arlolra @masomel Any thoughts on which is the better/safer approach? |
I thought a little about my above question: I think exposing the 'key's from the |
It seems I didn't understand your idea completely. Since the tree and pad are in the same package (
I prefer this way. |
I thought a little about this implementation. There are some concerns here:
|
Could you add a method of MerkleTree,
Then you could,
|
if str == nil { | ||
return ErrorSTRNotFound | ||
} | ||
index, _ := pad.computePrivateIndexInEpoch(key, str.epoch) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to use pad.policies
, not the latestSTR
.
There are two distinct times that we need to compute a private index,
- When setting a key. This happens before a root is signed, and therefore cannot get the key from an STR.
- When looking up a key. This always happens from a STR, and therefore uses the key from the policy in the STR.
So, it's fine to make computePrivateIndex
a method of STR, but then you'll also need another method to handle the Set case.
Or, you can make it a method of PAD but one of the arguments needs to be a key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again for your feedback! Changed in ad750fa
You are absolutely right. I actually confused the packages while thinking about it ... Thanks for your feedback and sorry for the noise!
OK, traversing the tree (as @arlolra suggested in #19 (comment)) maybe more efficient and it certainly makes storing the keys twice obsolete. I think, I'll go this way now. |
@c633 @masomel depending on the protocol and its complexity this would be a nice (optional?) addition
I think the above should be a separate issue. Regarding the recomputation of the tree/indices I think it's fine to keep it in this issue (as it is definitely related to the vrf-integration, also I feel all open questions are resolved now). On the other hand we thought of this as changing very few lines only, yo if you want to keep it in small separate issues I wouldn't vote against it. |
@@ -41,29 +45,42 @@ func NewPAD(policies Policies, key crypto.SigningKey, len int64) (*PAD, error) { | |||
} | |||
|
|||
// if policies is nil, the previous policies will be used | |||
func (pad *PAD) generateNextSTR(policies Policies, m *MerkleTree, epoch uint64) { | |||
func (pad *PAD) signTreeRoot(policies Policies, m *MerkleTree, epoch uint64) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The policies
argument here is unnecessary, since it's always going to be pad.policies
, which the pad
has access to.
I think this ready for another review. Sorry, that this took longer than expected... And thanks everyone for all the valuable feedback so far. |
@@ -31,6 +34,7 @@ func NewPAD(policies Policies, key crypto.SigningKey, len int64) (*PAD, error) { | |||
pad := new(PAD) | |||
pad.key = key | |||
pad.tree, err = NewMerkleTree() | |||
pad.policies = policies | |||
if err != nil { | |||
return nil, err | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can just do pad.updateInternal(nil, 0)
on L43 now
Never mind. I'm okay with this. |
visitULNsInternal(m.root, callBack) | ||
} | ||
|
||
func visitULNsInternal(nodePtr interface{}, callBack func(*userLeafNode)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change nodePtr interface{}
into nodePtr MerkleNode
. I also want to change L43 and L117, too. So if it makes sense to you ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense! I'll change the other lines for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, thanks!
Thanks! It looks great. |
* Should resolve #14
Seems fine with me.
Our idea was that users seeking to keep their key(s) or other data private from the server as well as other users would encrypt the This is a protocol we sketched out as part of a small follow-on project, and we never tested it out or anything, so I'm open to improvements/suggestions. Either way, I don't think that adding this protocol as part of this PR makes sense right now. |
Nice work @liamsi |
Use coname's vrf implementation to compute the private index
t.Error
in combination withreturn
witht.Fatal