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

[WIP] Registration should happen in epoch #189

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions coniksclient/cli/internal/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ func register(cc *client.ConsistencyChecks, conf *coniksclient.Config, name stri
switch response.Error {
case protocol.ReqNameExisted:
return (`Are you trying to update your binding? Unfortunately, KeyChange isn't supported yet.`)
case protocol.ErrOutdatedEpoch:
// FIXME
return (`You need to fetch the latest STR first. Unfortunately, we haven't implemented fetching STR functionality yet.`)
case protocol.ReqSuccess:
recvKey, err := response.GetKey()
if err != nil {
Expand Down
14 changes: 8 additions & 6 deletions coniksserver/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func TestUpdateDirectory(t *testing.T) {
server, teardown := startServer(t, 1, true, "")
defer teardown()
str0 := server.dir.LatestSTR()
rs := createMultiRegistrationRequests(10)
rs := createMultiRegistrationRequests(10, str0.Epoch)
for i := range rs {
req := server.handleOps(rs[i])
if req.Error != protocol.ReqSuccess {
Expand All @@ -217,12 +217,13 @@ func TestUpdateDirectory(t *testing.T) {
}
}

func createMultiRegistrationRequests(N uint64) []*protocol.Request {
func createMultiRegistrationRequests(N, epoch uint64) []*protocol.Request {
var rs []*protocol.Request
for i := uint64(0); i < N; i++ {
r := &protocol.Request{
Type: protocol.RegistrationType,
Request: &protocol.RegistrationRequest{
Epoch: epoch,
Username: "user" + string(i),
Key: []byte("key" + string(i)),
AllowPublicLookup: true,
Expand All @@ -237,8 +238,8 @@ func createMultiRegistrationRequests(N uint64) []*protocol.Request {
func TestRegisterDuplicateUserInOneEpoch(t *testing.T) {
server, teardown := startServer(t, 60, true, "")
defer teardown()
r0 := createMultiRegistrationRequests(1)[0]
r1 := createMultiRegistrationRequests(1)[0]
r0 := createMultiRegistrationRequests(1, server.dir.LatestSTR().Epoch)[0]
r1 := createMultiRegistrationRequests(1, server.dir.LatestSTR().Epoch)[0]
rev := server.handleOps(r0)
if rev.Error != protocol.ReqSuccess {
t.Fatal("Error while submitting registration request")
Expand All @@ -262,14 +263,15 @@ func TestRegisterDuplicateUserInOneEpoch(t *testing.T) {
func TestRegisterDuplicateUserInDifferentEpoches(t *testing.T) {
server, teardown := startServer(t, 1, true, "")
defer teardown()
r0 := createMultiRegistrationRequests(1)[0]
r0 := createMultiRegistrationRequests(1, server.dir.LatestSTR().Epoch)[0]
rev := server.handleOps(r0)
if rev.Error != protocol.ReqSuccess {
t.Fatal("Error while submitting registration request")
}
timer := time.NewTimer(2 * time.Second)
<-timer.C
rev = server.handleOps(r0)
r1 := createMultiRegistrationRequests(1, server.dir.LatestSTR().Epoch)[0]
rev = server.handleOps(r1)
response, ok := rev.DirectoryResponse.(*protocol.DirectoryProof)
if !ok {
t.Fatal("Expect a directory proof response")
Expand Down
16 changes: 16 additions & 0 deletions protocol/client/consistencychecks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var (
func registerAndVerify(d *directory.ConiksDirectory, cc *ConsistencyChecks,
name string, key []byte) error {
request := &protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: name,
Key: key,
}
Expand Down Expand Up @@ -103,6 +104,21 @@ func TestVerifyRegistrationResponseWithTB(t *testing.T) {
}
}

func TestRegistrationOutdatedEpoch(t *testing.T) {
d, pk := directory.NewTestDirectory(t, true)
cc := New(d.LatestSTR(), true, pk)
request := &protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: alice,
Key: key,
}
d.Update()
res := d.Register(request)
if err := cc.HandleResponse(protocol.RegistrationType, res, alice, key); err != protocol.ErrOutdatedEpoch {
t.Error(err)
}
}

func TestVerifyFullfilledPromise(t *testing.T) {
d, pk := directory.NewTestDirectory(t, true)

Expand Down
8 changes: 7 additions & 1 deletion protocol/directory/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,16 @@ func (d *ConiksDirectory) NewTB(name string, key []byte) *protocol.TemporaryBind
// a message.NewErrorResponse(ErrDirectory).
func (d *ConiksDirectory) Register(req *protocol.RegistrationRequest) *protocol.Response {
// make sure the request is well-formed
if len(req.Username) <= 0 || len(req.Key) <= 0 {
if len(req.Username) <= 0 || len(req.Key) <= 0 ||
req.Epoch > d.LatestSTR().Epoch {
return protocol.NewErrorResponse(protocol.ErrMalformedMessage)
}

// check whether this registration request happens in epoch
if req.Epoch < d.LatestSTR().Epoch {
Copy link
Member

Choose a reason for hiding this comment

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

Does the client really gain anything if we depend on the server to enforce the "in-epoch" property?

return protocol.NewErrorResponse(protocol.ErrOutdatedEpoch)
}

// check whether the name already exists
// in the directory before we register
ap, err := d.pad.Lookup(req.Username)
Expand Down
22 changes: 22 additions & 0 deletions protocol/directory/directory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func TestRegisterWithTB(t *testing.T) {
d, _ := NewTestDirectory(t, true)

res := d.Register(&protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: "alice",
Key: []byte("key")})
df := res.DirectoryResponse.(*protocol.DirectoryProof)
Expand All @@ -37,6 +38,7 @@ func TestRegisterWithTB(t *testing.T) {
func TestRegisterExistedUserWithTB(t *testing.T) {
d, _ := NewTestDirectory(t, true)
res := d.Register(&protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: "alice",
Key: []byte("key")})
if res.Error != protocol.ReqSuccess {
Expand All @@ -47,6 +49,7 @@ func TestRegisterExistedUserWithTB(t *testing.T) {
// along with a TB of registering user
// and error ReqNameExisted
res = d.Register(&protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: "alice",
Key: []byte("key")})
df := res.DirectoryResponse.(*protocol.DirectoryProof)
Expand All @@ -65,6 +68,7 @@ func TestRegisterExistedUserWithTB(t *testing.T) {
// expect return a proof of inclusion
// and error ReqNameExisted
res = d.Register(&protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: "alice",
Key: []byte("key")})
df = res.DirectoryResponse.(*protocol.DirectoryProof)
Expand All @@ -79,6 +83,21 @@ func TestRegisterExistedUserWithTB(t *testing.T) {
}
}

func TestRegisterInOutdatedEpoch(t *testing.T) {
// expect return a proof of absence
// along with a TB of registering user
d, _ := NewTestDirectory(t, true)
d.Update()

res := d.Register(&protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch - 1,
Username: "alice",
Key: []byte("key")})
if res.Error != protocol.ErrOutdatedEpoch {
t.Fatal("Expect ", protocol.ErrOutdatedEpoch, "got", res.Error)
}
}

func TestNewDirectoryPanicWithoutTB(t *testing.T) {
// workaround for #110
defer func() {
Expand All @@ -93,6 +112,7 @@ func TestNewDirectoryPanicWithoutTB(t *testing.T) {
func TestKeyLookupWithTB(t *testing.T) {
d, _ := NewTestDirectory(t, true)
res := d.Register(&protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: "alice",
Key: []byte("key")})
tb := res.DirectoryResponse.(*protocol.DirectoryProof).TB
Expand Down Expand Up @@ -134,6 +154,7 @@ func TestDirectoryMonitoring(t *testing.T) {

d, _ := NewTestDirectory(t, true)
d.Register(&protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: "alice",
Key: []byte("key")})

Expand Down Expand Up @@ -201,6 +222,7 @@ func TestDirectoryKeyLookupInEpoch(t *testing.T) {
}

d.Register(&protocol.RegistrationRequest{
Epoch: d.LatestSTR().Epoch,
Username: "alice",
Key: []byte("key")})
for i := 0; i < N; i++ {
Expand Down
3 changes: 3 additions & 0 deletions protocol/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
ErrDirectory
ErrAuditLog
ErrMalformedMessage
ErrOutdatedEpoch
)

// These codes indicate the result
Expand All @@ -49,6 +50,7 @@ var Errors = map[error]bool{
ErrMalformedMessage: true,
ErrDirectory: true,
ErrAuditLog: true,
ErrOutdatedEpoch: true,
}

var (
Expand All @@ -60,6 +62,7 @@ var (
ErrMalformedMessage: "[coniks] Malformed message",
ErrDirectory: "[coniks] Directory error",
ErrAuditLog: "[coniks] Audit log error",
ErrOutdatedEpoch: "[coniks] The requested epoch is outdated",

CheckBadSignature: "[coniks] Directory's signature on STR or TB is invalid",
CheckBadVRFProof: "[coniks] Returned index is not valid for the given name",
Expand Down
1 change: 1 addition & 0 deletions protocol/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Request struct {
// The response to a successful request is a DirectoryProof with a TB for
// the requested username and public key.
type RegistrationRequest struct {
Epoch uint64
Copy link
Member

Choose a reason for hiding this comment

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

What epoch is the client supposed to use here? Is the assumption that the client has fetched the latest STR before it even registers the name for the first time?

Username string
Key []byte
AllowUnsignedKeychange bool `json:",omitempty"`
Expand Down