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
|
package protocol
import (
"fmt"
"go.mau.fi/libsignal/ecc"
"go.mau.fi/libsignal/keys/identity"
"go.mau.fi/libsignal/signalerror"
"go.mau.fi/libsignal/util/optional"
)
// PreKeySignalMessageSerializer is an interface for serializing and deserializing
// PreKeySignalMessages into bytes. An implementation of this interface should be
// used to encode/decode the object into JSON, Protobuffers, etc.
type PreKeySignalMessageSerializer interface {
Serialize(signalMessage *PreKeySignalMessageStructure) []byte
Deserialize(serialized []byte) (*PreKeySignalMessageStructure, error)
}
// NewPreKeySignalMessageFromBytes will return a Signal Ciphertext message from the given
// bytes using the given serializer.
func NewPreKeySignalMessageFromBytes(serialized []byte, serializer PreKeySignalMessageSerializer,
msgSerializer SignalMessageSerializer) (*PreKeySignalMessage, error) {
// Use the given serializer to decode the signal message.
signalMessageStructure, err := serializer.Deserialize(serialized)
if err != nil {
return nil, err
}
return NewPreKeySignalMessageFromStruct(signalMessageStructure, serializer, msgSerializer)
}
// NewPreKeySignalMessageFromStruct will return a new PreKeySignalMessage from the given
// PreKeySignalMessageStructure.
func NewPreKeySignalMessageFromStruct(structure *PreKeySignalMessageStructure,
serializer PreKeySignalMessageSerializer, msgSerializer SignalMessageSerializer) (*PreKeySignalMessage, error) {
// Throw an error if the given message structure is an unsupported version.
if structure.Version <= UnsupportedVersion {
return nil, fmt.Errorf("%w %d (prekey message)", signalerror.ErrOldMessageVersion, structure.Version)
}
// Throw an error if the given message structure is a future version.
if structure.Version > CurrentVersion {
return nil, fmt.Errorf("%w %d (prekey message)", signalerror.ErrUnknownMessageVersion, structure.Version)
}
// Throw an error if the structure is missing critical fields.
if structure.BaseKey == nil || structure.IdentityKey == nil || structure.Message == nil {
return nil, fmt.Errorf("%w (prekey message)", signalerror.ErrIncompleteMessage)
}
// Create the signal message object from the structure.
preKeyWhisperMessage := &PreKeySignalMessage{structure: *structure, serializer: serializer}
// Generate the base ECC key from bytes.
var err error
preKeyWhisperMessage.baseKey, err = ecc.DecodePoint(structure.BaseKey, 0)
if err != nil {
return nil, err
}
// Generate the identity key from bytes
var identityKey ecc.ECPublicKeyable
identityKey, err = ecc.DecodePoint(structure.IdentityKey, 0)
if err != nil {
return nil, err
}
preKeyWhisperMessage.identityKey = identity.NewKey(identityKey)
// Generate the SignalMessage object from bytes.
preKeyWhisperMessage.message, err = NewSignalMessageFromBytes(structure.Message, msgSerializer)
if err != nil {
return nil, err
}
return preKeyWhisperMessage, nil
}
// NewPreKeySignalMessage will return a new PreKeySignalMessage object.
func NewPreKeySignalMessage(version int, registrationID uint32, preKeyID *optional.Uint32, signedPreKeyID uint32,
baseKey ecc.ECPublicKeyable, identityKey *identity.Key, message *SignalMessage, serializer PreKeySignalMessageSerializer,
msgSerializer SignalMessageSerializer) (*PreKeySignalMessage, error) {
structure := &PreKeySignalMessageStructure{
Version: version,
RegistrationID: registrationID,
PreKeyID: preKeyID,
SignedPreKeyID: signedPreKeyID,
BaseKey: baseKey.Serialize(),
IdentityKey: identityKey.PublicKey().Serialize(),
Message: message.Serialize(),
}
return NewPreKeySignalMessageFromStruct(structure, serializer, msgSerializer)
}
// PreKeySignalMessageStructure is a serializable structure for
// PreKeySignalMessages.
type PreKeySignalMessageStructure struct {
RegistrationID uint32
PreKeyID *optional.Uint32
SignedPreKeyID uint32
BaseKey []byte
IdentityKey []byte
Message []byte
Version int
}
// PreKeySignalMessage is an encrypted Signal message that is designed
// to be used when building a session with someone for the first time.
type PreKeySignalMessage struct {
structure PreKeySignalMessageStructure
baseKey ecc.ECPublicKeyable
identityKey *identity.Key
message *SignalMessage
serializer PreKeySignalMessageSerializer
}
func (p *PreKeySignalMessage) MessageVersion() int {
return p.structure.Version
}
func (p *PreKeySignalMessage) IdentityKey() *identity.Key {
return p.identityKey
}
func (p *PreKeySignalMessage) RegistrationID() uint32 {
return p.structure.RegistrationID
}
func (p *PreKeySignalMessage) PreKeyID() *optional.Uint32 {
return p.structure.PreKeyID
}
func (p *PreKeySignalMessage) SignedPreKeyID() uint32 {
return p.structure.SignedPreKeyID
}
func (p *PreKeySignalMessage) BaseKey() ecc.ECPublicKeyable {
return p.baseKey
}
func (p *PreKeySignalMessage) WhisperMessage() *SignalMessage {
return p.message
}
func (p *PreKeySignalMessage) Serialize() []byte {
return p.serializer.Serialize(&p.structure)
}
func (p *PreKeySignalMessage) Type() uint32 {
return PREKEY_TYPE
}
|