summaryrefslogtreecommitdiffstats
path: root/vendor/go.mau.fi/libsignal/protocol/PreKeySignalMessage.go
blob: 841d9d176280b78a3612d76e42dd2caebccadb76 (plain) (blame)
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
}