Browse Source

Fixing #118 - Adding an initial message to group setup

initial_message
Sarah Jamie Lewis 1 year ago
parent
commit
d37447f320
6 changed files with 73 additions and 41 deletions
  1. 21
    10
      model/group.go
  2. 8
    1
      model/profile.go
  3. 7
    1
      model/profile_test.go
  4. 7
    2
      peer/cwtch_peer.go
  5. 29
    27
      protocol/cwtch-profile.pb.go
  6. 1
    0
      protocol/cwtch-profile.proto

+ 21
- 10
model/group.go View File

@@ -16,15 +16,16 @@ import (
//Group defines and encapsulates Cwtch's conception of group chat. Which are sessions
// tied to a server under a given group key. Each group has a set of messages.
type Group struct {
GroupID string
SignedGroupID []byte
GroupKey [32]byte
GroupServer string
Timeline Timeline
Accepted bool
Owner string
IsCompromised bool
lock sync.Mutex
GroupID string
SignedGroupID []byte
GroupKey [32]byte
GroupServer string
Timeline Timeline
Accepted bool
Owner string
IsCompromised bool
InitialMessage []byte
lock sync.Mutex
}

// NewGroup initializes a new group associated with a given CwtchServer
@@ -58,18 +59,28 @@ func (g *Group) Compromised() {
g.IsCompromised = true
}

// GetInitialMessage returns the first message of the group, if one was sent with the invite.
func (g *Group) GetInitialMessage() []byte {
g.lock.Lock()
defer g.lock.Unlock()
return g.InitialMessage
}

// Invite generates a invitation that can be sent to a cwtch peer
func (g *Group) Invite() ([]byte, error) {
func (g *Group) Invite(initialMessage []byte) ([]byte, error) {

if g.SignedGroupID == nil {
return nil, errors.New("group isn't signed")
}

g.InitialMessage = initialMessage[:]

gci := &protocol.GroupChatInvite{
GroupName: g.GroupID,
GroupSharedKey: g.GroupKey[:],
ServerHost: g.GroupServer,
SignedGroupId: g.SignedGroupID[:],
InitialMessage: initialMessage[:],
}

cp := &protocol.CwtchPeerPacket{

+ 8
- 1
model/profile.go View File

@@ -199,11 +199,17 @@ func (p *Profile) SignMessage(message string) []byte {
//StartGroup when given a server, creates a new Group under this profile and returns the group id an a precomputed
// invite which can be sent on the wire.
func (p *Profile) StartGroup(server string) (groupID string, invite []byte, err error) {
return p.StartGroupWithMessage(server, []byte{})
}

//StartGroupWithMessage when given a server, and an initial message creates a new Group under this profile and returns the group id an a precomputed
// invite which can be sent on the wire.
func (p *Profile) StartGroupWithMessage(server string, initialMessage []byte) (groupID string, invite []byte, err error) {
group := NewGroup(server)
groupID = group.GroupID
signedGroupID := p.SignMessage(groupID + server)
group.SignGroup(signedGroupID)
invite, err = group.Invite()
invite, err = group.Invite(initialMessage)
p.lock.Lock()
defer p.lock.Unlock()
p.Groups[group.GroupID] = group
@@ -225,6 +231,7 @@ func (p *Profile) ProcessInvite(gci *protocol.GroupChatInvite, peerHostname stri
group.SignedGroupID = gci.GetSignedGroupId()
copy(group.GroupKey[:], gci.GetGroupSharedKey()[:])
group.GroupServer = gci.GetServerHost()
group.InitialMessage = gci.GetInitialMessage()[:]
group.Accepted = false
group.Owner = peerHostname
p.AddGroup(group)

+ 7
- 1
model/profile_test.go View File

@@ -94,7 +94,7 @@ func TestProfileGroup(t *testing.T) {
sarah.AddContact(alice.Onion, &alice.PublicProfile)
alice.AddContact(sarah.Onion, &sarah.PublicProfile)

gid, invite, _ := alice.StartGroup("aaa.onion")
gid, invite, _ := alice.StartGroupWithMessage("aaa.onion", []byte("Hello World"))
gci := &protocol.CwtchPeerPacket{}
proto.Unmarshal(invite, gci)
sarah.ProcessInvite(gci.GetGroupChatInvite(), alice.Onion)
@@ -115,6 +115,12 @@ func TestProfileGroup(t *testing.T) {
c2, s2, _ := sarah.EncryptMessageToGroup("Hello World", group2.GroupID)
alice.AttemptDecryption(c2, s2)

sarahGroup := sarah.GetGroupByGroupID(group.GroupID)
im := sarahGroup.GetInitialMessage()
if string(im) != "Hello World" {
t.Errorf("Initial Message was not stored properly: %v", im)
}

bob := GenerateNewProfile("bob")
bob.AddContact(alice.Onion, &alice.PublicProfile)
bob.ProcessInvite(gci2.GetGroupChatInvite(), alice.Onion)

+ 7
- 2
peer/cwtch_peer.go View File

@@ -224,7 +224,7 @@ func (cp *cwtchPeer) ImportGroup(exportedInvite string) (groupID string, err err
func (cp *cwtchPeer) ExportGroup(groupID string) (string, error) {
group := cp.Profile.GetGroupByGroupID(groupID)
if group != nil {
invite, err := group.Invite()
invite, err := group.Invite([]byte{})
if err == nil {
exportedInvite := "torv2" + cp.Profile.Onion + base64.StdEncoding.EncodeToString(cp.Profile.Ed25519PublicKey) + base64.StdEncoding.EncodeToString(invite)
return exportedInvite, err
@@ -238,6 +238,11 @@ func (cp *cwtchPeer) StartGroup(server string) (string, []byte, error) {
return cp.Profile.StartGroup(server)
}

// StartGroupWithMessage create a new group linked to the given server and returns the group ID, an invite or an error.
func (cp *cwtchPeer) StartGroupWithMessage(server string, initialMessage []byte) (string, []byte, error) {
return cp.Profile.StartGroupWithMessage(server, initialMessage)
}

// GetGroups returns an unordered list of all group IDs.
func (cp *cwtchPeer) GetGroups() []string {
return cp.Profile.GetGroups()
@@ -276,7 +281,7 @@ func (cp *cwtchPeer) InviteOnionToGroup(onion string, groupid string) error {
group := cp.Profile.GetGroupByGroupID(groupid)
if group != nil {
log.Printf("Constructing invite for group: %v\n", group)
invite, err := group.Invite()
invite, err := group.Invite(group.GetInitialMessage())
if err != nil {
return err
}

+ 29
- 27
protocol/cwtch-profile.pb.go View File

@@ -1,6 +1,17 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: cwtch-profile.proto

/*
Package protocol is a generated protocol buffer package.

It is generated from these files:
cwtch-profile.proto

It has these top-level messages:
CwtchPeerPacket
CwtchIdentity
GroupChatInvite
*/
package protocol

import proto "github.com/golang/protobuf/proto"
@@ -12,6 +23,12 @@ var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

type CwtchPeerPacket struct {
CwtchIdentify *CwtchIdentity `protobuf:"bytes,1,opt,name=cwtch_identify,json=cwtchIdentify" json:"cwtch_identify,omitempty"`
GroupChatInvite *GroupChatInvite `protobuf:"bytes,2,opt,name=group_chat_invite,json=groupChatInvite" json:"group_chat_invite,omitempty"`
@@ -20,7 +37,7 @@ type CwtchPeerPacket struct {
func (m *CwtchPeerPacket) Reset() { *m = CwtchPeerPacket{} }
func (m *CwtchPeerPacket) String() string { return proto.CompactTextString(m) }
func (*CwtchPeerPacket) ProtoMessage() {}
func (*CwtchPeerPacket) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
func (*CwtchPeerPacket) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

func (m *CwtchPeerPacket) GetCwtchIdentify() *CwtchIdentity {
if m != nil {
@@ -44,7 +61,7 @@ type CwtchIdentity struct {
func (m *CwtchIdentity) Reset() { *m = CwtchIdentity{} }
func (m *CwtchIdentity) String() string { return proto.CompactTextString(m) }
func (*CwtchIdentity) ProtoMessage() {}
func (*CwtchIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
func (*CwtchIdentity) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }

func (m *CwtchIdentity) GetName() string {
if m != nil {
@@ -66,12 +83,13 @@ type GroupChatInvite struct {
GroupSharedKey []byte `protobuf:"bytes,2,opt,name=group_shared_key,json=groupSharedKey,proto3" json:"group_shared_key,omitempty"`
ServerHost string `protobuf:"bytes,3,opt,name=server_host,json=serverHost" json:"server_host,omitempty"`
SignedGroupId []byte `protobuf:"bytes,4,opt,name=signed_group_id,json=signedGroupId,proto3" json:"signed_group_id,omitempty"`
InitialMessage []byte `protobuf:"bytes,5,opt,name=initial_message,json=initialMessage,proto3" json:"initial_message,omitempty"`
}

func (m *GroupChatInvite) Reset() { *m = GroupChatInvite{} }
func (m *GroupChatInvite) String() string { return proto.CompactTextString(m) }
func (*GroupChatInvite) ProtoMessage() {}
func (*GroupChatInvite) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} }
func (*GroupChatInvite) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }

func (m *GroupChatInvite) GetGroupName() string {
if m != nil {
@@ -101,33 +119,17 @@ func (m *GroupChatInvite) GetSignedGroupId() []byte {
return nil
}

func (m *GroupChatInvite) GetInitialMessage() []byte {
if m != nil {
return m.InitialMessage
}
return nil
}

func init() {
proto.RegisterType((*CwtchPeerPacket)(nil), "protocol.CwtchPeerPacket")
proto.RegisterType((*CwtchIdentity)(nil), "protocol.CwtchIdentity")
proto.RegisterType((*GroupChatInvite)(nil), "protocol.GroupChatInvite")
}

func init() { proto.RegisterFile("cwtch-profile.proto", fileDescriptor1) }

var fileDescriptor1 = []byte{
// 299 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0xc1, 0x4a, 0xf3, 0x40,
0x14, 0x85, 0xc9, 0xff, 0x17, 0xb1, 0xb7, 0xb6, 0xa9, 0xe3, 0xc2, 0xb8, 0x10, 0xa5, 0x0b, 0xe9,
0x42, 0x0b, 0x56, 0xba, 0x70, 0xe3, 0xa6, 0x88, 0x86, 0x82, 0xc4, 0xf8, 0x00, 0x43, 0x3a, 0x73,
0x93, 0x0c, 0x8d, 0x99, 0x30, 0x99, 0x56, 0xe6, 0x4d, 0xdc, 0xfb, 0xa2, 0x92, 0x1b, 0xa5, 0xad,
0xab, 0x99, 0x39, 0xe7, 0xde, 0xef, 0x1c, 0x06, 0x4e, 0xc4, 0x87, 0x15, 0xf9, 0x4d, 0x65, 0x74,
0xaa, 0x0a, 0x9c, 0x54, 0x46, 0x5b, 0xcd, 0x0e, 0xe9, 0x10, 0xba, 0x18, 0x7d, 0x7a, 0xe0, 0xcf,
0x9b, 0x89, 0x08, 0xd1, 0x44, 0x89, 0x58, 0xa1, 0x65, 0x0f, 0x30, 0xa0, 0x25, 0xae, 0x24, 0x96,
0x56, 0xa5, 0x2e, 0xf0, 0x2e, 0xbd, 0x71, 0x6f, 0x7a, 0x3a, 0xf9, 0x5d, 0x9b, 0xd0, 0x4a, 0x48,
0xb6, 0x75, 0x71, 0x5f, 0x6c, 0x9f, 0xa9, 0x63, 0x8f, 0x70, 0x9c, 0x19, 0xbd, 0xae, 0xb8, 0xc8,
0x13, 0xcb, 0x55, 0xb9, 0x51, 0x16, 0x83, 0x7f, 0x84, 0x38, 0xdb, 0x22, 0x9e, 0x9a, 0x91, 0x79,
0x9e, 0xd8, 0x90, 0x06, 0x62, 0x3f, 0xdb, 0x17, 0x46, 0xaf, 0xd0, 0xdf, 0x8b, 0x61, 0x0c, 0x3a,
0x65, 0xf2, 0x8e, 0xd4, 0xa6, 0x1b, 0xd3, 0x9d, 0x5d, 0x03, 0x43, 0x39, 0x9d, 0xcd, 0x6e, 0xef,
0x79, 0xb5, 0x5e, 0x16, 0x4a, 0xf0, 0x15, 0x3a, 0x0a, 0x3b, 0x8a, 0x87, 0x3f, 0x4e, 0x44, 0xc6,
0x02, 0xdd, 0xe8, 0xcb, 0x03, 0xff, 0x4f, 0x2e, 0x3b, 0x07, 0x68, 0xdb, 0xee, 0xb0, 0xbb, 0xa4,
0xbc, 0x34, 0x01, 0x63, 0x18, 0xb6, 0x76, 0x9d, 0x27, 0x06, 0xe5, 0x0e, 0x7e, 0x40, 0xfa, 0x1b,
0xc9, 0x0b, 0x74, 0xec, 0x02, 0x7a, 0x35, 0x9a, 0x0d, 0x1a, 0x9e, 0xeb, 0xda, 0x06, 0xff, 0x89,
0x04, 0xad, 0xf4, 0xac, 0x6b, 0xcb, 0xae, 0xc0, 0xaf, 0x55, 0x56, 0xa2, 0xe4, 0x2d, 0x51, 0xc9,
0xa0, 0x43, 0xa4, 0x7e, 0x2b, 0x53, 0xb3, 0x50, 0x2e, 0x0f, 0xe8, 0x8f, 0xee, 0xbe, 0x03, 0x00,
0x00, 0xff, 0xff, 0x62, 0x61, 0x2d, 0x00, 0xbb, 0x01, 0x00, 0x00,
}
func init() { proto.RegisterFile("cwtch-profile.proto", fileDescriptor0) }

+ 1
- 0
protocol/cwtch-profile.proto View File

@@ -17,4 +17,5 @@ message GroupChatInvite {
bytes group_shared_key = 2;
string server_host = 3;
bytes signed_group_id = 4;
bytes initial_message = 5;
}

Loading…
Cancel
Save