diff options
Diffstat (limited to 'vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go')
-rw-r--r-- | vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go b/vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go new file mode 100644 index 00000000..2a5569b7 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go @@ -0,0 +1,84 @@ +// Package groups is responsible for setting up group SenderKey encrypted sessions. +// Once a session has been established, GroupCipher can be used to encrypt/decrypt +// messages in that session. +// +// The built sessions are unidirectional: they can be used either for sending or +// for receiving, but not both. Sessions are constructed per (groupId + senderId + +// deviceId) tuple. Remote logical users are identified by their senderId, and each +// logical recipientId can have multiple physical devices. +package groups + +import ( + "go.mau.fi/libsignal/groups/state/record" + "go.mau.fi/libsignal/groups/state/store" + "go.mau.fi/libsignal/protocol" + "go.mau.fi/libsignal/serialize" + "go.mau.fi/libsignal/util/keyhelper" +) + +// NewGroupSessionBuilder will return a new group session builder. +func NewGroupSessionBuilder(senderKeyStore store.SenderKey, + serializer *serialize.Serializer) *SessionBuilder { + + return &SessionBuilder{ + senderKeyStore: senderKeyStore, + serializer: serializer, + } +} + +// SessionBuilder is a structure for building group sessions. +type SessionBuilder struct { + senderKeyStore store.SenderKey + serializer *serialize.Serializer +} + +// Process will process an incoming group message and set up the corresponding +// session for it. +func (b *SessionBuilder) Process(senderKeyName *protocol.SenderKeyName, + msg *protocol.SenderKeyDistributionMessage) { + + senderKeyRecord := b.senderKeyStore.LoadSenderKey(senderKeyName) + if senderKeyRecord == nil { + senderKeyRecord = record.NewSenderKey(b.serializer.SenderKeyRecord, b.serializer.SenderKeyState) + } + senderKeyRecord.AddSenderKeyState(msg.ID(), msg.Iteration(), msg.ChainKey(), msg.SignatureKey()) + b.senderKeyStore.StoreSenderKey(senderKeyName, senderKeyRecord) +} + +// Create will create a new group session for the given name. +func (b *SessionBuilder) Create(senderKeyName *protocol.SenderKeyName) (*protocol.SenderKeyDistributionMessage, error) { + // Load the senderkey by name + senderKeyRecord := b.senderKeyStore.LoadSenderKey(senderKeyName) + + // If the record is empty, generate new keys. + if senderKeyRecord == nil || senderKeyRecord.IsEmpty() { + senderKeyRecord = record.NewSenderKey(b.serializer.SenderKeyRecord, b.serializer.SenderKeyState) + signingKey, err := keyhelper.GenerateSenderSigningKey() + if err != nil { + return nil, err + } + senderKeyRecord.SetSenderKeyState( + keyhelper.GenerateSenderKeyID(), 0, + keyhelper.GenerateSenderKey(), + signingKey, + ) + b.senderKeyStore.StoreSenderKey(senderKeyName, senderKeyRecord) + } + + // Get the senderkey state. + state, err := senderKeyRecord.SenderKeyState() + if err != nil { + return nil, err + } + + // Create the group message to return. + senderKeyDistributionMessage := protocol.NewSenderKeyDistributionMessage( + state.KeyID(), + state.SenderChainKey().Iteration(), + state.SenderChainKey().Seed(), + state.SigningKey().PublicKey(), + b.serializer.SenderKeyDistributionMessage, + ) + + return senderKeyDistributionMessage, nil +} |