Documentation
¶
Overview ¶
Package protocol implements the Signal wire message types: the versioned, length-checked binary encodings of SignalMessage, PreKeySignalMessage, and the group/plaintext message forms. It is a pure-Go port of rust/protocol/src/protocol.rs and is wire-compatible with upstream libsignal.
Index ¶
- Constants
- Variables
- type DecryptionErrorMessage
- type PlaintextContent
- type PreKeySignalMessage
- func (m *PreKeySignalMessage) BaseKey() curve.PublicKey
- func (m *PreKeySignalMessage) IdentityKey() curve.PublicKey
- func (m *PreKeySignalMessage) KyberCiphertext() []byte
- func (m *PreKeySignalMessage) KyberPreKeyID() *uint32
- func (m *PreKeySignalMessage) Message() *SignalMessage
- func (m *PreKeySignalMessage) MessageVersion() uint8
- func (m *PreKeySignalMessage) PreKeyID() *uint32
- func (m *PreKeySignalMessage) RegistrationID() uint32
- func (m *PreKeySignalMessage) Serialize() []byte
- func (m *PreKeySignalMessage) SignedPreKeyID() uint32
- type SenderKeyDistributionMessage
- func (m *SenderKeyDistributionMessage) ChainID() uint32
- func (m *SenderKeyDistributionMessage) ChainKey() []byte
- func (m *SenderKeyDistributionMessage) DistributionID() [uuidLen]byte
- func (m *SenderKeyDistributionMessage) Iteration() uint32
- func (m *SenderKeyDistributionMessage) MessageVersion() uint8
- func (m *SenderKeyDistributionMessage) Serialized() []byte
- func (m *SenderKeyDistributionMessage) SigningKey() curve.PublicKey
- type SenderKeyMessage
- func (m *SenderKeyMessage) ChainID() uint32
- func (m *SenderKeyMessage) Ciphertext() []byte
- func (m *SenderKeyMessage) DistributionID() [uuidLen]byte
- func (m *SenderKeyMessage) Iteration() uint32
- func (m *SenderKeyMessage) MessageVersion() uint8
- func (m *SenderKeyMessage) Serialized() []byte
- func (m *SenderKeyMessage) VerifySignature(signatureKey curve.PublicKey) bool
- type SignalMessage
- func (m *SignalMessage) Body() []byte
- func (m *SignalMessage) Counter() uint32
- func (m *SignalMessage) MessageVersion() uint8
- func (m *SignalMessage) PQRatchet() []byte
- func (m *SignalMessage) PreviousCounter() uint32
- func (m *SignalMessage) SenderRatchetKey() curve.PublicKey
- func (m *SignalMessage) Serialize() []byte
- func (m *SignalMessage) VerifyMAC(senderIdentityKey, receiverIdentityKey curve.PublicKey, macKey []byte) (bool, error)
Constants ¶
const ( // CurrentVersion is the current ciphertext message version (PQXDH / v4). CurrentVersion uint8 = 4 // PreKyberVersion is the last version without Kyber keys (v3). Messages at // this version are still accepted on deserialize for backward compatibility. PreKyberVersion uint8 = 3 // SenderKeyCurrentVersion is the current SenderKeyMessage version // (SENDERKEY_MESSAGE_CURRENT_VERSION in protocol.rs). The sender-key message // family versions independently of the Double Ratchet messages. SenderKeyCurrentVersion uint8 = 3 )
Ciphertext message version constants, from rust/protocol/src/protocol.rs.
const ( // MessageTypeWhisper tags a SignalMessage. MessageTypeWhisper uint8 = 2 // MessageTypePreKey tags a PreKeySignalMessage. MessageTypePreKey uint8 = 3 // MessageTypeSenderKey tags a SenderKeyMessage. MessageTypeSenderKey uint8 = 7 // MessageTypePlaintext tags a PlaintextContent message. MessageTypePlaintext uint8 = 8 )
Ciphertext message type tags, from CiphertextMessageType in protocol.rs.
Variables ¶
var ( // ErrCiphertextTooShort is returned when a serialized message is shorter // than its minimum framing (version byte, and for SignalMessage the MAC). ErrCiphertextTooShort = errors.New("protocol: ciphertext message too short") // ErrLegacyVersion is returned when a message declares a version below the // minimum supported version (PreKyberVersion). ErrLegacyVersion = errors.New("protocol: legacy ciphertext version") // ErrUnrecognizedVersion is returned when a message declares a version // above CurrentVersion. ErrUnrecognizedVersion = errors.New("protocol: unrecognized ciphertext version") // ErrInvalidProtobuf is returned when the protobuf body fails to decode or // is missing a required field. ErrInvalidProtobuf = errors.New("protocol: invalid protobuf encoding") // ErrInvalidMACKeyLength is returned when a MAC key is not 32 bytes. ErrInvalidMACKeyLength = errors.New("protocol: invalid MAC key length") // ErrInvalidMessage is returned when a message is structurally valid but // semantically rejected (e.g. a v4 PreKeySignalMessage missing its Kyber // payload). ErrInvalidMessage = errors.New("protocol: invalid message") )
Errors returned by this package. All are sentinel errors matchable with errors.Is; call sites return them either directly or %w-wrapped with context.
Functions ¶
This section is empty.
Types ¶
type DecryptionErrorMessage ¶
type DecryptionErrorMessage struct {
// contains filtered or unexported fields
}
DecryptionErrorMessage reports a failed decryption back to the sender. Its wire form is the bare protobuf encoding (no version byte).
func DeserializeDecryptionErrorMessage ¶
func DeserializeDecryptionErrorMessage(value []byte) (*DecryptionErrorMessage, error)
DeserializeDecryptionErrorMessage parses the protobuf wire form. The timestamp field is required; ratchet_key is optional and device_id defaults to 0.
func NewDecryptionErrorMessage ¶
func NewDecryptionErrorMessage( ratchetKey *curve.PublicKey, timestamp uint64, deviceID uint32, ) (*DecryptionErrorMessage, error)
NewDecryptionErrorMessage builds a DecryptionErrorMessage. ratchetKey is the public ratchet key from the message that failed to decrypt, or nil when the original message type carries none (e.g. a sender-key message).
func (*DecryptionErrorMessage) DeviceID ¶
func (m *DecryptionErrorMessage) DeviceID() uint32
DeviceID returns the original sender device ID.
func (*DecryptionErrorMessage) RatchetKey ¶
func (m *DecryptionErrorMessage) RatchetKey() *curve.PublicKey
RatchetKey returns the ratchet public key, or nil if the message carries none.
func (*DecryptionErrorMessage) Serialized ¶
func (m *DecryptionErrorMessage) Serialized() []byte
Serialized returns the protobuf wire encoding.
func (*DecryptionErrorMessage) Timestamp ¶
func (m *DecryptionErrorMessage) Timestamp() uint64
Timestamp returns the original message timestamp (epoch milliseconds).
type PlaintextContent ¶
type PlaintextContent struct {
// contains filtered or unexported fields
}
PlaintextContent is a message that may be sent without encryption. Its wire form is the identifier byte (0xC0), a Content protobuf body, and a trailing padding-boundary byte (0x80).
func DeserializePlaintextContent ¶
func DeserializePlaintextContent(value []byte) (*PlaintextContent, error)
DeserializePlaintextContent parses the wire form, requiring the leading identifier byte. The body is not further decoded here (it mirrors upstream, which stores the serialized form and exposes the body via Body).
func NewPlaintextContentFromDecryptionError ¶
func NewPlaintextContentFromDecryptionError(message *DecryptionErrorMessage) (*PlaintextContent, error)
NewPlaintextContentFromDecryptionError wraps a DecryptionErrorMessage as PlaintextContent, matching the upstream From<DecryptionErrorMessage> conversion.
func (*PlaintextContent) Body ¶
func (m *PlaintextContent) Body() []byte
Body returns the message contents after the identifier byte.
func (*PlaintextContent) Serialized ¶
func (m *PlaintextContent) Serialized() []byte
Serialized returns the full wire encoding.
type PreKeySignalMessage ¶
type PreKeySignalMessage struct {
// contains filtered or unexported fields
}
PreKeySignalMessage is the initial message of a session, carrying the prekey identifiers and the keys needed to establish the ratchet, wrapping an inner SignalMessage. Its wire form is: version byte ‖ protobuf body (no MAC; the inner SignalMessage carries its own MAC).
func DeserializePreKeySignalMessage ¶
func DeserializePreKeySignalMessage(value []byte) (*PreKeySignalMessage, error)
DeserializePreKeySignalMessage parses and validates the wire form. It checks the version range, decodes the body (requiring base key, identity key, inner message, and signed-prekey id), enforces the Kyber-payload rule (required for versions above PreKyberVersion; both-or-neither otherwise), and recursively parses the inner SignalMessage. Mirrors PreKeySignalMessage::try_from.
func NewPreKeySignalMessage ¶
func NewPreKeySignalMessage( messageVersion uint8, registrationID uint32, preKeyID *uint32, signedPreKeyID uint32, kyberPreKeyID *uint32, kyberCiphertext []byte, baseKey curve.PublicKey, identityKey curve.PublicKey, message *SignalMessage, ) (*PreKeySignalMessage, error)
NewPreKeySignalMessage builds and serializes a PreKeySignalMessage. A Kyber payload (kyberPreKeyID + kyberCiphertext) is required for v4 sessions; pass a nil preKeyID when there is no one-time prekey. The message is the inner SignalMessage. Mirrors PreKeySignalMessage::new.
func (*PreKeySignalMessage) BaseKey ¶
func (m *PreKeySignalMessage) BaseKey() curve.PublicKey
BaseKey returns the sender's base public key.
func (*PreKeySignalMessage) IdentityKey ¶
func (m *PreKeySignalMessage) IdentityKey() curve.PublicKey
IdentityKey returns the sender's identity public key.
func (*PreKeySignalMessage) KyberCiphertext ¶
func (m *PreKeySignalMessage) KyberCiphertext() []byte
KyberCiphertext returns the Kyber ciphertext, or nil if no Kyber payload.
func (*PreKeySignalMessage) KyberPreKeyID ¶
func (m *PreKeySignalMessage) KyberPreKeyID() *uint32
KyberPreKeyID returns the Kyber prekey id, or nil if no Kyber payload.
func (*PreKeySignalMessage) Message ¶
func (m *PreKeySignalMessage) Message() *SignalMessage
Message returns the inner SignalMessage.
func (*PreKeySignalMessage) MessageVersion ¶
func (m *PreKeySignalMessage) MessageVersion() uint8
MessageVersion returns the message's protocol version.
func (*PreKeySignalMessage) PreKeyID ¶
func (m *PreKeySignalMessage) PreKeyID() *uint32
PreKeyID returns the one-time prekey id, or nil if the message used none.
func (*PreKeySignalMessage) RegistrationID ¶
func (m *PreKeySignalMessage) RegistrationID() uint32
RegistrationID returns the sender's registration id.
func (*PreKeySignalMessage) Serialize ¶
func (m *PreKeySignalMessage) Serialize() []byte
Serialize returns the full wire form (version byte ‖ body).
func (*PreKeySignalMessage) SignedPreKeyID ¶
func (m *PreKeySignalMessage) SignedPreKeyID() uint32
SignedPreKeyID returns the signed prekey id.
type SenderKeyDistributionMessage ¶
type SenderKeyDistributionMessage struct {
// contains filtered or unexported fields
}
SenderKeyDistributionMessage announces a sender-key chain to group members. Its wire form is a version byte followed by the protobuf body; it carries no signature.
func DeserializeSenderKeyDistributionMessage ¶
func DeserializeSenderKeyDistributionMessage(value []byte) (*SenderKeyDistributionMessage, error)
DeserializeSenderKeyDistributionMessage parses the wire form of a SenderKeyDistributionMessage.
func NewSenderKeyDistributionMessage ¶
func NewSenderKeyDistributionMessage( distributionID [uuidLen]byte, chainID uint32, iteration uint32, chainKey []byte, signingKey curve.PublicKey, ) (*SenderKeyDistributionMessage, error)
NewSenderKeyDistributionMessage builds a SenderKeyDistributionMessage.
func (*SenderKeyDistributionMessage) ChainID ¶
func (m *SenderKeyDistributionMessage) ChainID() uint32
ChainID returns the chain ID.
func (*SenderKeyDistributionMessage) ChainKey ¶
func (m *SenderKeyDistributionMessage) ChainKey() []byte
ChainKey returns the chain key.
func (*SenderKeyDistributionMessage) DistributionID ¶
func (m *SenderKeyDistributionMessage) DistributionID() [uuidLen]byte
DistributionID returns the raw 16-byte distribution UUID.
func (*SenderKeyDistributionMessage) Iteration ¶
func (m *SenderKeyDistributionMessage) Iteration() uint32
Iteration returns the iteration.
func (*SenderKeyDistributionMessage) MessageVersion ¶
func (m *SenderKeyDistributionMessage) MessageVersion() uint8
MessageVersion returns the message version.
func (*SenderKeyDistributionMessage) Serialized ¶
func (m *SenderKeyDistributionMessage) Serialized() []byte
Serialized returns the full wire encoding.
func (*SenderKeyDistributionMessage) SigningKey ¶
func (m *SenderKeyDistributionMessage) SigningKey() curve.PublicKey
SigningKey returns the signing public key.
type SenderKeyMessage ¶
type SenderKeyMessage struct {
// contains filtered or unexported fields
}
SenderKeyMessage is a group (sender-key) ciphertext message. Its wire form is a version byte, the protobuf body, and a trailing 64-byte XEdDSA signature computed over the version byte and body.
func DeserializeSenderKeyMessage ¶
func DeserializeSenderKeyMessage(value []byte) (*SenderKeyMessage, error)
DeserializeSenderKeyMessage parses the wire form of a SenderKeyMessage, validating the version and protobuf body. It does not verify the signature; call VerifySignature for that.
func NewSenderKeyMessage ¶
func NewSenderKeyMessage( distributionID [uuidLen]byte, chainID uint32, iteration uint32, ciphertext []byte, rng io.Reader, signatureKey curve.PrivateKey, ) (*SenderKeyMessage, error)
NewSenderKeyMessage builds and signs a SenderKeyMessage. The signature is an XEdDSA signature over the version byte and protobuf body, using signatureKey; rng supplies the signature nonce (use crypto/rand.Reader in production).
func (*SenderKeyMessage) ChainID ¶
func (m *SenderKeyMessage) ChainID() uint32
ChainID returns the chain ID.
func (*SenderKeyMessage) Ciphertext ¶
func (m *SenderKeyMessage) Ciphertext() []byte
Ciphertext returns the ciphertext body.
func (*SenderKeyMessage) DistributionID ¶
func (m *SenderKeyMessage) DistributionID() [uuidLen]byte
DistributionID returns the raw 16-byte distribution UUID.
func (*SenderKeyMessage) Iteration ¶
func (m *SenderKeyMessage) Iteration() uint32
Iteration returns the iteration.
func (*SenderKeyMessage) MessageVersion ¶
func (m *SenderKeyMessage) MessageVersion() uint8
MessageVersion returns the message version.
func (*SenderKeyMessage) Serialized ¶
func (m *SenderKeyMessage) Serialized() []byte
Serialized returns the full wire encoding.
func (*SenderKeyMessage) VerifySignature ¶
func (m *SenderKeyMessage) VerifySignature(signatureKey curve.PublicKey) bool
VerifySignature reports whether the message's trailing signature is valid under signatureKey, computed over the version byte and protobuf body.
type SignalMessage ¶
type SignalMessage struct {
// contains filtered or unexported fields
}
SignalMessage is the Double Ratchet ciphertext message ("Whisper" message). Its wire form is: version byte ‖ protobuf body ‖ HMAC-SHA256 tag[:8].
func DeserializeSignalMessage ¶
func DeserializeSignalMessage(value []byte) (*SignalMessage, error)
DeserializeSignalMessage parses and validates the wire form of a SignalMessage. It checks the minimum length, the version range, and decodes the protobuf body, requiring the ratchet key, counter, and ciphertext fields. It does not verify the MAC; call VerifyMAC for that.
func NewSignalMessage ¶
func NewSignalMessage( messageVersion uint8, macKey []byte, senderRatchetKey curve.PublicKey, counter uint32, previousCounter uint32, ciphertext []byte, senderIdentityKey curve.PublicKey, receiverIdentityKey curve.PublicKey, pqRatchet []byte, addresses []byte, ) (*SignalMessage, error)
NewSignalMessage builds and serializes a SignalMessage, computing the MAC over the sender/receiver identity public keys and the versioned body, exactly as SignalMessage::new in protocol.rs. macKey must be 32 bytes. pqRatchet may be nil/empty (it is then omitted from the proto, matching upstream). addresses may be nil.
func (*SignalMessage) Body ¶
func (m *SignalMessage) Body() []byte
Body returns the inner ciphertext.
func (*SignalMessage) Counter ¶
func (m *SignalMessage) Counter() uint32
Counter returns the message counter.
func (*SignalMessage) MessageVersion ¶
func (m *SignalMessage) MessageVersion() uint8
MessageVersion returns the message's protocol version.
func (*SignalMessage) PQRatchet ¶
func (m *SignalMessage) PQRatchet() []byte
PQRatchet returns the opaque SPQR state bytes (empty when absent).
func (*SignalMessage) PreviousCounter ¶
func (m *SignalMessage) PreviousCounter() uint32
PreviousCounter returns the previous-chain counter.
func (*SignalMessage) SenderRatchetKey ¶
func (m *SignalMessage) SenderRatchetKey() curve.PublicKey
SenderRatchetKey returns the sender's ratchet public key.
func (*SignalMessage) Serialize ¶
func (m *SignalMessage) Serialize() []byte
Serialize returns the full wire form (version byte ‖ body ‖ MAC).
func (*SignalMessage) VerifyMAC ¶
func (m *SignalMessage) VerifyMAC(senderIdentityKey, receiverIdentityKey curve.PublicKey, macKey []byte) (bool, error)
VerifyMAC recomputes the message's MAC from the identity keys and mac key and compares it (in constant time) against the trailing tag. It returns false on mismatch and an error only for a malformed mac key. Mirrors SignalMessage::verify_mac.