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

Feat/channels encryption #3789

Merged
merged 1 commit into from
Jul 24, 2023
Merged
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
4 changes: 2 additions & 2 deletions protocol/common/message_sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func (s *MessageSender) sendCommunity(
// Check if it's a key exchange message. In this case we send it
// to all the recipients
if rawMessage.CommunityKeyExMsgType != KeyExMsgNone {
keyExMessageSpecs, err := s.protocol.GetKeyExMessageSpecs(rawMessage.CommunityID, s.identity, rawMessage.Recipients, rawMessage.CommunityKeyExMsgType == KeyExMsgRekey)
keyExMessageSpecs, err := s.protocol.GetKeyExMessageSpecs(rawMessage.HashRatchetGroupID, s.identity, rawMessage.Recipients, rawMessage.CommunityKeyExMsgType == KeyExMsgRekey)
if err != nil {
return nil, err
}
Expand All @@ -307,7 +307,7 @@ func (s *MessageSender) sendCommunity(

// If it's a chat message, we send it on the community chat topic
if ShouldCommunityMessageBeEncrypted(rawMessage.MessageType) {
messageSpec, err := s.protocol.BuildHashRatchetMessage(rawMessage.CommunityID, wrappedMessage)
messageSpec, err := s.protocol.BuildHashRatchetMessage(rawMessage.HashRatchetGroupID, wrappedMessage)
if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions protocol/common/raw_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ type RawMessage struct {
CommunityKeyExMsgType CommKeyExMsgType
Ephemeral bool
BeforeDispatch func(*RawMessage) error
HashRatchetGroupID []byte
}
85 changes: 63 additions & 22 deletions protocol/communities/community.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,20 @@ func (o *Community) GetMember(pk *ecdsa.PublicKey) *protobuf.CommunityMember {
return o.getMember(pk)
}

func (o *Community) getChatMember(pk *ecdsa.PublicKey, chatID string) *protobuf.CommunityMember {
if !o.hasMember(pk) {
return nil
}

chat, ok := o.config.CommunityDescription.Chats[chatID]
if !ok {
return nil
}

key := common.PubkeyToHex(pk)
return chat.Members[key]
}

func (o *Community) hasMember(pk *ecdsa.PublicKey) bool {

member := o.getMember(pk)
Expand Down Expand Up @@ -735,18 +749,7 @@ func (o *Community) IsMemberInChat(pk *ecdsa.PublicKey, chatID string) bool {
o.mutex.Lock()
defer o.mutex.Unlock()

if !o.hasMember(pk) {
return false
}

chat, ok := o.config.CommunityDescription.Chats[chatID]
if !ok {
return false
}

key := common.PubkeyToHex(pk)
_, ok = chat.Members[key]
return ok
return o.getChatMember(pk, chatID) != nil
}

func (o *Community) RemoveUserFromChat(pk *ecdsa.PublicKey, chatID string) (*protobuf.CommunityDescription, error) {
Expand Down Expand Up @@ -904,17 +907,27 @@ func (o *Community) AddRoleToMember(pk *ecdsa.PublicKey, role protobuf.Community
}

updated := false
member := o.getMember(pk)
if member != nil {
addRole := func(member *protobuf.CommunityMember) {
roles := make(map[protobuf.CommunityMember_Roles]bool)
roles[role] = true
if !o.hasMemberPermission(member, roles) {
member.Roles = append(member.Roles, role)
o.config.CommunityDescription.Members[common.PubkeyToHex(pk)] = member
updated = true
}
}

member := o.getMember(pk)
if member != nil {
addRole(member)
}

for channelID := range o.chats() {
chatMember := o.getChatMember(pk, channelID)
if chatMember != nil {
addRole(member)
}
}

if updated {
o.increaseClock()
}
Expand All @@ -930,8 +943,7 @@ func (o *Community) RemoveRoleFromMember(pk *ecdsa.PublicKey, role protobuf.Comm
}

updated := false
member := o.getMember(pk)
if member != nil {
removeRole := func(member *protobuf.CommunityMember) {
roles := make(map[protobuf.CommunityMember_Roles]bool)
roles[role] = true
if o.hasMemberPermission(member, roles) {
Expand All @@ -942,11 +954,22 @@ func (o *Community) RemoveRoleFromMember(pk *ecdsa.PublicKey, role protobuf.Comm
}
}
member.Roles = newRoles
o.config.CommunityDescription.Members[common.PubkeyToHex(pk)] = member
updated = true
}
}

member := o.getMember(pk)
if member != nil {
removeRole(member)
}

for channelID := range o.chats() {
chatMember := o.getChatMember(pk, channelID)
if chatMember != nil {
removeRole(member)
}
}

if updated {
o.increaseClock()
}
Expand Down Expand Up @@ -1329,16 +1352,20 @@ func (o *Community) ToBytes() ([]byte, error) {
}

func (o *Community) Chats() map[string]*protobuf.CommunityChat {
response := make(map[string]*protobuf.CommunityChat)

// Why are we checking here for nil, it should be the responsibility of the caller
if o == nil {
return response
return make(map[string]*protobuf.CommunityChat)
}

o.mutex.Lock()
defer o.mutex.Unlock()

return o.chats()
}

func (o *Community) chats() map[string]*protobuf.CommunityChat {
response := make(map[string]*protobuf.CommunityChat)

if o.config != nil && o.config.CommunityDescription != nil {
for k, v := range o.config.CommunityDescription.Chats {
response[k] = v
Expand Down Expand Up @@ -1392,7 +1419,21 @@ func (o *Community) TokenPermissions() map[string]*protobuf.CommunityTokenPermis
}

func (o *Community) HasTokenPermissions() bool {
return len(o.config.CommunityDescription.TokenPermissions) > 0
return o.config.CommunityDescription.TokenPermissions != nil && len(o.config.CommunityDescription.TokenPermissions) > 0
}

func (o *Community) ChannelHasTokenPermissions(chatID string) bool {
if !o.HasTokenPermissions() {
return false
}

for _, tokenPermission := range o.TokenPermissions() {
if includes(tokenPermission.ChatIds, chatID) {
return true
}
}

return false
}

func TokenPermissionsByType(permissions map[string]*protobuf.CommunityTokenPermission, permissionType protobuf.CommunityTokenPermission_Type) []*protobuf.CommunityTokenPermission {
Expand Down
8 changes: 5 additions & 3 deletions protocol/communities/community_encryption_key_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ func evaluateCommunityLevelEncryptionKeyAction(origin, modified *Community, chan
func evaluateChannelLevelEncryptionKeyActions(origin, modified *Community, changes *CommunityChanges) *map[string]EncryptionKeyAction {
result := make(map[string]EncryptionKeyAction)

for chatID := range modified.config.CommunityDescription.Chats {
for channelID := range modified.config.CommunityDescription.Chats {
chatID := modified.IDString() + channelID

originChannelViewOnlyPermissions := origin.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL)
originChannelViewAndPostPermissions := origin.ChannelTokenPermissionsByType(chatID, protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL)
originChannelPermissions := append(originChannelViewOnlyPermissions, originChannelViewAndPostPermissions...)
Expand All @@ -75,13 +77,13 @@ func evaluateChannelLevelEncryptionKeyActions(origin, modified *Community, chang
membersAdded := make(map[string]*protobuf.CommunityMember)
membersRemoved := make(map[string]*protobuf.CommunityMember)

chatChanges, ok := changes.ChatsModified[chatID]
chatChanges, ok := changes.ChatsModified[channelID]
if ok {
membersAdded = chatChanges.MembersAdded
membersRemoved = chatChanges.MembersRemoved
}

result[chatID] = *evaluateEncryptionKeyAction(originChannelPermissions, modifiedChannelPermissions, modified.config.CommunityDescription.Members, membersAdded, membersRemoved)
result[channelID] = *evaluateEncryptionKeyAction(originChannelPermissions, modifiedChannelPermissions, modified.config.CommunityDescription.Chats[channelID].Members, membersAdded, membersRemoved)
}

return &result
Expand Down
22 changes: 13 additions & 9 deletions protocol/communities/community_encryption_key_action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/suite"

"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
)
Expand Down Expand Up @@ -622,7 +623,8 @@ func (s *CommunityEncryptionKeyActionSuite) TestCommunityLevelKeyActions_Permiss
}

func (s *CommunityEncryptionKeyActionSuite) TestChannelLevelKeyActions() {
chatID := "0x1234"
channelID := "1234"
chatID := types.EncodeHex(crypto.CompressPubkey(&s.identity.PublicKey)) + channelID
testCases := []struct {
name string
originPermissions []*protobuf.CommunityTokenPermission
Expand Down Expand Up @@ -736,7 +738,7 @@ func (s *CommunityEncryptionKeyActionSuite) TestChannelLevelKeyActions() {
for _, tc := range testCases {
s.Run(tc.name, func() {
origin := createTestCommunity(s.identity)
_, err := origin.CreateChat(chatID, &protobuf.CommunityChat{
_, err := origin.CreateChat(channelID, &protobuf.CommunityChat{
Members: map[string]*protobuf.CommunityMember{},
Permissions: &protobuf.CommunityPermissions{Access: protobuf.CommunityPermissions_NO_MEMBERSHIP},
Identity: &protobuf.ChatIdentity{},
Expand All @@ -752,7 +754,7 @@ func (s *CommunityEncryptionKeyActionSuite) TestChannelLevelKeyActions() {
for _, member := range tc.originMembers {
_, err := origin.AddMember(member, []protobuf.CommunityMember_Roles{})
s.Require().NoError(err)
_, err = origin.AddMemberToChat(chatID, member, []protobuf.CommunityMember_Roles{})
_, err = origin.AddMemberToChat(channelID, member, []protobuf.CommunityMember_Roles{})
s.Require().NoError(err)
}

Expand All @@ -763,12 +765,12 @@ func (s *CommunityEncryptionKeyActionSuite) TestChannelLevelKeyActions() {
for _, member := range tc.modifiedMembers {
_, err := modified.AddMember(member, []protobuf.CommunityMember_Roles{})
s.Require().NoError(err)
_, err = modified.AddMemberToChat(chatID, member, []protobuf.CommunityMember_Roles{})
_, err = modified.AddMemberToChat(channelID, member, []protobuf.CommunityMember_Roles{})
s.Require().NoError(err)
}

actions := EvaluateCommunityEncryptionKeyActions(origin, modified)
channelAction, ok := actions.ChannelKeysActions[chatID]
channelAction, ok := actions.ChannelKeysActions[channelID]
s.Require().True(ok)
s.Require().Equal(tc.expectedAction.ActionType, channelAction.ActionType)
s.Require().Len(tc.expectedAction.Members, len(channelAction.Members))
Expand All @@ -783,8 +785,10 @@ func (s *CommunityEncryptionKeyActionSuite) TestChannelLevelKeyActions() {
func (s *CommunityEncryptionKeyActionSuite) TestNilOrigin() {
newCommunity := createTestCommunity(s.identity)

chatID := "0x1234"
_, err := newCommunity.CreateChat(chatID, &protobuf.CommunityChat{
channelID := "0x1234"
chatID := types.EncodeHex(crypto.CompressPubkey(&s.identity.PublicKey)) + channelID

_, err := newCommunity.CreateChat(channelID, &protobuf.CommunityChat{
Members: map[string]*protobuf.CommunityMember{},
Permissions: &protobuf.CommunityPermissions{Access: protobuf.CommunityPermissions_NO_MEMBERSHIP},
Identity: &protobuf.ChatIdentity{},
Expand Down Expand Up @@ -813,6 +817,6 @@ func (s *CommunityEncryptionKeyActionSuite) TestNilOrigin() {
actions := EvaluateCommunityEncryptionKeyActions(nil, newCommunity)
s.Require().Equal(actions.CommunityKeyAction.ActionType, EncryptionKeyAdd)
s.Require().Len(actions.ChannelKeysActions, 1)
s.Require().NotNil(actions.ChannelKeysActions[chatID])
s.Require().Equal(actions.ChannelKeysActions[chatID].ActionType, EncryptionKeyAdd)
s.Require().NotNil(actions.ChannelKeysActions[channelID])
s.Require().Equal(actions.ChannelKeysActions[channelID].ActionType, EncryptionKeyAdd)
}
Loading