From 4b5b536205920587ba7c4f146ce40ff3605d2c51 Mon Sep 17 00:00:00 2001
From: Benjamin Wenger <ben@elixxir.ioo>
Date: Sat, 8 Jan 2022 11:31:42 -0800
Subject: [PATCH] added preimage and notification for reception of group chat
 request

---
 api/authenticatedChannel.go    |  8 +++
 api/client.go                  | 10 ++++
 auth/callback.go               |  7 +++
 auth/confirm.go                |  7 +++
 bindings/notifications.go      |  1 +
 groupChat/sendRequests.go      | 12 ++++-
 groupChat/sendRequests_test.go | 94 +++++++++++++++++++++++++++++++++-
 interfaces/preimage/types.go   |  1 +
 storage/e2e/manager.go         |  6 +++
 9 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/api/authenticatedChannel.go b/api/authenticatedChannel.go
index 84fd75117..93446db2b 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 c70518706..2d455d90c 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 3151fdb43..471d415a8 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 2a8169d21..492e758a3 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 71db73728..7f393cf72 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 edcecc77f..b48335911 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 9c22c13fe..9f2b9c19f 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 0b87ef34c..bd6226e62 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 d8ec60e65..f6c000f78 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
-- 
GitLab