4
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2025-06-27 15:49:23 +00:00

Add dependencies/vendor (whatsapp)

This commit is contained in:
Wim
2022-01-31 00:27:37 +01:00
parent e7b193788a
commit e3cafeaf92
1074 changed files with 3091569 additions and 26075 deletions

View File

@ -0,0 +1,141 @@
package groups
import (
"fmt"
"go.mau.fi/libsignal/cipher"
"go.mau.fi/libsignal/ecc"
"go.mau.fi/libsignal/groups/ratchet"
"go.mau.fi/libsignal/groups/state/record"
"go.mau.fi/libsignal/groups/state/store"
"go.mau.fi/libsignal/protocol"
"go.mau.fi/libsignal/signalerror"
)
// NewGroupCipher will return a new group message cipher that can be used for
// encrypt/decrypt operations.
func NewGroupCipher(builder *SessionBuilder, senderKeyID *protocol.SenderKeyName,
senderKeyStore store.SenderKey) *GroupCipher {
return &GroupCipher{
senderKeyID: senderKeyID,
senderKeyStore: senderKeyStore,
sessionBuilder: builder,
}
}
// GroupCipher is the main entry point for group encrypt/decrypt operations.
// Once a session has been established, this can be used for
// all encrypt/decrypt operations within that session.
type GroupCipher struct {
senderKeyID *protocol.SenderKeyName
senderKeyStore store.SenderKey
sessionBuilder *SessionBuilder
}
// Encrypt will take the given message in bytes and return encrypted bytes.
func (c *GroupCipher) Encrypt(plaintext []byte) (protocol.GroupCiphertextMessage, error) {
// Load the sender key based on id from our store.
keyRecord := c.senderKeyStore.LoadSenderKey(c.senderKeyID)
senderKeyState, err := keyRecord.SenderKeyState()
if err != nil {
return nil, err
}
// Get the message key from the senderkey state.
senderKey, err := senderKeyState.SenderChainKey().SenderMessageKey()
if err != nil {
return nil, err
}
// Encrypt the plaintext.
ciphertext, err := cipher.EncryptCbc(senderKey.Iv(), senderKey.CipherKey(), plaintext)
if err != nil {
return nil, err
}
senderKeyMessage := protocol.NewSenderKeyMessage(
senderKeyState.KeyID(),
senderKey.Iteration(),
ciphertext,
senderKeyState.SigningKey().PrivateKey(),
c.sessionBuilder.serializer.SenderKeyMessage,
)
senderKeyState.SetSenderChainKey(senderKeyState.SenderChainKey().Next())
c.senderKeyStore.StoreSenderKey(c.senderKeyID, keyRecord)
return senderKeyMessage, nil
}
// Decrypt decrypts the given message using an existing session that
// is stored in the senderKey store.
func (c *GroupCipher) Decrypt(senderKeyMessage *protocol.SenderKeyMessage) ([]byte, error) {
keyRecord := c.senderKeyStore.LoadSenderKey(c.senderKeyID)
if keyRecord.IsEmpty() {
return nil, fmt.Errorf("%w for %s in %s", signalerror.ErrNoSenderKeyForUser, c.senderKeyID.Sender().String(), c.senderKeyID.GroupID())
}
// Get the senderkey state by id.
senderKeyState, err := keyRecord.GetSenderKeyStateByID(senderKeyMessage.KeyID())
if err != nil {
return nil, err
}
// Verify the signature of the senderkey message.
verified := c.verifySignature(senderKeyState.SigningKey().PublicKey(), senderKeyMessage)
if !verified {
return nil, signalerror.ErrSenderKeyStateVerificationFailed
}
senderKey, err := c.getSenderKey(senderKeyState, senderKeyMessage.Iteration())
if err != nil {
return nil, err
}
// Decrypt the message ciphertext.
plaintext, err := cipher.DecryptCbc(senderKey.Iv(), senderKey.CipherKey(), senderKeyMessage.Ciphertext())
if err != nil {
return nil, err
}
// Store the sender key by id.
c.senderKeyStore.StoreSenderKey(c.senderKeyID, keyRecord)
return plaintext, nil
}
// verifySignature will verify the signature of the senderkey message with
// the given public key.
func (c *GroupCipher) verifySignature(signingPubKey ecc.ECPublicKeyable,
senderKeyMessage *protocol.SenderKeyMessage) bool {
return ecc.VerifySignature(signingPubKey, senderKeyMessage.Serialize(), senderKeyMessage.Signature())
}
func (c *GroupCipher) getSenderKey(senderKeyState *record.SenderKeyState, iteration uint32) (*ratchet.SenderMessageKey, error) {
senderChainKey := senderKeyState.SenderChainKey()
if senderChainKey.Iteration() > iteration {
if senderKeyState.HasSenderMessageKey(iteration) {
return senderKeyState.RemoveSenderMessageKey(iteration), nil
}
return nil, fmt.Errorf("%w (current: %d, received: %d)", signalerror.ErrOldCounter, senderChainKey.Iteration(), iteration)
}
if iteration-senderChainKey.Iteration() > 2000 {
return nil, signalerror.ErrTooFarIntoFuture
}
for senderChainKey.Iteration() < iteration {
senderMessageKey, err := senderChainKey.SenderMessageKey()
if err != nil {
return nil, err
}
senderKeyState.AddSenderMessageKey(senderMessageKey)
senderChainKey = senderChainKey.Next()
}
senderKeyState.SetSenderChainKey(senderChainKey.Next())
return senderChainKey.SenderMessageKey()
}

