diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go index 84fd751178f710482c49c24df38449ef731f0779..93446db2b9bee15a5755f49d62ce42bcedf15794 100644 --- a/api/authenticatedChannel.go +++ b/api/authenticatedChannel.go @@ -158,6 +158,14 @@ func (c *Client) MakePrecannedAuthenticatedChannel(precannedID uint) (contact.Co Source: precan.ID[:], }, me) + // group request + c.storage.GetEdge().Add(edge.Preimage{ + Data: sessionPartner.GetGroupRequestPreimage(), + Type: preimage.GroupRq, + Source: precan.ID[:], + }, me) + + return precan, err } diff --git a/api/client.go b/api/client.go index c705187068226c528ac1ac24f1dfd28c49f1eb8f..2d455d90cc2ea0d972dc82eee94f7e8a2773f18d 100644 --- a/api/client.go +++ b/api/client.go @@ -696,6 +696,7 @@ func (c *Client) DeleteContact(partnerId *id.ID) error { e2ePreimage := partner.GetE2EPreimage() rekeyPreimage := partner.GetSilentPreimage() fileTransferPreimage := partner.GetFileTransferPreimage() + groupRequestPreimage := partner.GetGroupRequestPreimage() //delete the partner if err = c.storage.E2e().DeletePartner(partnerId); err != nil { @@ -729,6 +730,15 @@ func (c *Client) DeleteContact(partnerId *id.ID) error { "from %s on contact deletion: %+v", partnerId, err) } + if err = c.storage.GetEdge().Remove(edge.Preimage{ + Data: groupRequestPreimage, + Type: preimage.GroupRq, + Source: partnerId[:], + }, c.storage.GetUser().ReceptionID); err != nil { + jww.WARN.Printf("Failed delete the preimage for group request "+ + "from %s on contact deletion: %+v", partnerId, err) + } + if err = c.storage.Auth().Delete(partnerId); err != nil { return err } diff --git a/auth/callback.go b/auth/callback.go index 3151fdb43de00b988d3356ea1833c9979c83cfba..471d415a8e4147e6718e926553619cd2908403e8 100644 --- a/auth/callback.go +++ b/auth/callback.go @@ -434,6 +434,13 @@ func (m *Manager) doConfirm(sr *auth.SentRequest, grp *cyclic.Group, Source: sr.GetPartner()[:], }, me) + //group Request + m.storage.GetEdge().Add(edge.Preimage{ + Data: sessionPartner.GetGroupRequestPreimage(), + Type: preimage.GroupRq, + Source: sr.GetPartner()[:], + }, me) + // delete the in progress negotiation // this undoes the request lock if err := m.storage.Auth().Delete(sr.GetPartner()); err != nil { diff --git a/auth/confirm.go b/auth/confirm.go index 2a8169d21eb5be5f80ccbe5519aeb6a5a1e0d783..492e758a38c55fb0cda1aed0feedcb8fcce66f73 100644 --- a/auth/confirm.go +++ b/auth/confirm.go @@ -147,6 +147,13 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, Source: partner.ID[:], }, me) + //group Request + storage.GetEdge().Add(edge.Preimage{ + Data: sessionPartner.GetGroupRequestPreimage(), + Type: preimage.GroupRq, + Source: partner.ID[:], + }, me) + // delete the in progress negotiation // this unlocks the request lock //fixme - do these deletes at a later date diff --git a/bindings/notifications.go b/bindings/notifications.go index 71db73728f59e1fcd4d382fe79de310eddf860d4..7f393cf7271c253cf5e07771f9f570d89b69a3de 100644 --- a/bindings/notifications.go +++ b/bindings/notifications.go @@ -59,6 +59,7 @@ func (mnfmr *ManyNotificationForMeReport) Len() int { // "e2e" sender user ID reception of an E2E message // "group" group ID reception of a group chat message // "endFT" sender user ID Last message sent confirming end of file transfer +// "groupRQ" sender user ID Request from sender to join a group chat func NotificationsForMe(notifCSV, preimages string) (*ManyNotificationForMeReport, error) { //handle deserialization of preimages var preimageList []edge.Preimage diff --git a/groupChat/sendRequests.go b/groupChat/sendRequests.go index edcecc77f1b5516a9ed75d9481738210374b88e4..b48335911b5ff2d193a070dc62455b5378f769fb 100644 --- a/groupChat/sendRequests.go +++ b/groupChat/sendRequests.go @@ -117,7 +117,17 @@ func (m Manager) sendRequest(memberID *id.ID, request []byte) ([]id.Round, error MessageType: message.GroupCreationRequest, } - rounds, _, _, err := m.net.SendE2E(sendMsg, params.GetDefaultE2E(), nil) + + recipent, err := m.store.E2e().GetPartner(memberID) + if err!=nil{ + return nil, errors.WithMessagef(err,"Failed to send request to %s " + + "because e2e relationship could not be found", memberID) + } + + p := params.GetDefaultE2E() + p.IdentityPreimage = recipent.GetGroupRequestPreimage() + + rounds, _, _, err := m.net.SendE2E(sendMsg, p, nil) if err != nil { return nil, errors.Errorf(sendE2eErr, memberID, err) } diff --git a/groupChat/sendRequests_test.go b/groupChat/sendRequests_test.go index 9c22c13fed92f6b986a6f71db63d6f9aea3a230a..9f2b9c19f2eb2c65dd51d3f66e3dc512cfe991b3 100644 --- a/groupChat/sendRequests_test.go +++ b/groupChat/sendRequests_test.go @@ -9,8 +9,13 @@ package groupChat import ( "fmt" + "github.com/cloudflare/circl/dh/sidh" "github.com/golang/protobuf/proto" "gitlab.com/elixxir/client/interfaces/message" + "gitlab.com/elixxir/client/interfaces/params" + util "gitlab.com/elixxir/client/storage/utility" + "gitlab.com/elixxir/crypto/diffieHellman" + "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" "math/rand" "reflect" @@ -33,11 +38,29 @@ func TestManager_ResendRequest(t *testing.T) { Created: g.Created.UnixNano(), } + for i := range g.Members{ + grp := m.store.E2e().GetGroup() + dhKey := grp.NewInt(int64(i + 42)) + pubKey := diffieHellman.GeneratePublicKey(dhKey, grp) + p := params.GetDefaultE2ESessionParams() + rng := csprng.NewSystemRNG() + _, mySidhPriv := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhA, rng) + theirSidhPub, _ := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhB, rng) + err := m.store.E2e().AddPartner(g.Members[i].ID, pubKey, dhKey, + mySidhPriv, theirSidhPub, p, p) + if err != nil { + t.Errorf("Failed to add partner #%d %s: %+v", i, g.Members[i].ID, err) + } + } + _, status, err := m.ResendRequest(g.ID) if err != nil { t.Errorf("ResendRequest() returned an error: %+v", err) } + if status != AllSent { t.Errorf("ResendRequest() failed to return the expected status."+ "\nexpected: %s\nreceived: %s", AllSent, status) @@ -112,6 +135,23 @@ func TestManager_sendRequests(t *testing.T) { Created: g.Created.UnixNano(), } + for i := range g.Members{ + grp := m.store.E2e().GetGroup() + dhKey := grp.NewInt(int64(i + 42)) + pubKey := diffieHellman.GeneratePublicKey(dhKey, grp) + p := params.GetDefaultE2ESessionParams() + rng := csprng.NewSystemRNG() + _, mySidhPriv := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhA, rng) + theirSidhPub, _ := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhB, rng) + err := m.store.E2e().AddPartner(g.Members[i].ID, pubKey, dhKey, + mySidhPriv, theirSidhPub, p, p) + if err != nil { + t.Errorf("Failed to add partner #%d %s: %+v", i, g.Members[i].ID, err) + } + } + _, status, err := m.sendRequests(g) if err != nil { t.Errorf("sendRequests() returned an error: %+v", err) @@ -195,6 +235,23 @@ func TestManager_sendRequests_SendPartialSent(t *testing.T) { expectedErr := fmt.Sprintf(sendRequestPartialErr, (len(g.Members)-1)/2, len(g.Members)-1, "") + for i := range g.Members{ + grp := m.store.E2e().GetGroup() + dhKey := grp.NewInt(int64(i + 42)) + pubKey := diffieHellman.GeneratePublicKey(dhKey, grp) + p := params.GetDefaultE2ESessionParams() + rng := csprng.NewSystemRNG() + _, mySidhPriv := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhA, rng) + theirSidhPub, _ := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhB, rng) + err := m.store.E2e().AddPartner(g.Members[i].ID, pubKey, dhKey, + mySidhPriv, theirSidhPub, p, p) + if err != nil { + t.Errorf("Failed to add partner #%d %s: %+v", i, g.Members[i].ID, err) + } + } + _, status, err := m.sendRequests(g) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("sendRequests() failed to return the expected error."+ @@ -217,6 +274,23 @@ func TestManager_sendRequest(t *testing.T) { prng := rand.New(rand.NewSource(42)) m, g := newTestManagerWithStore(prng, 10, 0, nil, nil, t) + for i := range g.Members{ + grp := m.store.E2e().GetGroup() + dhKey := grp.NewInt(int64(i + 42)) + pubKey := diffieHellman.GeneratePublicKey(dhKey, grp) + p := params.GetDefaultE2ESessionParams() + rng := csprng.NewSystemRNG() + _, mySidhPriv := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhA, rng) + theirSidhPub, _ := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhB, rng) + err := m.store.E2e().AddPartner(g.Members[i].ID, pubKey, dhKey, + mySidhPriv, theirSidhPub, p, p) + if err != nil { + t.Errorf("Failed to add partner #%d %s: %+v", i, g.Members[i].ID, err) + } + } + expected := message.Send{ Recipient: g.Members[0].ID, Payload: []byte("request message"), @@ -241,7 +315,25 @@ func TestManager_sendRequest_SendE2eError(t *testing.T) { m, _ := newTestManagerWithStore(prng, 10, 1, nil, nil, t) expectedErr := strings.SplitN(sendE2eErr, "%", 2)[0] - _, err := m.sendRequest(id.NewIdFromString("memberID", id.User, t), nil) + recipientID := id.NewIdFromString("memberID", id.User, t) + + grp := m.store.E2e().GetGroup() + dhKey := grp.NewInt(int64(42)) + pubKey := diffieHellman.GeneratePublicKey(dhKey, grp) + p := params.GetDefaultE2ESessionParams() + rng := csprng.NewSystemRNG() + _, mySidhPriv := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhA, rng) + theirSidhPub, _ := util.GenerateSIDHKeyPair( + sidh.KeyVariantSidhB, rng) + err := m.store.E2e().AddPartner(recipientID, pubKey, dhKey, + mySidhPriv, theirSidhPub, p, p) + if err != nil { + t.Errorf("Failed to add partner %s: %+v", recipientID, err) + } + + + _, err = m.sendRequest(recipientID, nil) if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Errorf("sendRequest() failed to return the expected error."+ "\nexpected: %s\nreceived: %+v", expectedErr, err) diff --git a/interfaces/preimage/types.go b/interfaces/preimage/types.go index 0b87ef34c47bc1574a94813ebb77ebb0155a67d8..bd6226e623594561ef0338210af8824c1b789f27 100644 --- a/interfaces/preimage/types.go +++ b/interfaces/preimage/types.go @@ -8,4 +8,5 @@ const ( E2e = "e2e" Group = "group" EndFT = "endFT" + GroupRq = "groupRq" ) diff --git a/storage/e2e/manager.go b/storage/e2e/manager.go index d8ec60e65209a217e45bcc28d2387ce6eadd1d9d..f6c000f78ff002e3a3c82db143b8e783ca8a497e 100644 --- a/storage/e2e/manager.go +++ b/storage/e2e/manager.go @@ -292,3 +292,9 @@ func (m *Manager) GetSilentPreimage() []byte { func (m *Manager) GetFileTransferPreimage() []byte { return preimage.Generate(m.GetRelationshipFingerprintBytes(), preimage.EndFT) } + +// GetGroupRequestPreimage returns a hash of the unique +// fingerprint for group requests received from this user. +func (m *Manager) GetGroupRequestPreimage() []byte { + return preimage.Generate(m.GetRelationshipFingerprintBytes(), preimage.GroupRq) +} \ No newline at end of file