1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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,
}
}
|