forked from tulir/libsignal-protocol-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SenderKeyState.go
186 lines (157 loc) · 6.19 KB
/
SenderKeyState.go
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package record
import (
"github.com/UristLikot/libsignal/ecc"
"github.com/UristLikot/libsignal/groups/ratchet"
"github.com/UristLikot/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
}