96 lines
3.0 KiB
Go
96 lines
3.0 KiB
Go
package communities
|
|
|
|
import (
|
|
"github.com/golang/protobuf/proto"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
|
)
|
|
|
|
type DescriptionEncryptor interface {
|
|
encryptCommunityDescription(community *Community, d *protobuf.CommunityDescription) (string, []byte, error)
|
|
encryptCommunityDescriptionChannel(community *Community, channelID string, d *protobuf.CommunityDescription) (string, []byte, error)
|
|
decryptCommunityDescription(keyIDSeqNo string, d []byte) (*protobuf.CommunityDescription, error)
|
|
}
|
|
|
|
// Encrypts members and chats
|
|
func encryptDescription(encryptor DescriptionEncryptor, community *Community, description *protobuf.CommunityDescription) error {
|
|
description.PrivateData = make(map[string][]byte)
|
|
|
|
for channelID, channel := range description.Chats {
|
|
if !community.channelEncrypted(channelID) {
|
|
continue
|
|
}
|
|
|
|
descriptionToEncrypt := &protobuf.CommunityDescription{
|
|
Chats: map[string]*protobuf.CommunityChat{
|
|
channelID: proto.Clone(channel).(*protobuf.CommunityChat),
|
|
},
|
|
}
|
|
|
|
keyIDSeqNo, encryptedDescription, err := encryptor.encryptCommunityDescriptionChannel(community, channelID, descriptionToEncrypt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Set private data and cleanup unencrypted channel's members
|
|
description.PrivateData[keyIDSeqNo] = encryptedDescription
|
|
channel.Members = make(map[string]*protobuf.CommunityMember)
|
|
}
|
|
|
|
if community.Encrypted() {
|
|
descriptionToEncrypt := &protobuf.CommunityDescription{
|
|
Members: description.Members,
|
|
Chats: description.Chats,
|
|
}
|
|
|
|
keyIDSeqNo, encryptedDescription, err := encryptor.encryptCommunityDescription(community, descriptionToEncrypt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Set private data and cleanup unencrypted members and chats
|
|
description.PrivateData[keyIDSeqNo] = encryptedDescription
|
|
description.Members = make(map[string]*protobuf.CommunityMember)
|
|
description.Chats = make(map[string]*protobuf.CommunityChat)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Decrypts members and chats
|
|
func decryptDescription(encryptor DescriptionEncryptor, description *protobuf.CommunityDescription, logger *zap.Logger) error {
|
|
for keyIDSeqNo, encryptedDescription := range description.PrivateData {
|
|
decryptedDescription, err := encryptor.decryptCommunityDescription(keyIDSeqNo, encryptedDescription)
|
|
if err != nil {
|
|
// ignore error, try to decrypt next data
|
|
logger.Debug("failed to decrypt community private data", zap.String("keyIDSeqNo", keyIDSeqNo), zap.Error(err))
|
|
continue
|
|
}
|
|
|
|
for pk, member := range decryptedDescription.Members {
|
|
if description.Members == nil {
|
|
description.Members = make(map[string]*protobuf.CommunityMember)
|
|
}
|
|
description.Members[pk] = member
|
|
}
|
|
|
|
for id, decryptedChannel := range decryptedDescription.Chats {
|
|
if description.Chats == nil {
|
|
description.Chats = make(map[string]*protobuf.CommunityChat)
|
|
}
|
|
|
|
if channel := description.Chats[id]; channel != nil {
|
|
if len(channel.Members) == 0 {
|
|
channel.Members = decryptedChannel.Members
|
|
}
|
|
} else {
|
|
description.Chats[id] = decryptedChannel
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|