github.com/status-im/status-go@v1.1.0/protocol/communities/community_description_encryption.go (about) 1 package communities 2 3 import ( 4 "go.uber.org/zap" 5 6 "github.com/status-im/status-go/eth-node/types" 7 "github.com/status-im/status-go/protocol/protobuf" 8 ) 9 10 type DescriptionEncryptor interface { 11 encryptCommunityDescription(community *Community, d *protobuf.CommunityDescription) (string, []byte, error) 12 encryptCommunityDescriptionChannel(community *Community, channelID string, d *protobuf.CommunityDescription) (string, []byte, error) 13 decryptCommunityDescription(keyIDSeqNo string, d []byte) (*DecryptCommunityResponse, error) 14 } 15 16 // Encrypts members and chats 17 func encryptDescription(encryptor DescriptionEncryptor, community *Community, description *protobuf.CommunityDescription) error { 18 description.PrivateData = make(map[string][]byte) 19 20 for channelID, channel := range description.Chats { 21 if !community.channelEncrypted(channelID) { 22 continue 23 } 24 25 descriptionToEncrypt := &protobuf.CommunityDescription{ 26 Chats: map[string]*protobuf.CommunityChat{ 27 channelID: channel, 28 }, 29 } 30 31 keyIDSeqNo, encryptedDescription, err := encryptor.encryptCommunityDescriptionChannel(community, channelID, descriptionToEncrypt) 32 if err != nil { 33 return err 34 } 35 36 // Set private data and cleanup unencrypted channel's members 37 description.PrivateData[keyIDSeqNo] = encryptedDescription 38 channel.Members = make(map[string]*protobuf.CommunityMember) 39 } 40 41 if community.Encrypted() { 42 descriptionToEncrypt := &protobuf.CommunityDescription{ 43 Members: description.Members, 44 ActiveMembersCount: description.ActiveMembersCount, 45 Chats: description.Chats, 46 Categories: description.Categories, 47 } 48 49 keyIDSeqNo, encryptedDescription, err := encryptor.encryptCommunityDescription(community, descriptionToEncrypt) 50 if err != nil { 51 return err 52 } 53 54 // Set private data and cleanup unencrypted members, chats and categories 55 description.PrivateData[keyIDSeqNo] = encryptedDescription 56 description.Members = make(map[string]*protobuf.CommunityMember) 57 description.ActiveMembersCount = 0 58 description.Chats = make(map[string]*protobuf.CommunityChat) 59 description.Categories = make(map[string]*protobuf.CommunityCategory) 60 } 61 62 return nil 63 } 64 65 type CommunityPrivateDataFailedToDecrypt struct { 66 GroupID []byte 67 KeyID []byte 68 } 69 70 // Decrypts members and chats 71 func decryptDescription(id types.HexBytes, encryptor DescriptionEncryptor, description *protobuf.CommunityDescription, logger *zap.Logger) ([]*CommunityPrivateDataFailedToDecrypt, error) { 72 if len(description.PrivateData) == 0 { 73 return nil, nil 74 } 75 76 var failedToDecrypt []*CommunityPrivateDataFailedToDecrypt 77 78 for keyIDSeqNo, encryptedDescription := range description.PrivateData { 79 decryptedDescriptionResponse, err := encryptor.decryptCommunityDescription(keyIDSeqNo, encryptedDescription) 80 if decryptedDescriptionResponse != nil && !decryptedDescriptionResponse.Decrypted { 81 failedToDecrypt = append(failedToDecrypt, &CommunityPrivateDataFailedToDecrypt{GroupID: id, KeyID: decryptedDescriptionResponse.KeyID}) 82 } 83 if err != nil { 84 // ignore error, try to decrypt next data 85 logger.Debug("failed to decrypt community private data", zap.String("keyIDSeqNo", keyIDSeqNo), zap.Error(err)) 86 continue 87 } 88 decryptedDescription := decryptedDescriptionResponse.Description 89 90 if len(decryptedDescription.Members) > 0 { 91 description.Members = decryptedDescription.Members 92 } 93 94 if decryptedDescription.ActiveMembersCount > 0 { 95 description.ActiveMembersCount = decryptedDescription.ActiveMembersCount 96 } 97 98 for id, decryptedChannel := range decryptedDescription.Chats { 99 if description.Chats == nil { 100 description.Chats = make(map[string]*protobuf.CommunityChat) 101 } 102 103 if channel := description.Chats[id]; channel != nil { 104 if len(decryptedChannel.Members) > 0 { 105 channel.Members = decryptedChannel.Members 106 } 107 } else { 108 description.Chats[id] = decryptedChannel 109 } 110 } 111 112 if len(decryptedDescription.Categories) > 0 { 113 description.Categories = decryptedDescription.Categories 114 } 115 } 116 117 return failedToDecrypt, nil 118 }