mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-06-27 23:49:25 +00:00
Add dependencies/vendor (whatsapp)
This commit is contained in:
157
vendor/go.mau.fi/libsignal/state/record/ChainState.go
vendored
Normal file
157
vendor/go.mau.fi/libsignal/state/record/ChainState.go
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/kdf"
|
||||
"go.mau.fi/libsignal/keys/chain"
|
||||
"go.mau.fi/libsignal/keys/message"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
// NewReceiverChainPair will return a new ReceiverChainPair object.
|
||||
func NewReceiverChainPair(receiverChain *Chain, index int) *ReceiverChainPair {
|
||||
return &ReceiverChainPair{
|
||||
ReceiverChain: receiverChain,
|
||||
Index: index,
|
||||
}
|
||||
}
|
||||
|
||||
// ReceiverChainPair is a structure for a receiver chain key and index number.
|
||||
type ReceiverChainPair struct {
|
||||
ReceiverChain *Chain
|
||||
Index int
|
||||
}
|
||||
|
||||
// NewChain returns a new Chain structure for SessionState.
|
||||
func NewChain(senderRatchetKeyPair *ecc.ECKeyPair, chainKey *chain.Key,
|
||||
messageKeys []*message.Keys) *Chain {
|
||||
|
||||
return &Chain{
|
||||
senderRatchetKeyPair: senderRatchetKeyPair,
|
||||
chainKey: chainKey,
|
||||
messageKeys: messageKeys,
|
||||
}
|
||||
}
|
||||
|
||||
// NewChainFromStructure will return a new Chain with the given
|
||||
// chain structure.
|
||||
func NewChainFromStructure(structure *ChainStructure) (*Chain, error) {
|
||||
// Alias to SliceToArray
|
||||
getArray := bytehelper.SliceToArray
|
||||
|
||||
// Build the sender ratchet key from bytes.
|
||||
senderRatchetKeyPublic, err := ecc.DecodePoint(structure.SenderRatchetKeyPublic, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var senderRatchetKeyPrivate ecc.ECPrivateKeyable
|
||||
if len(structure.SenderRatchetKeyPrivate) == 32 {
|
||||
senderRatchetKeyPrivate = ecc.NewDjbECPrivateKey(getArray(structure.SenderRatchetKeyPrivate))
|
||||
}
|
||||
senderRatchetKeyPair := ecc.NewECKeyPair(senderRatchetKeyPublic, senderRatchetKeyPrivate)
|
||||
|
||||
// Build our message keys from the message key structures.
|
||||
messageKeys := make([]*message.Keys, len(structure.MessageKeys))
|
||||
for i := range structure.MessageKeys {
|
||||
messageKeys[i] = message.NewKeysFromStruct(structure.MessageKeys[i])
|
||||
}
|
||||
|
||||
// Build our new chain state.
|
||||
chainState := NewChain(
|
||||
senderRatchetKeyPair,
|
||||
chain.NewKeyFromStruct(structure.ChainKey, kdf.DeriveSecrets),
|
||||
messageKeys,
|
||||
)
|
||||
|
||||
return chainState, nil
|
||||
}
|
||||
|
||||
// ChainStructure is a serializeable structure for chain states.
|
||||
type ChainStructure struct {
|
||||
SenderRatchetKeyPublic []byte
|
||||
SenderRatchetKeyPrivate []byte
|
||||
ChainKey *chain.KeyStructure
|
||||
MessageKeys []*message.KeysStructure
|
||||
}
|
||||
|
||||
// Chain is a structure used inside the SessionState that keeps
|
||||
// track of an ongoing ratcheting chain for a session.
|
||||
type Chain struct {
|
||||
senderRatchetKeyPair *ecc.ECKeyPair
|
||||
chainKey *chain.Key
|
||||
messageKeys []*message.Keys
|
||||
}
|
||||
|
||||
// SenderRatchetKey returns the sender's EC keypair.
|
||||
func (c *Chain) SenderRatchetKey() *ecc.ECKeyPair {
|
||||
return c.senderRatchetKeyPair
|
||||
}
|
||||
|
||||
// SetSenderRatchetKey will set the chain state with the given EC
|
||||
// key pair.
|
||||
func (c *Chain) SetSenderRatchetKey(key *ecc.ECKeyPair) {
|
||||
c.senderRatchetKeyPair = key
|
||||
}
|
||||
|
||||
// ChainKey will return the chain key in the chain state.
|
||||
func (c *Chain) ChainKey() *chain.Key {
|
||||
return c.chainKey
|
||||
}
|
||||
|
||||
// SetChainKey will set the chain state's chain key.
|
||||
func (c *Chain) SetChainKey(key *chain.Key) {
|
||||
c.chainKey = key
|
||||
}
|
||||
|
||||
// MessageKeys will return the message keys associated with the
|
||||
// chain state.
|
||||
func (c *Chain) MessageKeys() []*message.Keys {
|
||||
return c.messageKeys
|
||||
}
|
||||
|
||||
// SetMessageKeys will set the chain state with the given message
|
||||
// keys.
|
||||
func (c *Chain) SetMessageKeys(keys []*message.Keys) {
|
||||
c.messageKeys = keys
|
||||
}
|
||||
|
||||
// AddMessageKeys will append the chain state with the given
|
||||
// message keys.
|
||||
func (c *Chain) AddMessageKeys(keys *message.Keys) {
|
||||
c.messageKeys = append(c.messageKeys, keys)
|
||||
}
|
||||
|
||||
// PopFirstMessageKeys will remove the first message key from
|
||||
// the chain's list of message keys.
|
||||
func (c *Chain) PopFirstMessageKeys() *message.Keys {
|
||||
removed := c.messageKeys[0]
|
||||
c.messageKeys = c.messageKeys[1:]
|
||||
|
||||
return removed
|
||||
}
|
||||
|
||||
// structure returns a serializeable structure of the chain state.
|
||||
func (c *Chain) structure() *ChainStructure {
|
||||
// Alias to ArrayToSlice
|
||||
getSlice := bytehelper.ArrayToSlice
|
||||
|
||||
// Convert our message keys into a serializeable structure.
|
||||
messageKeys := make([]*message.KeysStructure, len(c.messageKeys))
|
||||
for i := range c.messageKeys {
|
||||
messageKeys[i] = message.NewStructFromKeys(c.messageKeys[i])
|
||||
}
|
||||
|
||||
// Convert our sender ratchet key private
|
||||
var senderRatchetKeyPrivate []byte
|
||||
if c.senderRatchetKeyPair.PrivateKey() != nil {
|
||||
senderRatchetKeyPrivate = getSlice(c.senderRatchetKeyPair.PrivateKey().Serialize())
|
||||
}
|
||||
|
||||
// Build the chain structure.
|
||||
return &ChainStructure{
|
||||
SenderRatchetKeyPublic: c.senderRatchetKeyPair.PublicKey().Serialize(),
|
||||
SenderRatchetKeyPrivate: senderRatchetKeyPrivate,
|
||||
ChainKey: chain.NewStructFromKey(c.chainKey),
|
||||
MessageKeys: messageKeys,
|
||||
}
|
||||
}
|
3
vendor/go.mau.fi/libsignal/state/record/Doc.go
vendored
Normal file
3
vendor/go.mau.fi/libsignal/state/record/Doc.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// Package record provides the state and record of an ongoing double
|
||||
// ratchet session.
|
||||
package record
|
91
vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go
vendored
Normal file
91
vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
// NewPendingKeyExchange will return a new PendingKeyExchange object.
|
||||
func NewPendingKeyExchange(sequence uint32, localBaseKeyPair, localRatchetKeyPair *ecc.ECKeyPair,
|
||||
localIdentityKeyPair *identity.KeyPair) *PendingKeyExchange {
|
||||
|
||||
return &PendingKeyExchange{
|
||||
sequence: sequence,
|
||||
localBaseKeyPair: localBaseKeyPair,
|
||||
localRatchetKeyPair: localRatchetKeyPair,
|
||||
localIdentityKeyPair: localIdentityKeyPair,
|
||||
}
|
||||
}
|
||||
|
||||
// NewPendingKeyExchangeFromStruct will return a PendingKeyExchange object from
|
||||
// the given structure. This is used to get a deserialized pending prekey exchange
|
||||
// fetched from persistent storage.
|
||||
func NewPendingKeyExchangeFromStruct(structure *PendingKeyExchangeStructure) *PendingKeyExchange {
|
||||
// Return nil if no structure was provided.
|
||||
if structure == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Alias the SliceToArray method.
|
||||
getArray := bytehelper.SliceToArray
|
||||
|
||||
// Convert the bytes in the given structure to ECC objects.
|
||||
localBaseKeyPair := ecc.NewECKeyPair(
|
||||
ecc.NewDjbECPublicKey(getArray(structure.LocalBaseKeyPublic)),
|
||||
ecc.NewDjbECPrivateKey(getArray(structure.LocalBaseKeyPrivate)),
|
||||
)
|
||||
localRatchetKeyPair := ecc.NewECKeyPair(
|
||||
ecc.NewDjbECPublicKey(getArray(structure.LocalRatchetKeyPublic)),
|
||||
ecc.NewDjbECPrivateKey(getArray(structure.LocalRatchetKeyPrivate)),
|
||||
)
|
||||
localIdentityKeyPair := identity.NewKeyPair(
|
||||
identity.NewKey(ecc.NewDjbECPublicKey(getArray(structure.LocalIdentityKeyPublic))),
|
||||
ecc.NewDjbECPrivateKey(getArray(structure.LocalIdentityKeyPrivate)),
|
||||
)
|
||||
|
||||
// Return the PendingKeyExchange with the deserialized keys.
|
||||
return &PendingKeyExchange{
|
||||
sequence: structure.Sequence,
|
||||
localBaseKeyPair: localBaseKeyPair,
|
||||
localRatchetKeyPair: localRatchetKeyPair,
|
||||
localIdentityKeyPair: localIdentityKeyPair,
|
||||
}
|
||||
}
|
||||
|
||||
// PendingKeyExchangeStructure is a serializable structure for pending
|
||||
// key exchanges. This structure is used for persistent storage of the
|
||||
// key exchange state.
|
||||
type PendingKeyExchangeStructure struct {
|
||||
Sequence uint32
|
||||
LocalBaseKeyPublic []byte
|
||||
LocalBaseKeyPrivate []byte
|
||||
LocalRatchetKeyPublic []byte
|
||||
LocalRatchetKeyPrivate []byte
|
||||
LocalIdentityKeyPublic []byte
|
||||
LocalIdentityKeyPrivate []byte
|
||||
}
|
||||
|
||||
// PendingKeyExchange is a structure for storing a pending
|
||||
// key exchange for a session state.
|
||||
type PendingKeyExchange struct {
|
||||
sequence uint32
|
||||
localBaseKeyPair *ecc.ECKeyPair
|
||||
localRatchetKeyPair *ecc.ECKeyPair
|
||||
localIdentityKeyPair *identity.KeyPair
|
||||
}
|
||||
|
||||
// structre will return a serializable structure of a pending key exchange
|
||||
// so it can be persistently stored.
|
||||
func (p *PendingKeyExchange) structure() *PendingKeyExchangeStructure {
|
||||
getSlice := bytehelper.ArrayToSlice
|
||||
return &PendingKeyExchangeStructure{
|
||||
Sequence: p.sequence,
|
||||
LocalBaseKeyPublic: getSlice(p.localBaseKeyPair.PublicKey().PublicKey()),
|
||||
LocalBaseKeyPrivate: getSlice(p.localBaseKeyPair.PrivateKey().Serialize()),
|
||||
LocalRatchetKeyPublic: getSlice(p.localRatchetKeyPair.PublicKey().PublicKey()),
|
||||
LocalRatchetKeyPrivate: getSlice(p.localRatchetKeyPair.PrivateKey().Serialize()),
|
||||
LocalIdentityKeyPublic: getSlice(p.localIdentityKeyPair.PublicKey().PublicKey().PublicKey()),
|
||||
LocalIdentityKeyPrivate: getSlice(p.localIdentityKeyPair.PrivateKey().Serialize()),
|
||||
}
|
||||
}
|
62
vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go
vendored
Normal file
62
vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// NewPendingPreKey will return a new pending pre key object.
|
||||
func NewPendingPreKey(preKeyID *optional.Uint32, signedPreKeyID uint32,
|
||||
baseKey ecc.ECPublicKeyable) *PendingPreKey {
|
||||
|
||||
return &PendingPreKey{
|
||||
preKeyID: preKeyID,
|
||||
signedPreKeyID: signedPreKeyID,
|
||||
baseKey: baseKey,
|
||||
}
|
||||
}
|
||||
|
||||
// NewPendingPreKeyFromStruct will return a new pending prekey object from the
|
||||
// given structure.
|
||||
func NewPendingPreKeyFromStruct(preKey *PendingPreKeyStructure) (*PendingPreKey, error) {
|
||||
baseKey, err := ecc.DecodePoint(preKey.BaseKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pendingPreKey := NewPendingPreKey(
|
||||
preKey.PreKeyID,
|
||||
preKey.SignedPreKeyID,
|
||||
baseKey,
|
||||
)
|
||||
|
||||
return pendingPreKey, nil
|
||||
}
|
||||
|
||||
// PendingPreKeyStructure is a serializeable structure for pending
|
||||
// prekeys.
|
||||
type PendingPreKeyStructure struct {
|
||||
PreKeyID *optional.Uint32
|
||||
SignedPreKeyID uint32
|
||||
BaseKey []byte
|
||||
}
|
||||
|
||||
// PendingPreKey is a structure for pending pre keys
|
||||
// for a session state.
|
||||
type PendingPreKey struct {
|
||||
preKeyID *optional.Uint32
|
||||
signedPreKeyID uint32
|
||||
baseKey ecc.ECPublicKeyable
|
||||
}
|
||||
|
||||
// structure will return a serializeable structure of the pending prekey.
|
||||
func (p *PendingPreKey) structure() *PendingPreKeyStructure {
|
||||
if p != nil {
|
||||
return &PendingPreKeyStructure{
|
||||
PreKeyID: p.preKeyID,
|
||||
SignedPreKeyID: p.signedPreKeyID,
|
||||
BaseKey: p.baseKey.Serialize(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
90
vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go
vendored
Normal file
90
vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// PreKeySerializer is an interface for serializing and deserializing
|
||||
// PreKey objects into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type PreKeySerializer interface {
|
||||
Serialize(preKey *PreKeyStructure) []byte
|
||||
Deserialize(serialized []byte) (*PreKeyStructure, error)
|
||||
}
|
||||
|
||||
// NewPreKeyFromBytes will return a prekey record from the given bytes using the given serializer.
|
||||
func NewPreKeyFromBytes(serialized []byte, serializer PreKeySerializer) (*PreKey, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
preKeyStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewPreKeyFromStruct(preKeyStructure, serializer)
|
||||
}
|
||||
|
||||
// NewPreKeyFromStruct returns a PreKey record using the given serializable structure.
|
||||
func NewPreKeyFromStruct(structure *PreKeyStructure, serializer PreKeySerializer) (*PreKey, error) {
|
||||
// Create the prekey record from the structure.
|
||||
preKey := &PreKey{
|
||||
structure: *structure,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
// Generate the ECC key from bytes.
|
||||
publicKey := ecc.NewDjbECPublicKey(bytehelper.SliceToArray(structure.PublicKey))
|
||||
privateKey := ecc.NewDjbECPrivateKey(bytehelper.SliceToArray(structure.PrivateKey))
|
||||
keyPair := ecc.NewECKeyPair(publicKey, privateKey)
|
||||
preKey.keyPair = keyPair
|
||||
|
||||
return preKey, nil
|
||||
}
|
||||
|
||||
// NewPreKey record returns a new pre key record that can
|
||||
// be stored in a PreKeyStore.
|
||||
func NewPreKey(id uint32, keyPair *ecc.ECKeyPair, serializer PreKeySerializer) *PreKey {
|
||||
return &PreKey{
|
||||
structure: PreKeyStructure{
|
||||
ID: id,
|
||||
PublicKey: keyPair.PublicKey().Serialize(),
|
||||
PrivateKey: bytehelper.ArrayToSlice(keyPair.PrivateKey().Serialize()),
|
||||
},
|
||||
keyPair: keyPair,
|
||||
serializer: serializer,
|
||||
}
|
||||
}
|
||||
|
||||
// PreKeyStructure is a structure for serializing PreKey records.
|
||||
type PreKeyStructure struct {
|
||||
ID uint32
|
||||
PublicKey []byte
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
// PreKey record is a structure for storing pre keys inside
|
||||
// a PreKeyStore.
|
||||
type PreKey struct {
|
||||
structure PreKeyStructure
|
||||
keyPair *ecc.ECKeyPair
|
||||
serializer PreKeySerializer
|
||||
}
|
||||
|
||||
// ID returns the pre key record's id.
|
||||
func (p *PreKey) ID() *optional.Uint32 {
|
||||
// TODO: manually set this to empty if empty
|
||||
return optional.NewOptionalUint32(p.structure.ID)
|
||||
}
|
||||
|
||||
// KeyPair returns the pre key record's key pair.
|
||||
func (p *PreKey) KeyPair() *ecc.ECKeyPair {
|
||||
return p.keyPair
|
||||
}
|
||||
|
||||
// Serialize uses the PreKey serializer to return the PreKey
|
||||
// as serialized bytes.
|
||||
func (p *PreKey) Serialize() []byte {
|
||||
structure := p.structure
|
||||
return p.serializer.Serialize(&structure)
|
||||
}
|
197
vendor/go.mau.fi/libsignal/state/record/SessionRecord.go
vendored
Normal file
197
vendor/go.mau.fi/libsignal/state/record/SessionRecord.go
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// archivedStatesMaxLength describes how many previous session
|
||||
// states we should keep track of.
|
||||
const archivedStatesMaxLength int = 40
|
||||
|
||||
// SessionSerializer is an interface for serializing and deserializing
|
||||
// a Signal Session into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SessionSerializer interface {
|
||||
Serialize(state *SessionStructure) []byte
|
||||
Deserialize(serialized []byte) (*SessionStructure, error)
|
||||
}
|
||||
|
||||
// NewSessionFromBytes will return a Signal Session from the given
|
||||
// bytes using the given serializer.
|
||||
func NewSessionFromBytes(serialized []byte, serializer SessionSerializer, stateSerializer StateSerializer) (*Session, error) {
|
||||
// Use the given serializer to decode the session.
|
||||
sessionStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSessionFromStructure(sessionStructure, serializer, stateSerializer)
|
||||
}
|
||||
|
||||
// NewSession creates a new session record and uses the given session and state
|
||||
// serializers to convert the object into storeable bytes.
|
||||
func NewSession(serializer SessionSerializer, stateSerializer StateSerializer) *Session {
|
||||
record := Session{
|
||||
sessionState: NewState(stateSerializer),
|
||||
previousStates: []*State{},
|
||||
fresh: true,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return &record
|
||||
}
|
||||
|
||||
// NewSessionFromStructure will return a new Signal Session from the given
|
||||
// session structure and serializer.
|
||||
func NewSessionFromStructure(structure *SessionStructure, serializer SessionSerializer,
|
||||
stateSerializer StateSerializer) (*Session, error) {
|
||||
|
||||
// Build our previous states from structure.
|
||||
previousStates := make([]*State, len(structure.PreviousStates))
|
||||
for i := range structure.PreviousStates {
|
||||
var err error
|
||||
previousStates[i], err = NewStateFromStructure(structure.PreviousStates[i], stateSerializer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Build our current state from structure.
|
||||
sessionState, err := NewStateFromStructure(structure.SessionState, stateSerializer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build and return our session.
|
||||
session := &Session{
|
||||
previousStates: previousStates,
|
||||
sessionState: sessionState,
|
||||
serializer: serializer,
|
||||
fresh: false,
|
||||
}
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// NewSessionFromState creates a new session record from the given
|
||||
// session state.
|
||||
func NewSessionFromState(sessionState *State, serializer SessionSerializer) *Session {
|
||||
record := Session{
|
||||
sessionState: sessionState,
|
||||
previousStates: []*State{},
|
||||
fresh: false,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return &record
|
||||
}
|
||||
|
||||
// SessionStructure is a public, serializeable structure for Signal
|
||||
// Sessions. The states defined in the session are immuteable, as
|
||||
// they should not be changed by anyone but the serializer.
|
||||
type SessionStructure struct {
|
||||
SessionState *StateStructure
|
||||
PreviousStates []*StateStructure
|
||||
}
|
||||
|
||||
// Session encapsulates the state of an ongoing session.
|
||||
type Session struct {
|
||||
serializer SessionSerializer
|
||||
sessionState *State
|
||||
previousStates []*State
|
||||
fresh bool
|
||||
}
|
||||
|
||||
// SetState sets the session record's current state to the given
|
||||
// one.
|
||||
func (r *Session) SetState(sessionState *State) {
|
||||
r.sessionState = sessionState
|
||||
}
|
||||
|
||||
// IsFresh is used to determine if this is a brand new session
|
||||
// or if a session record has already existed.
|
||||
func (r *Session) IsFresh() bool {
|
||||
return r.fresh
|
||||
}
|
||||
|
||||
// SessionState returns the session state object of the current
|
||||
// session record.
|
||||
func (r *Session) SessionState() *State {
|
||||
return r.sessionState
|
||||
}
|
||||
|
||||
// PreviousSessionStates returns a list of all currently maintained
|
||||
// "previous" session states.
|
||||
func (r *Session) PreviousSessionStates() []*State {
|
||||
return r.previousStates
|
||||
}
|
||||
|
||||
// HasSessionState will check this record to see if the sender's
|
||||
// base key exists in the current and previous states.
|
||||
func (r *Session) HasSessionState(version int, senderBaseKey []byte) bool {
|
||||
// Ensure the session state version is identical to this one.
|
||||
if r.sessionState.Version() == version && (bytes.Compare(senderBaseKey, r.sessionState.SenderBaseKey()) == 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Loop through all of our previous states and see if this
|
||||
// exists in our state.
|
||||
for i := range r.previousStates {
|
||||
if r.previousStates[i].Version() == version && bytes.Compare(senderBaseKey, r.previousStates[i].SenderBaseKey()) == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ArchiveCurrentState moves the current session state into the list
|
||||
// of "previous" session states, and replaces the current session state
|
||||
// with a fresh reset instance.
|
||||
func (r *Session) ArchiveCurrentState() {
|
||||
r.PromoteState(NewState(r.sessionState.serializer))
|
||||
}
|
||||
|
||||
// PromoteState takes the given session state and replaces it with the
|
||||
// current state, pushing the previous current state to "previousStates".
|
||||
func (r *Session) PromoteState(promotedState *State) {
|
||||
r.previousStates = r.prependStates(r.previousStates, r.sessionState)
|
||||
r.sessionState = promotedState
|
||||
|
||||
// Remove the last state if it has reached our maximum length
|
||||
if len(r.previousStates) > archivedStatesMaxLength {
|
||||
r.previousStates = r.removeLastState(r.previousStates)
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize will return the session as serialized bytes so it can be
|
||||
// persistently stored.
|
||||
func (r *Session) Serialize() []byte {
|
||||
return r.serializer.Serialize(r.Structure())
|
||||
}
|
||||
|
||||
// prependStates takes an array/slice of states and prepends it with
|
||||
// the given session state.
|
||||
func (r *Session) prependStates(states []*State, sessionState *State) []*State {
|
||||
return append([]*State{sessionState}, states...)
|
||||
}
|
||||
|
||||
// removeLastState takes an array/slice of states and removes the
|
||||
// last element from it.
|
||||
func (r *Session) removeLastState(states []*State) []*State {
|
||||
return states[:len(states)-1]
|
||||
}
|
||||
|
||||
// Structure will return a simple serializable session structure
|
||||
// from the given structure. This is used for serialization to persistently
|
||||
// store a session record.
|
||||
func (r *Session) Structure() *SessionStructure {
|
||||
previousStates := make([]*StateStructure, len(r.previousStates))
|
||||
for i := range r.previousStates {
|
||||
previousStates[i] = r.previousStates[i].structure()
|
||||
}
|
||||
return &SessionStructure{
|
||||
SessionState: r.sessionState.structure(),
|
||||
PreviousStates: previousStates,
|
||||
}
|
||||
}
|
531
vendor/go.mau.fi/libsignal/state/record/SessionState.go
vendored
Normal file
531
vendor/go.mau.fi/libsignal/state/record/SessionState.go
vendored
Normal file
@ -0,0 +1,531 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/kdf"
|
||||
"go.mau.fi/libsignal/keys/chain"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/keys/message"
|
||||
"go.mau.fi/libsignal/keys/root"
|
||||
"go.mau.fi/libsignal/keys/session"
|
||||
"go.mau.fi/libsignal/logger"
|
||||
"go.mau.fi/libsignal/util/errorhelper"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
const maxMessageKeys int = 2000
|
||||
const maxReceiverChains int = 5
|
||||
|
||||
// StateSerializer 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 StateSerializer interface {
|
||||
Serialize(state *StateStructure) []byte
|
||||
Deserialize(serialized []byte) (*StateStructure, error)
|
||||
}
|
||||
|
||||
// NewStateFromBytes will return a Signal State from the given
|
||||
// bytes using the given serializer.
|
||||
func NewStateFromBytes(serialized []byte, serializer StateSerializer) (*State, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
stateStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewStateFromStructure(stateStructure, serializer)
|
||||
}
|
||||
|
||||
// NewState returns a new session state.
|
||||
func NewState(serializer StateSerializer) *State {
|
||||
return &State{serializer: serializer}
|
||||
}
|
||||
|
||||
// NewStateFromStructure will return a new session state with the
|
||||
// given state structure.
|
||||
func NewStateFromStructure(structure *StateStructure, serializer StateSerializer) (*State, error) {
|
||||
// Keep a list of errors, so they can be handled once.
|
||||
errors := errorhelper.NewMultiError()
|
||||
|
||||
// Convert our ecc keys from bytes into object form.
|
||||
localIdentityPublic, err := ecc.DecodePoint(structure.LocalIdentityPublic, 0)
|
||||
errors.Add(err)
|
||||
remoteIdentityPublic, err := ecc.DecodePoint(structure.RemoteIdentityPublic, 0)
|
||||
errors.Add(err)
|
||||
senderBaseKey, err := ecc.DecodePoint(structure.SenderBaseKey, 0)
|
||||
errors.Add(err)
|
||||
var pendingPreKey *PendingPreKey
|
||||
if structure.PendingPreKey != nil {
|
||||
pendingPreKey, err = NewPendingPreKeyFromStruct(structure.PendingPreKey)
|
||||
errors.Add(err)
|
||||
}
|
||||
senderChain, err := NewChainFromStructure(structure.SenderChain)
|
||||
errors.Add(err)
|
||||
|
||||
// Build our receiver chains from structure.
|
||||
receiverChains := make([]*Chain, len(structure.ReceiverChains))
|
||||
for i := range structure.ReceiverChains {
|
||||
receiverChains[i], err = NewChainFromStructure(structure.ReceiverChains[i])
|
||||
errors.Add(err)
|
||||
}
|
||||
|
||||
// Handle any errors. The first error will always be returned if there are multiple.
|
||||
if errors.HasErrors() {
|
||||
return nil, errors
|
||||
}
|
||||
|
||||
// Build our state object.
|
||||
state := &State{
|
||||
localIdentityPublic: identity.NewKey(localIdentityPublic),
|
||||
localRegistrationID: structure.LocalRegistrationID,
|
||||
needsRefresh: structure.NeedsRefresh,
|
||||
pendingKeyExchange: NewPendingKeyExchangeFromStruct(structure.PendingKeyExchange),
|
||||
pendingPreKey: pendingPreKey,
|
||||
previousCounter: structure.PreviousCounter,
|
||||
receiverChains: receiverChains,
|
||||
remoteIdentityPublic: identity.NewKey(remoteIdentityPublic),
|
||||
remoteRegistrationID: structure.RemoteRegistrationID,
|
||||
rootKey: root.NewKey(kdf.DeriveSecrets, structure.RootKey),
|
||||
senderBaseKey: senderBaseKey,
|
||||
senderChain: senderChain,
|
||||
serializer: serializer,
|
||||
sessionVersion: structure.SessionVersion,
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// StateStructure is the structure of a session state. Fields are public
|
||||
// to be used for serialization and deserialization.
|
||||
type StateStructure struct {
|
||||
LocalIdentityPublic []byte
|
||||
LocalRegistrationID uint32
|
||||
NeedsRefresh bool
|
||||
PendingKeyExchange *PendingKeyExchangeStructure
|
||||
PendingPreKey *PendingPreKeyStructure
|
||||
PreviousCounter uint32
|
||||
ReceiverChains []*ChainStructure
|
||||
RemoteIdentityPublic []byte
|
||||
RemoteRegistrationID uint32
|
||||
RootKey []byte
|
||||
SenderBaseKey []byte
|
||||
SenderChain *ChainStructure
|
||||
SessionVersion int
|
||||
}
|
||||
|
||||
// State is a session state that contains the structure for
|
||||
// all sessions. Session states are contained inside session records.
|
||||
// The session state is implemented as a struct rather than protobuffers
|
||||
// to allow other serialization methods.
|
||||
type State struct {
|
||||
localIdentityPublic *identity.Key
|
||||
localRegistrationID uint32
|
||||
needsRefresh bool
|
||||
pendingKeyExchange *PendingKeyExchange
|
||||
pendingPreKey *PendingPreKey
|
||||
previousCounter uint32
|
||||
receiverChains []*Chain
|
||||
remoteIdentityPublic *identity.Key
|
||||
remoteRegistrationID uint32
|
||||
rootKey *root.Key
|
||||
senderBaseKey ecc.ECPublicKeyable
|
||||
senderChain *Chain
|
||||
serializer StateSerializer
|
||||
sessionVersion int
|
||||
}
|
||||
|
||||
// SenderBaseKey returns the sender's base key in bytes.
|
||||
func (s *State) SenderBaseKey() []byte {
|
||||
if s.senderBaseKey == nil {
|
||||
return nil
|
||||
}
|
||||
return s.senderBaseKey.Serialize()
|
||||
}
|
||||
|
||||
// SetSenderBaseKey sets the sender's base key with the given bytes.
|
||||
func (s *State) SetSenderBaseKey(senderBaseKey []byte) {
|
||||
s.senderBaseKey, _ = ecc.DecodePoint(senderBaseKey, 0)
|
||||
}
|
||||
|
||||
// Version returns the session's version.
|
||||
func (s *State) Version() int {
|
||||
return s.sessionVersion
|
||||
}
|
||||
|
||||
// SetVersion sets the session state's version number.
|
||||
func (s *State) SetVersion(version int) {
|
||||
s.sessionVersion = version
|
||||
}
|
||||
|
||||
// RemoteIdentityKey returns the identity key of the remote user.
|
||||
func (s *State) RemoteIdentityKey() *identity.Key {
|
||||
return s.remoteIdentityPublic
|
||||
}
|
||||
|
||||
// SetRemoteIdentityKey sets this session's identity key for the remote
|
||||
// user.
|
||||
func (s *State) SetRemoteIdentityKey(identityKey *identity.Key) {
|
||||
s.remoteIdentityPublic = identityKey
|
||||
}
|
||||
|
||||
// LocalIdentityKey returns the session's identity key for the local
|
||||
// user.
|
||||
func (s *State) LocalIdentityKey() *identity.Key {
|
||||
return s.localIdentityPublic
|
||||
}
|
||||
|
||||
// SetLocalIdentityKey sets the session's identity key for the local
|
||||
// user.
|
||||
func (s *State) SetLocalIdentityKey(identityKey *identity.Key) {
|
||||
s.localIdentityPublic = identityKey
|
||||
}
|
||||
|
||||
// PreviousCounter returns the counter of the previous message.
|
||||
func (s *State) PreviousCounter() uint32 {
|
||||
return s.previousCounter
|
||||
}
|
||||
|
||||
// SetPreviousCounter sets the counter for the previous message.
|
||||
func (s *State) SetPreviousCounter(previousCounter uint32) {
|
||||
s.previousCounter = previousCounter
|
||||
}
|
||||
|
||||
// RootKey returns the root key for the session.
|
||||
func (s *State) RootKey() session.RootKeyable {
|
||||
return s.rootKey
|
||||
}
|
||||
|
||||
// SetRootKey sets the root key for the session.
|
||||
func (s *State) SetRootKey(rootKey session.RootKeyable) {
|
||||
s.rootKey = rootKey.(*root.Key)
|
||||
}
|
||||
|
||||
// SenderRatchetKey returns the public ratchet key of the sender.
|
||||
func (s *State) SenderRatchetKey() ecc.ECPublicKeyable {
|
||||
return s.senderChain.senderRatchetKeyPair.PublicKey()
|
||||
}
|
||||
|
||||
// SenderRatchetKeyPair returns the public/private ratchet key pair
|
||||
// of the sender.
|
||||
func (s *State) SenderRatchetKeyPair() *ecc.ECKeyPair {
|
||||
return s.senderChain.senderRatchetKeyPair
|
||||
}
|
||||
|
||||
// HasReceiverChain will check to see if the session state has
|
||||
// the given ephemeral key.
|
||||
func (s *State) HasReceiverChain(senderEphemeral ecc.ECPublicKeyable) bool {
|
||||
return s.receiverChain(senderEphemeral) != nil
|
||||
}
|
||||
|
||||
// HasSenderChain will check to see if the session state has a
|
||||
// sender chain.
|
||||
func (s *State) HasSenderChain() bool {
|
||||
return s.senderChain != nil
|
||||
}
|
||||
|
||||
// receiverChain will loop through the session state's receiver chains
|
||||
// and compare the given ephemeral key. If it is found, then the chain
|
||||
// and index will be returned as a pair.
|
||||
func (s *State) receiverChain(senderEphemeral ecc.ECPublicKeyable) *ReceiverChainPair {
|
||||
receiverChains := s.receiverChains
|
||||
|
||||
for i, receiverChain := range receiverChains {
|
||||
chainSenderRatchetKey, err := ecc.DecodePoint(receiverChain.senderRatchetKeyPair.PublicKey().Serialize(), 0)
|
||||
if err != nil {
|
||||
logger.Error("Error getting receiverchain: ", err)
|
||||
}
|
||||
|
||||
// If the chainSenderRatchetKey equals our senderEphemeral key, return it.
|
||||
if chainSenderRatchetKey.PublicKey() == senderEphemeral.PublicKey() {
|
||||
return NewReceiverChainPair(receiverChain, i)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReceiverChainKey will use the given ephemeral key to generate a new
|
||||
// chain key.
|
||||
func (s *State) ReceiverChainKey(senderEphemeral ecc.ECPublicKeyable) *chain.Key {
|
||||
receiverChainAndIndex := s.receiverChain(senderEphemeral)
|
||||
receiverChain := receiverChainAndIndex.ReceiverChain
|
||||
|
||||
if receiverChainAndIndex == nil || receiverChain == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return chain.NewKey(
|
||||
kdf.DeriveSecrets,
|
||||
receiverChain.chainKey.Key(),
|
||||
receiverChain.chainKey.Index(),
|
||||
)
|
||||
}
|
||||
|
||||
// AddReceiverChain will add the given ratchet key and chain key to the session
|
||||
// state.
|
||||
func (s *State) AddReceiverChain(senderRatchetKey ecc.ECPublicKeyable, chainKey session.ChainKeyable) {
|
||||
// Create a keypair structure with our sender ratchet key.
|
||||
senderKey := ecc.NewECKeyPair(senderRatchetKey, nil)
|
||||
|
||||
// Create a Chain state object that will hold our sender key, chain key, and
|
||||
// message keys.
|
||||
chain := NewChain(senderKey, chainKey.(*chain.Key), []*message.Keys{})
|
||||
|
||||
// Add the Chain state to our list of receiver chain states.
|
||||
s.receiverChains = append(s.receiverChains, chain)
|
||||
|
||||
// If our list of receiver chains is too big, delete the oldest entry.
|
||||
if len(s.receiverChains) > maxReceiverChains {
|
||||
i := 0
|
||||
s.receiverChains = append(s.receiverChains[:i], s.receiverChains[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
// SetSenderChain will set the given ratchet key pair and chain key for this session
|
||||
// state.
|
||||
func (s *State) SetSenderChain(senderRatchetKeyPair *ecc.ECKeyPair, chainKey session.ChainKeyable) {
|
||||
// Create a Chain state object that will hold our sender key, chain key, and
|
||||
// message keys.
|
||||
chain := NewChain(senderRatchetKeyPair, chainKey.(*chain.Key), []*message.Keys{})
|
||||
|
||||
// Set the sender chain.
|
||||
s.senderChain = chain
|
||||
}
|
||||
|
||||
// SenderChainKey will return the chain key of the session state.
|
||||
func (s *State) SenderChainKey() session.ChainKeyable {
|
||||
chainKey := s.senderChain.chainKey
|
||||
return chain.NewKey(kdf.DeriveSecrets, chainKey.Key(), chainKey.Index())
|
||||
}
|
||||
|
||||
// SetSenderChainKey will set the chain key in the chain state for this session to
|
||||
// the given chain key.
|
||||
func (s *State) SetSenderChainKey(nextChainKey session.ChainKeyable) {
|
||||
senderChain := s.senderChain
|
||||
senderChain.SetChainKey(nextChainKey.(*chain.Key))
|
||||
}
|
||||
|
||||
// HasMessageKeys returns true if we have message keys associated with the given
|
||||
// sender key and counter.
|
||||
func (s *State) HasMessageKeys(senderEphemeral ecc.ECPublicKeyable, counter uint32) bool {
|
||||
// Get our chain state that has our chain key.
|
||||
chainAndIndex := s.receiverChain(senderEphemeral)
|
||||
receiverChain := chainAndIndex.ReceiverChain
|
||||
|
||||
// If the chain is empty, we don't have any message keys.
|
||||
if receiverChain == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Get our message keys from our receiver chain.
|
||||
messageKeyList := receiverChain.MessageKeys()
|
||||
|
||||
// Loop through our message keys and compare its index with the
|
||||
// given counter.
|
||||
for _, messageKey := range messageKeyList {
|
||||
if messageKey.Index() == counter {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// RemoveMessageKeys removes the message key with the given sender key and
|
||||
// counter. It will return the removed message key.
|
||||
func (s *State) RemoveMessageKeys(senderEphemeral ecc.ECPublicKeyable, counter uint32) *message.Keys {
|
||||
// Get our chain state that has our chain key.
|
||||
chainAndIndex := s.receiverChain(senderEphemeral)
|
||||
chainKey := chainAndIndex.ReceiverChain
|
||||
|
||||
// If the chain is empty, we don't have any message keys.
|
||||
if chainKey == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get our message keys from our receiver chain.
|
||||
messageKeyList := chainKey.MessageKeys()
|
||||
|
||||
// Loop through our message keys and compare its index with the
|
||||
// given counter. When we find a match, remove it from our list.
|
||||
var rmIndex int
|
||||
for i, messageKey := range messageKeyList {
|
||||
if messageKey.Index() == counter {
|
||||
rmIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Retrive the message key
|
||||
messageKey := chainKey.messageKeys[rmIndex]
|
||||
|
||||
// Delete the message key from the given position.
|
||||
chainKey.messageKeys = append(chainKey.messageKeys[:rmIndex], chainKey.messageKeys[rmIndex+1:]...)
|
||||
|
||||
return message.NewKeys(
|
||||
messageKey.CipherKey(),
|
||||
messageKey.MacKey(),
|
||||
messageKey.Iv(),
|
||||
messageKey.Index(),
|
||||
)
|
||||
}
|
||||
|
||||
// SetMessageKeys will update the chain associated with the given sender key with
|
||||
// the given message keys.
|
||||
func (s *State) SetMessageKeys(senderEphemeral ecc.ECPublicKeyable, messageKeys *message.Keys) {
|
||||
chainAndIndex := s.receiverChain(senderEphemeral)
|
||||
chainState := chainAndIndex.ReceiverChain
|
||||
|
||||
// Add the message keys to our chain state.
|
||||
chainState.AddMessageKeys(
|
||||
message.NewKeys(
|
||||
messageKeys.CipherKey(),
|
||||
messageKeys.MacKey(),
|
||||
messageKeys.Iv(),
|
||||
messageKeys.Index(),
|
||||
),
|
||||
)
|
||||
|
||||
if len(chainState.MessageKeys()) > maxMessageKeys {
|
||||
chainState.PopFirstMessageKeys()
|
||||
}
|
||||
}
|
||||
|
||||
// SetReceiverChainKey sets the session's receiver chain key with the given chain key
|
||||
// associated with the given senderEphemeral key.
|
||||
func (s *State) SetReceiverChainKey(senderEphemeral ecc.ECPublicKeyable, chainKey session.ChainKeyable) {
|
||||
chainAndIndex := s.receiverChain(senderEphemeral)
|
||||
chainState := chainAndIndex.ReceiverChain
|
||||
chainState.SetChainKey(chainKey.(*chain.Key))
|
||||
}
|
||||
|
||||
// SetPendingKeyExchange will set the session's pending key exchange state to the given
|
||||
// sequence and key pairs.
|
||||
func (s *State) SetPendingKeyExchange(sequence uint32, ourBaseKey, ourRatchetKey *ecc.ECKeyPair,
|
||||
ourIdentityKey *identity.KeyPair) {
|
||||
|
||||
s.pendingKeyExchange = NewPendingKeyExchange(
|
||||
sequence,
|
||||
ourBaseKey,
|
||||
ourRatchetKey,
|
||||
ourIdentityKey,
|
||||
)
|
||||
}
|
||||
|
||||
// PendingKeyExchangeSequence will return the session's pending key exchange sequence
|
||||
// number.
|
||||
func (s *State) PendingKeyExchangeSequence() uint32 {
|
||||
return s.pendingKeyExchange.sequence
|
||||
}
|
||||
|
||||
// PendingKeyExchangeBaseKeyPair will return the session's pending key exchange base keypair.
|
||||
func (s *State) PendingKeyExchangeBaseKeyPair() *ecc.ECKeyPair {
|
||||
return s.pendingKeyExchange.localBaseKeyPair
|
||||
}
|
||||
|
||||
// PendingKeyExchangeRatchetKeyPair will return the session's pending key exchange ratchet
|
||||
// keypair.
|
||||
func (s *State) PendingKeyExchangeRatchetKeyPair() *ecc.ECKeyPair {
|
||||
return s.pendingKeyExchange.localRatchetKeyPair
|
||||
}
|
||||
|
||||
// PendingKeyExchangeIdentityKeyPair will return the session's pending key exchange identity
|
||||
// keypair.
|
||||
func (s *State) PendingKeyExchangeIdentityKeyPair() *identity.KeyPair {
|
||||
return s.pendingKeyExchange.localIdentityKeyPair
|
||||
}
|
||||
|
||||
// HasPendingKeyExchange will return true if there is a valid pending key exchange waiting.
|
||||
func (s *State) HasPendingKeyExchange() bool {
|
||||
return s.pendingKeyExchange != nil
|
||||
}
|
||||
|
||||
// SetUnacknowledgedPreKeyMessage will return unacknowledged pre key message with the
|
||||
// given key ids and base key.
|
||||
func (s *State) SetUnacknowledgedPreKeyMessage(preKeyID *optional.Uint32, signedPreKeyID uint32, baseKey ecc.ECPublicKeyable) {
|
||||
s.pendingPreKey = NewPendingPreKey(
|
||||
preKeyID,
|
||||
signedPreKeyID,
|
||||
baseKey,
|
||||
)
|
||||
}
|
||||
|
||||
// HasUnacknowledgedPreKeyMessage will return true if this session has an unacknowledged
|
||||
// pre key message.
|
||||
func (s *State) HasUnacknowledgedPreKeyMessage() bool {
|
||||
return s.pendingPreKey != nil
|
||||
}
|
||||
|
||||
// UnackPreKeyMessageItems will return the session's unacknowledged pre key messages.
|
||||
func (s *State) UnackPreKeyMessageItems() (*UnackPreKeyMessageItems, error) {
|
||||
preKeyID := s.pendingPreKey.preKeyID
|
||||
signedPreKeyID := s.pendingPreKey.signedPreKeyID
|
||||
baseKey, err := ecc.DecodePoint(s.pendingPreKey.baseKey.Serialize(), 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewUnackPreKeyMessageItems(preKeyID, signedPreKeyID, baseKey), nil
|
||||
}
|
||||
|
||||
// ClearUnackPreKeyMessage will clear the session's pending pre key.
|
||||
func (s *State) ClearUnackPreKeyMessage() {
|
||||
s.pendingPreKey = nil
|
||||
}
|
||||
|
||||
// SetRemoteRegistrationID sets the remote user's registration id.
|
||||
func (s *State) SetRemoteRegistrationID(registrationID uint32) {
|
||||
s.remoteRegistrationID = registrationID
|
||||
}
|
||||
|
||||
// RemoteRegistrationID returns the remote user's registration id.
|
||||
func (s *State) RemoteRegistrationID() uint32 {
|
||||
return s.remoteRegistrationID
|
||||
}
|
||||
|
||||
// SetLocalRegistrationID sets the local user's registration id.
|
||||
func (s *State) SetLocalRegistrationID(registrationID uint32) {
|
||||
s.localRegistrationID = registrationID
|
||||
}
|
||||
|
||||
// LocalRegistrationID returns the local user's registration id.
|
||||
func (s *State) LocalRegistrationID() uint32 {
|
||||
return s.localRegistrationID
|
||||
}
|
||||
|
||||
// Serialize will return the state as bytes using the given serializer.
|
||||
func (s *State) Serialize() []byte {
|
||||
return s.serializer.Serialize(s.structure())
|
||||
}
|
||||
|
||||
// structure will return a serializable structure of the
|
||||
// the given state so it can be persistently stored.
|
||||
func (s *State) structure() *StateStructure {
|
||||
// Convert our receiver chains into a serializeable structure
|
||||
receiverChains := make([]*ChainStructure, len(s.receiverChains))
|
||||
for i := range s.receiverChains {
|
||||
receiverChains[i] = s.receiverChains[i].structure()
|
||||
}
|
||||
|
||||
// Convert our pending key exchange into a serializeable structure
|
||||
var pendingKeyExchange *PendingKeyExchangeStructure
|
||||
if s.pendingKeyExchange != nil {
|
||||
pendingKeyExchange = s.pendingKeyExchange.structure()
|
||||
}
|
||||
|
||||
// Build and return our state structure.
|
||||
return &StateStructure{
|
||||
LocalIdentityPublic: s.localIdentityPublic.Serialize(),
|
||||
LocalRegistrationID: s.localRegistrationID,
|
||||
NeedsRefresh: s.needsRefresh,
|
||||
PendingKeyExchange: pendingKeyExchange,
|
||||
PendingPreKey: s.pendingPreKey.structure(),
|
||||
PreviousCounter: s.previousCounter,
|
||||
ReceiverChains: receiverChains,
|
||||
RemoteIdentityPublic: s.remoteIdentityPublic.Serialize(),
|
||||
RemoteRegistrationID: s.remoteRegistrationID,
|
||||
RootKey: s.rootKey.Bytes(),
|
||||
SenderBaseKey: s.senderBaseKey.Serialize(),
|
||||
SenderChain: s.senderChain.structure(),
|
||||
SessionVersion: s.sessionVersion,
|
||||
}
|
||||
}
|
112
vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go
vendored
Normal file
112
vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
// SignedPreKeySerializer is an interface for serializing and deserializing
|
||||
// SignedPreKey objects into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SignedPreKeySerializer interface {
|
||||
Serialize(signedPreKey *SignedPreKeyStructure) []byte
|
||||
Deserialize(serialized []byte) (*SignedPreKeyStructure, error)
|
||||
}
|
||||
|
||||
// NewSignedPreKeyFromBytes will return a signed prekey record from the given
|
||||
// bytes using the given serializer.
|
||||
func NewSignedPreKeyFromBytes(serialized []byte, serializer SignedPreKeySerializer) (*SignedPreKey, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
signedPreKeyStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSignedPreKeyFromStruct(signedPreKeyStructure, serializer)
|
||||
}
|
||||
|
||||
// NewSignedPreKeyFromStruct returns a SignedPreKey record using the given
|
||||
// serializable structure.
|
||||
func NewSignedPreKeyFromStruct(structure *SignedPreKeyStructure,
|
||||
serializer SignedPreKeySerializer) (*SignedPreKey, error) {
|
||||
|
||||
// Create the signed prekey record from the structure.
|
||||
signedPreKey := &SignedPreKey{
|
||||
structure: *structure,
|
||||
serializer: serializer,
|
||||
signature: bytehelper.SliceToArray64(structure.Signature),
|
||||
}
|
||||
|
||||
// Generate the ECC key from bytes.
|
||||
publicKey := ecc.NewDjbECPublicKey(bytehelper.SliceToArray(structure.PublicKey))
|
||||
privateKey := ecc.NewDjbECPrivateKey(bytehelper.SliceToArray(structure.PrivateKey))
|
||||
keyPair := ecc.NewECKeyPair(publicKey, privateKey)
|
||||
signedPreKey.keyPair = keyPair
|
||||
|
||||
return signedPreKey, nil
|
||||
}
|
||||
|
||||
// NewSignedPreKey record creates a new signed pre key record
|
||||
// with the given properties.
|
||||
func NewSignedPreKey(id uint32, timestamp int64, keyPair *ecc.ECKeyPair,
|
||||
sig [64]byte, serializer SignedPreKeySerializer) *SignedPreKey {
|
||||
|
||||
return &SignedPreKey{
|
||||
structure: SignedPreKeyStructure{
|
||||
ID: id,
|
||||
Timestamp: timestamp,
|
||||
PublicKey: keyPair.PublicKey().Serialize(),
|
||||
PrivateKey: bytehelper.ArrayToSlice(keyPair.PrivateKey().Serialize()),
|
||||
Signature: bytehelper.ArrayToSlice64(sig),
|
||||
},
|
||||
keyPair: keyPair,
|
||||
signature: sig,
|
||||
serializer: serializer,
|
||||
}
|
||||
}
|
||||
|
||||
// SignedPreKeyStructure is a flat structure of a signed pre key, used
|
||||
// for serialization and deserialization.
|
||||
type SignedPreKeyStructure struct {
|
||||
ID uint32
|
||||
PublicKey []byte
|
||||
PrivateKey []byte
|
||||
Signature []byte
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
// SignedPreKey record is a structure for storing a signed
|
||||
// pre key in a SignedPreKey store.
|
||||
type SignedPreKey struct {
|
||||
structure SignedPreKeyStructure
|
||||
keyPair *ecc.ECKeyPair
|
||||
signature [64]byte
|
||||
serializer SignedPreKeySerializer
|
||||
}
|
||||
|
||||
// ID returns the record's id.
|
||||
func (s *SignedPreKey) ID() uint32 {
|
||||
return s.structure.ID
|
||||
}
|
||||
|
||||
// Timestamp returns the record's timestamp
|
||||
func (s *SignedPreKey) Timestamp() int64 {
|
||||
return s.structure.Timestamp
|
||||
}
|
||||
|
||||
// KeyPair returns the signed pre key record's key pair.
|
||||
func (s *SignedPreKey) KeyPair() *ecc.ECKeyPair {
|
||||
return s.keyPair
|
||||
}
|
||||
|
||||
// Signature returns the record's signed prekey signature.
|
||||
func (s *SignedPreKey) Signature() [64]byte {
|
||||
return s.signature
|
||||
}
|
||||
|
||||
// Serialize uses the SignedPreKey serializer to return the SignedPreKey
|
||||
// as serialized bytes.
|
||||
func (s *SignedPreKey) Serialize() []byte {
|
||||
structure := s.structure
|
||||
return s.serializer.Serialize(&structure)
|
||||
}
|
69
vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go
vendored
Normal file
69
vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// NewUnackPreKeyMessageItems returns message items that are unacknowledged.
|
||||
func NewUnackPreKeyMessageItems(preKeyID *optional.Uint32, signedPreKeyID uint32,
|
||||
baseKey ecc.ECPublicKeyable) *UnackPreKeyMessageItems {
|
||||
|
||||
return &UnackPreKeyMessageItems{
|
||||
preKeyID: preKeyID,
|
||||
signedPreKeyID: signedPreKeyID,
|
||||
baseKey: baseKey,
|
||||
}
|
||||
}
|
||||
|
||||
// NewUnackPreKeyMessageItemsFromStruct will return a new unacknowledged prekey
|
||||
// message items object from the given structure.
|
||||
func NewUnackPreKeyMessageItemsFromStruct(structure *UnackPreKeyMessageItemsStructure) *UnackPreKeyMessageItems {
|
||||
baseKey, _ := ecc.DecodePoint(structure.BaseKey, 0)
|
||||
return NewUnackPreKeyMessageItems(
|
||||
structure.PreKeyID,
|
||||
structure.SignedPreKeyID,
|
||||
baseKey,
|
||||
)
|
||||
}
|
||||
|
||||
// UnackPreKeyMessageItemsStructure is a serializable structure for unackowledged
|
||||
// prekey message items.
|
||||
type UnackPreKeyMessageItemsStructure struct {
|
||||
PreKeyID *optional.Uint32
|
||||
SignedPreKeyID uint32
|
||||
BaseKey []byte
|
||||
}
|
||||
|
||||
// UnackPreKeyMessageItems is a structure for messages that have not been
|
||||
// acknowledged.
|
||||
type UnackPreKeyMessageItems struct {
|
||||
preKeyID *optional.Uint32
|
||||
signedPreKeyID uint32
|
||||
baseKey ecc.ECPublicKeyable
|
||||
}
|
||||
|
||||
// PreKeyID returns the prekey id of the unacknowledged message.
|
||||
func (u *UnackPreKeyMessageItems) PreKeyID() *optional.Uint32 {
|
||||
return u.preKeyID
|
||||
}
|
||||
|
||||
// SignedPreKeyID returns the signed prekey id of the unacknowledged message.
|
||||
func (u *UnackPreKeyMessageItems) SignedPreKeyID() uint32 {
|
||||
return u.signedPreKeyID
|
||||
}
|
||||
|
||||
// BaseKey returns the ECC public key of the unacknowledged message.
|
||||
func (u *UnackPreKeyMessageItems) BaseKey() ecc.ECPublicKeyable {
|
||||
return u.baseKey
|
||||
}
|
||||
|
||||
// structure will return a serializable base structure
|
||||
// for unacknowledged prekey message items.
|
||||
func (u *UnackPreKeyMessageItems) structure() *UnackPreKeyMessageItemsStructure {
|
||||
return &UnackPreKeyMessageItemsStructure{
|
||||
PreKeyID: u.preKeyID,
|
||||
SignedPreKeyID: u.signedPreKeyID,
|
||||
BaseKey: u.baseKey.Serialize(),
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user