forked from jshiffer/matterbridge
85 lines
2.9 KiB
Go
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
|
|
}
|