diff options
Diffstat (limited to 'vendor/go.mau.fi/libsignal/groups/state')
5 files changed, 351 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/libsignal/groups/state/record/Doc.go b/vendor/go.mau.fi/libsignal/groups/state/record/Doc.go new file mode 100644 index 00000000..5a7d7307 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/groups/state/record/Doc.go @@ -0,0 +1,2 @@ +// Package record provides the state and record of a group session. +package record diff --git a/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go b/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go new file mode 100644 index 00000000..64d59068 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go @@ -0,0 +1,149 @@ +package record + +import ( + "fmt" + + "go.mau.fi/libsignal/ecc" + "go.mau.fi/libsignal/signalerror" +) + +const maxStates = 5 + +// SenderKeySerializer is an interface for serializing and deserializing +// SenderKey objects into bytes. An implementation of this interface should be +// used to encode/decode the object into JSON, Protobuffers, etc. +type SenderKeySerializer interface { + Serialize(preKey *SenderKeyStructure) []byte + Deserialize(serialized []byte) (*SenderKeyStructure, error) +} + +// NewSenderKeyFromBytes will return a prekey record from the given bytes using the given serializer. +func NewSenderKeyFromBytes(serialized []byte, serializer SenderKeySerializer, + stateSerializer SenderKeyStateSerializer) (*SenderKey, error) { + + // Use the given serializer to decode the senderkey record + senderKeyStructure, err := serializer.Deserialize(serialized) + if err != nil { + return nil, err + } + + return NewSenderKeyFromStruct(senderKeyStructure, serializer, stateSerializer) +} + +// NewSenderKeyFromStruct returns a SenderKey record using the given serializable structure. +func NewSenderKeyFromStruct(structure *SenderKeyStructure, serializer SenderKeySerializer, + stateSerializer SenderKeyStateSerializer) (*SenderKey, error) { + + // Build our sender key states from structure. + senderKeyStates := make([]*SenderKeyState, len(structure.SenderKeyStates)) + for i := range structure.SenderKeyStates { + var err error + senderKeyStates[i], err = NewSenderKeyStateFromStructure(structure.SenderKeyStates[i], stateSerializer) + if err != nil { + return nil, err + } + } + + // Build and return our session. + senderKey := &SenderKey{ + senderKeyStates: senderKeyStates, + serializer: serializer, + } + + return senderKey, nil + +} + +// NewSenderKey record returns a new sender key record that can +// be stored in a SenderKeyStore. +func NewSenderKey(serializer SenderKeySerializer, + stateSerializer SenderKeyStateSerializer) *SenderKey { + + return &SenderKey{ + senderKeyStates: []*SenderKeyState{}, + serializer: serializer, + stateSerializer: stateSerializer, + } +} + +// SenderKeyStructure is a structure for serializing SenderKey records. +type SenderKeyStructure struct { + SenderKeyStates []*SenderKeyStateStructure +} + +// SenderKey record is a structure for storing pre keys inside +// a SenderKeyStore. +type SenderKey struct { + senderKeyStates []*SenderKeyState + serializer SenderKeySerializer + stateSerializer SenderKeyStateSerializer +} + +// SenderKeyState will return the first sender key state in the record's +// list of sender key states. +func (k *SenderKey) SenderKeyState() (*SenderKeyState, error) { + if len(k.senderKeyStates) > 0 { + return k.senderKeyStates[0], nil + } + return nil, signalerror.ErrNoSenderKeyStatesInRecord +} + +// GetSenderKeyStateByID will return the sender key state with the given +// key id. +func (k *SenderKey) GetSenderKeyStateByID(keyID uint32) (*SenderKeyState, error) { + for i := 0; i < len(k.senderKeyStates); i++ { + if k.senderKeyStates[i].KeyID() == keyID { + return k.senderKeyStates[i], nil + } + } + + return nil, fmt.Errorf("%w %d", signalerror.ErrNoSenderKeyStateForID, keyID) +} + +// IsEmpty will return false if there is more than one state in this +// senderkey record. +func (k *SenderKey) IsEmpty() bool { + return len(k.senderKeyStates) == 0 +} + +// AddSenderKeyState will add a new state to this senderkey record with the given +// id, iteration, chainkey, and signature key. +func (k *SenderKey) AddSenderKeyState(id uint32, iteration uint32, + chainKey []byte, signatureKey ecc.ECPublicKeyable) { + + newState := NewSenderKeyStateFromPublicKey(id, iteration, chainKey, signatureKey, k.stateSerializer) + k.senderKeyStates = append([]*SenderKeyState{newState}, k.senderKeyStates...) + + if len(k.senderKeyStates) > maxStates { + k.senderKeyStates = k.senderKeyStates[:len(k.senderKeyStates)-1] + } +} + +// SetSenderKeyState will replace the current senderkey states with the given +// senderkey state. +func (k *SenderKey) SetSenderKeyState(id uint32, iteration uint32, + chainKey []byte, signatureKey *ecc.ECKeyPair) { + + newState := NewSenderKeyState(id, iteration, chainKey, signatureKey, k.stateSerializer) + k.senderKeyStates = make([]*SenderKeyState, 0, maxStates/2) + k.senderKeyStates = append(k.senderKeyStates, newState) +} + +// Serialize will return the record as serialized bytes so it can be +// persistently stored. +func (k *SenderKey) Serialize() []byte { + return k.serializer.Serialize(k.Structure()) +} + +// Structure will return a simple serializable record structure. +// This is used for serialization to persistently +// store a session record. +func (k *SenderKey) Structure() *SenderKeyStructure { + senderKeyStates := make([]*SenderKeyStateStructure, len(k.senderKeyStates)) + for i := range k.senderKeyStates { + senderKeyStates[i] = k.senderKeyStates[i].structure() + } + return &SenderKeyStructure{ + SenderKeyStates: senderKeyStates, + } +} diff --git a/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go b/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go new file mode 100644 index 00000000..e3187c30 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go @@ -0,0 +1,186 @@ +package record + +import ( + "go.mau.fi/libsignal/ecc" + "go.mau.fi/libsignal/groups/ratchet" + "go.mau.fi/libsignal/util/bytehelper" +) + +const maxMessageKeys = 2000 + +// SenderKeyStateSerializer is an interface for serializing and deserializing +// a Signal State into bytes. An implementation of this interface should be +// used to encode/decode the object into JSON, Protobuffers, etc. +type SenderKeyStateSerializer interface { + Serialize(state *SenderKeyStateStructure) []byte + Deserialize(serialized []byte) (*SenderKeyStateStructure, error) +} + +// NewSenderKeyStateFromBytes will return a Signal State from the given +// bytes using the given serializer. +func NewSenderKeyStateFromBytes(serialized []byte, serializer SenderKeyStateSerializer) (*SenderKeyState, error) { + // Use the given serializer to decode the signal message. + stateStructure, err := serializer.Deserialize(serialized) + if err != nil { + return nil, err + } + + return NewSenderKeyStateFromStructure(stateStructure, serializer) +} + +// NewSenderKeyState returns a new SenderKeyState. +func NewSenderKeyState(keyID uint32, iteration uint32, chainKey []byte, + signatureKey *ecc.ECKeyPair, serializer SenderKeyStateSerializer) *SenderKeyState { + + return &SenderKeyState{ + keys: make([]*ratchet.SenderMessageKey, 0, maxMessageKeys/2), + keyID: keyID, + senderChainKey: ratchet.NewSenderChainKey(iteration, chainKey), + signingKeyPair: signatureKey, + serializer: serializer, + } +} + +// NewSenderKeyStateFromPublicKey returns a new SenderKeyState with the given publicKey. +func NewSenderKeyStateFromPublicKey(keyID uint32, iteration uint32, chainKey []byte, + signatureKey ecc.ECPublicKeyable, serializer SenderKeyStateSerializer) *SenderKeyState { + + keyPair := ecc.NewECKeyPair(signatureKey, nil) + + return &SenderKeyState{ + keys: make([]*ratchet.SenderMessageKey, 0, maxMessageKeys/2), + keyID: keyID, + senderChainKey: ratchet.NewSenderChainKey(iteration, chainKey), + signingKeyPair: keyPair, + serializer: serializer, + } +} + +// NewSenderKeyStateFromStructure will return a new session state with the +// given state structure. This structure is given back from an +// implementation of the sender key state serializer. +func NewSenderKeyStateFromStructure(structure *SenderKeyStateStructure, + serializer SenderKeyStateSerializer) (*SenderKeyState, error) { + + // Convert our ecc keys from bytes into object form. + signingKeyPublic, err := ecc.DecodePoint(structure.SigningKeyPublic, 0) + if err != nil { + return nil, err + } + signingKeyPrivate := ecc.NewDjbECPrivateKey(bytehelper.SliceToArray(structure.SigningKeyPrivate)) + + // Build our sender message keys from structure + senderMessageKeys := make([]*ratchet.SenderMessageKey, len(structure.Keys)) + for i := range structure.Keys { + senderMessageKeys[i] = ratchet.NewSenderMessageKeyFromStruct(structure.Keys[i]) + } + + // Build our state object. + state := &SenderKeyState{ + keys: senderMessageKeys, + keyID: structure.KeyID, + senderChainKey: ratchet.NewSenderChainKeyFromStruct(structure.SenderChainKey), + signingKeyPair: ecc.NewECKeyPair(signingKeyPublic, signingKeyPrivate), + serializer: serializer, + } + + return state, nil +} + +// SenderKeyStateStructure is a serializeable structure of SenderKeyState. +type SenderKeyStateStructure struct { + Keys []*ratchet.SenderMessageKeyStructure + KeyID uint32 + SenderChainKey *ratchet.SenderChainKeyStructure + SigningKeyPrivate []byte + SigningKeyPublic []byte +} + +// SenderKeyState is a structure for maintaining a senderkey session state. +type SenderKeyState struct { + keys []*ratchet.SenderMessageKey + keyID uint32 + senderChainKey *ratchet.SenderChainKey + signingKeyPair *ecc.ECKeyPair + serializer SenderKeyStateSerializer +} + +// SigningKey returns the signing key pair of the sender key state. +func (k *SenderKeyState) SigningKey() *ecc.ECKeyPair { + return k.signingKeyPair +} + +// SenderChainKey returns the sender chain key of the state. +func (k *SenderKeyState) SenderChainKey() *ratchet.SenderChainKey { + return k.senderChainKey +} + +// KeyID returns the state's key id. +func (k *SenderKeyState) KeyID() uint32 { + return k.keyID +} + +// HasSenderMessageKey will return true if the state has a key with the +// given iteration. +func (k *SenderKeyState) HasSenderMessageKey(iteration uint32) bool { + for i := 0; i < len(k.keys); i++ { + if k.keys[i].Iteration() == iteration { + return true + } + } + return false +} + +// AddSenderMessageKey will add the given sender message key to the state. +func (k *SenderKeyState) AddSenderMessageKey(senderMsgKey *ratchet.SenderMessageKey) { + k.keys = append(k.keys, senderMsgKey) + + if len(k.keys) > maxMessageKeys { + k.keys = k.keys[1:] + } +} + +// SetSenderChainKey will set the state's sender chain key with the given key. +func (k *SenderKeyState) SetSenderChainKey(senderChainKey *ratchet.SenderChainKey) { + k.senderChainKey = senderChainKey +} + +// RemoveSenderMessageKey will remove the key in this state with the given iteration number. +func (k *SenderKeyState) RemoveSenderMessageKey(iteration uint32) *ratchet.SenderMessageKey { + for i := 0; i < len(k.keys); i++ { + if k.keys[i].Iteration() == iteration { + removed := k.keys[i] + k.keys = append(k.keys[0:i], k.keys[i+1:]...) + return removed + } + } + + return nil +} + +// Serialize will return the state as bytes using the given serializer. +func (k *SenderKeyState) Serialize() []byte { + return k.serializer.Serialize(k.structure()) +} + +// structure will return a serializable structure of the +// the given state so it can be persistently stored. +func (k *SenderKeyState) structure() *SenderKeyStateStructure { + // Convert our sender message keys into a serializeable structure + keys := make([]*ratchet.SenderMessageKeyStructure, len(k.keys)) + for i := range k.keys { + keys[i] = ratchet.NewStructFromSenderMessageKey(k.keys[i]) + } + + // Build and return our state structure. + s := &SenderKeyStateStructure{ + Keys: keys, + KeyID: k.keyID, + SenderChainKey: ratchet.NewStructFromSenderChainKey(k.senderChainKey), + SigningKeyPublic: k.signingKeyPair.PublicKey().Serialize(), + } + if k.signingKeyPair.PrivateKey() != nil { + s.SigningKeyPrivate = bytehelper.ArrayToSlice(k.signingKeyPair.PrivateKey().Serialize()) + } + return s +} diff --git a/vendor/go.mau.fi/libsignal/groups/state/store/Doc.go b/vendor/go.mau.fi/libsignal/groups/state/store/Doc.go new file mode 100644 index 00000000..8a23b446 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/groups/state/store/Doc.go @@ -0,0 +1,3 @@ +// Package store provides the storage interfaces for storing group sender +// key records. +package store diff --git a/vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go b/vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go new file mode 100644 index 00000000..a068df7c --- /dev/null +++ b/vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go @@ -0,0 +1,11 @@ +package store + +import ( + "go.mau.fi/libsignal/groups/state/record" + "go.mau.fi/libsignal/protocol" +) + +type SenderKey interface { + StoreSenderKey(senderKeyName *protocol.SenderKeyName, keyRecord *record.SenderKey) + LoadSenderKey(senderKeyName *protocol.SenderKeyName) *record.SenderKey +} |