message

package
v0.1.0-preview.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

Documentation

Overview

Package message defines authenticated application messages and client delivery receipts. These objects must be encrypted inside an audited ratchet; they are not a replacement for a ratchet or metadata-private transport.

Index

Constants

View Source
const (
	Version               = 1
	MaxBodyBytes          = 192 * 1024
	MaxSignedMessageBytes = 300 * 1024
	MaxReceiptBytes       = 64 * 1024
)
View Source
const MaxRatchetSkippedKeys = 2048

Variables

View Source
var (
	ErrRatchetProviderRequired          = errors.New("audited PQXDH/Double-or-Triple-Ratchet provider required")
	ErrMetadataPrivateTransportRequired = errors.New("metadata-private mix transport with cover traffic required")
	ErrReplayStoreRequired              = errors.New("persistent atomic message replay store required")
)

Functions

func Digest

func Digest(message SignedMessage) ([]byte, error)

func Encode

func Encode(message SignedMessage) ([]byte, error)

func EncodeDeliveryReceipt

func EncodeDeliveryReceipt(receipt DeliveryReceipt) ([]byte, error)

func VerifyDeliveryReceipt

func VerifyDeliveryReceipt(receiverProfile account.PublicProfile, receipt DeliveryReceipt, original SignedMessage, now time.Time) error

Types

type DeliveryReceipt

type DeliveryReceipt struct {
	Version                 uint8                     `json:"version"`
	MessageID               string                    `json:"message_id"`
	MessageDigest           []byte                    `json:"message_digest"`
	SenderID                string                    `json:"sender_id"`
	RecipientID             string                    `json:"recipient_id"`
	ReceiverProfileRevision uint64                    `json:"receiver_profile_revision"`
	ReceiverDevice          account.DeviceCertificate `json:"receiver_device"`
	ReceivedAt              time.Time                 `json:"received_at"`
	Signature               protocol.HybridSignature  `json:"signature"`
}

DeliveryReceipt proves that a certified recipient device accepted and authenticated a specific message. It must itself travel inside the ratchet. A storage receipt from a node is not a DeliveryReceipt.

func DecodeDeliveryReceipt

func DecodeDeliveryReceipt(encoded []byte) (DeliveryReceipt, error)

func NewDeliveryReceipt

func NewDeliveryReceipt(receiver *account.LocalAccount, verified VerifiedMessage, now time.Time) (DeliveryReceipt, error)

type PrivateTransport

type PrivateTransport interface {
	Security() TransportSecurity
	Send(ctx context.Context, item RoutedCiphertext) error
}

PrivateTransport only receives one-time route capabilities and already encrypted, padded payloads. Send must return nil only after validating the transport's authenticated storage acknowledgement.

type RatchetProvider

type RatchetProvider interface {
	Security() RatchetSecurity
	Encrypt(ctx context.Context, peerID, peerDeviceID string, plaintext []byte, expiresAt time.Time) (RoutedCiphertext, error)
	Decrypt(ctx context.Context, item RoutedCiphertext) ([]byte, error)
}

RatchetProvider is a narrow boundary for an audited implementation. The provider owns session state, prekeys, skipped-key limits, key deletion, and replay handling at the cryptographic layer. Propagare does not implement a custom ratchet behind this interface.

type RatchetSecurity

type RatchetSecurity struct {
	Protocol               string
	IndependentAudit       string
	ForwardSecrecy         bool
	PostCompromiseSecurity bool
	PostQuantumHandshake   bool
	UniquePerMessageKeys   bool
	DeletesConsumedKeys    bool
	MaxSkippedMessageKeys  int
}

type ReplayStore

type ReplayStore interface {
	Accept(ctx context.Context, senderID, messageID string, expiresAt time.Time) error
}

ReplayStore must atomically reject an already accepted (senderID,messageID) pair and persist entries at least until expiresAt.

type RoutedCiphertext

type RoutedCiphertext struct {
	RouteTag  string
	Payload   []byte
	ExpiresAt time.Time
}

type SignedMessage

type SignedMessage struct {
	Version               uint8                     `json:"version"`
	Kind                  string                    `json:"kind"`
	MessageID             string                    `json:"message_id"`
	SenderID              string                    `json:"sender_id"`
	RecipientID           string                    `json:"recipient_id"`
	SenderProfileRevision uint64                    `json:"sender_profile_revision"`
	SenderDevice          account.DeviceCertificate `json:"sender_device"`
	CreatedAt             time.Time                 `json:"created_at"`
	ExpiresAt             time.Time                 `json:"expires_at"`
	Body                  []byte                    `json:"body"`
	Signature             protocol.HybridSignature  `json:"signature"`
}

func Decode

func Decode(encoded []byte) (SignedMessage, error)

func NewDirect

func NewDirect(sender *account.LocalAccount, recipientID string, body []byte, now time.Time, retention time.Duration) (SignedMessage, error)

NewDirect binds an application-level expiry into the signed message. This expiry travels only inside the end-to-end encrypted envelope and is never visible to nodes; node-side item storage always uses the fixed protocol retention window. It may not exceed that window.

type StrictPipeline

type StrictPipeline struct {
	// contains filtered or unexported fields
}

func NewStrictPipeline

func NewStrictPipeline(ratchet RatchetProvider, transport PrivateTransport, replays ReplayStore) (*StrictPipeline, error)

func (*StrictPipeline) OpenDirect

func (pipeline *StrictPipeline) OpenDirect(ctx context.Context, local *account.LocalAccount, sender account.PublicProfile, item RoutedCiphertext, now time.Time) (VerifiedMessage, error)

OpenDirect only returns an authenticated message after ratchet decryption, ENIG/profile validation, device-signature validation, and atomic replay rejection all succeed.

func (*StrictPipeline) SendDirect

func (pipeline *StrictPipeline) SendDirect(ctx context.Context, sender *account.LocalAccount, recipient account.PublicProfile, body []byte, now time.Time, retention time.Duration) (SignedMessage, []RoutedCiphertext, error)

SendDirect signs once and creates an independent ratchet ciphertext for every certified recipient device. The signed sender and recipient IDs remain inside the ratchet ciphertext and are never passed to the transport.

type TransportSecurity

type TransportSecurity struct {
	Protocol                    string
	IndependentAudit            string
	MixLayers                   int
	SenderReceiverUnlinkability bool
	CoverTraffic                bool
	ConstantRate                bool
	Batching                    bool
	AnonymousFetch              bool
	FixedSizePackets            bool
}

type VerifiedMessage

type VerifiedMessage struct {
	// contains filtered or unexported fields
}

func VerifyDirect

func VerifyDirect(senderProfile account.PublicProfile, message SignedMessage, expectedRecipient string, now time.Time) (VerifiedMessage, error)

func (VerifiedMessage) Message

func (verified VerifiedMessage) Message() SignedMessage

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL