169 lines
5.1 KiB
Go
169 lines
5.1 KiB
Go
|
package protocol
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"go.mau.fi/libsignal/ecc"
|
||
|
"go.mau.fi/libsignal/signalerror"
|
||
|
"go.mau.fi/libsignal/util/bytehelper"
|
||
|
)
|
||
|
|
||
|
// SenderKeyMessageSerializer is an interface for serializing and deserializing
|
||
|
// SenderKeyMessages into bytes. An implementation of this interface should be
|
||
|
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||
|
type SenderKeyMessageSerializer interface {
|
||
|
Serialize(signalMessage *SenderKeyMessageStructure) []byte
|
||
|
Deserialize(serialized []byte) (*SenderKeyMessageStructure, error)
|
||
|
}
|
||
|
|
||
|
// NewSenderKeyMessageFromBytes will return a Signal Ciphertext message from the given
|
||
|
// bytes using the given serializer.
|
||
|
func NewSenderKeyMessageFromBytes(serialized []byte,
|
||
|
serializer SenderKeyMessageSerializer) (*SenderKeyMessage, error) {
|
||
|
|
||
|
// Use the given serializer to decode the signal message.
|
||
|
senderKeyMessageStructure, err := serializer.Deserialize(serialized)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return NewSenderKeyMessageFromStruct(senderKeyMessageStructure, serializer)
|
||
|
}
|
||
|
|
||
|
// NewSenderKeyMessageFromStruct returns a Signal Ciphertext message from the
|
||
|
// given serializable structure.
|
||
|
func NewSenderKeyMessageFromStruct(structure *SenderKeyMessageStructure,
|
||
|
serializer SenderKeyMessageSerializer) (*SenderKeyMessage, error) {
|
||
|
|
||
|
// Throw an error if the given message structure is an unsupported version.
|
||
|
if structure.Version <= UnsupportedVersion {
|
||
|
return nil, fmt.Errorf("%w %d (sender key 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 (sender key message)", signalerror.ErrUnknownMessageVersion, structure.Version)
|
||
|
}
|
||
|
|
||
|
// Throw an error if the structure is missing critical fields.
|
||
|
if structure.CipherText == nil {
|
||
|
return nil, fmt.Errorf("%w (sender key message)", signalerror.ErrIncompleteMessage)
|
||
|
}
|
||
|
|
||
|
// Create the signal message object from the structure.
|
||
|
whisperMessage := &SenderKeyMessage{
|
||
|
keyID: structure.ID,
|
||
|
version: structure.Version,
|
||
|
iteration: structure.Iteration,
|
||
|
ciphertext: structure.CipherText,
|
||
|
signature: structure.Signature,
|
||
|
serializer: serializer,
|
||
|
}
|
||
|
|
||
|
return whisperMessage, nil
|
||
|
}
|
||
|
|
||
|
// NewSenderKeyMessage returns a SenderKeyMessage.
|
||
|
func NewSenderKeyMessage(keyID uint32, iteration uint32, ciphertext []byte,
|
||
|
signatureKey ecc.ECPrivateKeyable, serializer SenderKeyMessageSerializer) *SenderKeyMessage {
|
||
|
|
||
|
// Ensure we have a valid signature key
|
||
|
if signatureKey == nil {
|
||
|
panic("Signature is nil. Unable to sign new senderkey message.")
|
||
|
}
|
||
|
|
||
|
// Build our SenderKeyMessage.
|
||
|
senderKeyMessage := &SenderKeyMessage{
|
||
|
keyID: keyID,
|
||
|
iteration: iteration,
|
||
|
ciphertext: ciphertext,
|
||
|
version: CurrentVersion,
|
||
|
serializer: serializer,
|
||
|
}
|
||
|
|
||
|
// Sign the serialized message and include it in the message. This will be included
|
||
|
// in the signed serialized version of the message.
|
||
|
signature := ecc.CalculateSignature(signatureKey, senderKeyMessage.Serialize())
|
||
|
senderKeyMessage.signature = bytehelper.ArrayToSlice64(signature)
|
||
|
|
||
|
return senderKeyMessage
|
||
|
}
|
||
|
|
||
|
// SenderKeyMessageStructure is a serializeable structure for SenderKey messages.
|
||
|
type SenderKeyMessageStructure struct {
|
||
|
ID uint32
|
||
|
Iteration uint32
|
||
|
CipherText []byte
|
||
|
Version uint32
|
||
|
Signature []byte
|
||
|
}
|
||
|
|
||
|
// SenderKeyMessage is a structure for messages using senderkey groups.
|
||
|
type SenderKeyMessage struct {
|
||
|
version uint32
|
||
|
keyID uint32
|
||
|
iteration uint32
|
||
|
ciphertext []byte
|
||
|
signature []byte
|
||
|
serializer SenderKeyMessageSerializer
|
||
|
}
|
||
|
|
||
|
// KeyID returns the SenderKeyMessage key ID.
|
||
|
func (p *SenderKeyMessage) KeyID() uint32 {
|
||
|
return p.keyID
|
||
|
}
|
||
|
|
||
|
// Iteration returns the SenderKeyMessage iteration.
|
||
|
func (p *SenderKeyMessage) Iteration() uint32 {
|
||
|
return p.iteration
|
||
|
}
|
||
|
|
||
|
// Ciphertext returns the SenderKeyMessage encrypted ciphertext.
|
||
|
func (p *SenderKeyMessage) Ciphertext() []byte {
|
||
|
return p.ciphertext
|
||
|
}
|
||
|
|
||
|
// Version returns the Signal message version of the message.
|
||
|
func (p *SenderKeyMessage) Version() uint32 {
|
||
|
return p.version
|
||
|
}
|
||
|
|
||
|
// Serialize will use the given serializer to return the message as bytes
|
||
|
// excluding the signature. This should be used for signing and verifying
|
||
|
// message signatures.
|
||
|
func (p *SenderKeyMessage) Serialize() []byte {
|
||
|
structure := &SenderKeyMessageStructure{
|
||
|
ID: p.keyID,
|
||
|
Iteration: p.iteration,
|
||
|
CipherText: p.ciphertext,
|
||
|
Version: p.version,
|
||
|
}
|
||
|
|
||
|
return p.serializer.Serialize(structure)
|
||
|
}
|
||
|
|
||
|
// SignedSerialize will use the given serializer to return the message as
|
||
|
// bytes with the message signature included. This should be used when
|
||
|
// sending the message over the network.
|
||
|
func (p *SenderKeyMessage) SignedSerialize() []byte {
|
||
|
structure := &SenderKeyMessageStructure{
|
||
|
ID: p.keyID,
|
||
|
Iteration: p.iteration,
|
||
|
CipherText: p.ciphertext,
|
||
|
Version: p.version,
|
||
|
Signature: p.signature,
|
||
|
}
|
||
|
|
||
|
return p.serializer.Serialize(structure)
|
||
|
}
|
||
|
|
||
|
// Signature returns the SenderKeyMessage signature
|
||
|
func (p *SenderKeyMessage) Signature() [64]byte {
|
||
|
return bytehelper.SliceToArray64(p.signature)
|
||
|
}
|
||
|
|
||
|
// Type returns the sender key type.
|
||
|
func (p *SenderKeyMessage) Type() uint32 {
|
||
|
return SENDERKEY_TYPE
|
||
|
}
|