View File

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

View File

@ -0,0 +1,3 @@
// Package ratchet provides the methods necessary to establish a ratchet
// session for group messaging.
package ratchet

View File

@ -0,0 +1,68 @@
package ratchet
import (
"crypto/hmac"
"crypto/sha256"
)
var messageKeySeed = []byte{0x01}
var chainKeySeed = []byte{0x02}
// NewSenderChainKey will return a new SenderChainKey.
func NewSenderChainKey(iteration uint32, chainKey []byte) *SenderChainKey {
return &SenderChainKey{
iteration: iteration,
chainKey: chainKey,
}
}
// NewSenderChainKeyFromStruct will return a new chain key object from the
// given serializeable structure.
func NewSenderChainKeyFromStruct(structure *SenderChainKeyStructure) *SenderChainKey {
return &SenderChainKey{
iteration: structure.Iteration,
chainKey: structure.ChainKey,
}
}
// NewStructFromSenderChainKeys returns a serializeable structure of chain keys.
func NewStructFromSenderChainKey(key *SenderChainKey) *SenderChainKeyStructure {
return &SenderChainKeyStructure{
Iteration: key.iteration,
ChainKey: key.chainKey,
}
}
// SenderChainKeyStructure is a serializeable structure of SenderChainKeys.
type SenderChainKeyStructure struct {
Iteration uint32
ChainKey []byte
}
type SenderChainKey struct {
iteration uint32
chainKey []byte
}
func (k *SenderChainKey) Iteration() uint32 {
return k.iteration
}
func (k *SenderChainKey) SenderMessageKey() (*SenderMessageKey, error) {
return NewSenderMessageKey(k.iteration, k.getDerivative(messageKeySeed, k.chainKey))
}
func (k *SenderChainKey) Next() *SenderChainKey {
return NewSenderChainKey(k.iteration+1, k.getDerivative(chainKeySeed, k.chainKey))
}
func (k *SenderChainKey) Seed() []byte {
return k.chainKey
}
func (k *SenderChainKey) getDerivative(seed []byte, key []byte) []byte {
mac := hmac.New(sha256.New, key[:])
mac.Write(seed)
return mac.Sum(nil)
}

View File

@ -0,0 +1,89 @@
package ratchet
import (
"go.mau.fi/libsignal/kdf"
"go.mau.fi/libsignal/util/bytehelper"
)
// KdfInfo is optional bytes to include in deriving secrets with KDF.
const KdfInfo string = "WhisperGroup"
// NewSenderMessageKey will return a new sender message key using the given
// iteration and seed.
func NewSenderMessageKey(iteration uint32, seed []byte) (*SenderMessageKey, error) {
derivative, err := kdf.DeriveSecrets(seed, nil, []byte(KdfInfo), 48)
if err != nil {
return nil, err
}
// Split our derived secrets into 2 parts
parts := bytehelper.Split(derivative, 16, 32)
// Build the message key.
senderKeyMessage := &SenderMessageKey{
iteration: iteration,
seed: seed,
iv: parts[0],
cipherKey: parts[1],
}
return senderKeyMessage, nil
}
// NewSenderMessageKeyFromStruct will return a new message key object from the
// given serializeable structure.
func NewSenderMessageKeyFromStruct(structure *SenderMessageKeyStructure) *SenderMessageKey {
return &SenderMessageKey{
iteration: structure.Iteration,
iv: structure.IV,
cipherKey: structure.CipherKey,
seed: structure.Seed,
}
}
// NewStructFromSenderMessageKey returns a serializeable structure of message keys.
func NewStructFromSenderMessageKey(key *SenderMessageKey) *SenderMessageKeyStructure {
return &SenderMessageKeyStructure{
CipherKey: key.cipherKey,
Iteration: key.iteration,
IV: key.iv,
Seed: key.seed,
}
}
// SenderMessageKeyStructure is a serializeable structure of SenderMessageKeys.
type SenderMessageKeyStructure struct {
Iteration uint32
IV []byte
CipherKey []byte
Seed []byte
}
// SenderMessageKey is a structure for sender message keys used in group
// messaging.
type SenderMessageKey struct {
iteration uint32
iv []byte
cipherKey []byte
seed []byte
}
// Iteration will return the sender message key's iteration.
func (k *SenderMessageKey) Iteration() uint32 {
return k.iteration
}
// Iv will return the sender message key's initialization vector.
func (k *SenderMessageKey) Iv() []byte {
return k.iv
}
// CipherKey will return the key in bytes.
func (k *SenderMessageKey) CipherKey() []byte {
return k.cipherKey
}
// Seed will return the sender message key's seed.
func (k *SenderMessageKey) Seed() []byte {
return k.seed
}

View File

@ -0,0 +1,2 @@
// Package record provides the state and record of a group session.
package record

View File

@ -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,
}
}

View File

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

View File

@ -0,0 +1,3 @@
// Package store provides the storage interfaces for storing group sender
// key records.
package store

View File

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