matterbridge/vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go
2022-03-20 14:57:48 +01:00

85 lines
2.9 KiB
Go

// 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
}