engine

package
v0.3.8 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: BSD-3-Clause Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CapabilityOneToOneContacts    = "one_to_one_contacts"
	CapabilityGroupsV2            = "groups_v2"
	CapabilityWebRTCContinuousICE = "webrtc_continuous_ice"
)

Capability name constants (reference ObvCapability, exact lowercase snake_case literals — wire-exact).

View Source
const (
	CapMsgOwnToContact = 3 // OwnCapabilitiesToContactMessage: [rawCaps[], isResponse]
	CapMsgOwnToSelf    = 4 // OwnCapabilitiesToSelfMessage:    [rawCaps[], isResponse]
)

Device-capabilities protocol message ids (reference DeviceCapabilitiesDiscoveryProtocol). Only 3 and 4 travel on a channel; 0/1/2 are reference-internal local triggers we don't need.

View Source
const (
	ContactMgmtMsgDeletionNotification   = 1 // to the contact:  "I removed you" (empty payload)
	ContactMgmtMsgPropagateDeletion      = 2 // to own devices:  contact identity
	ContactMgmtMsgDowngradeNotification  = 4 // to the contact:  "I downgraded you" (empty payload)
	ContactMgmtMsgPropagateDowngrade     = 5 // to own devices:  contact identity
	ContactMgmtMsgPerformDeviceDiscovery = 6 // from a contact:  "re-discover my devices" (empty payload)
)

Contact-management message ids (reference ContactManagementProtocol).

View Source
const (
	GroupV2MsgInvitationOrMembersUpdate           = 4
	GroupV2MsgInvitationOrMembersUpdateBroadcast  = 5
	GroupV2MsgInvitationOrMembersUpdatePropagated = 6
	GroupV2MsgPing                                = 11
)

Groups v2 protocol message ids (reference GroupsV2Protocol.*_MESSAGE_ID). The invitation/members-update carrying the blob keys to a member comes in three transport variants, distinguished only by the message id (their payload differs only in the trailing fields):

  • id 4 (Oblivious): sent over a confirmed oblivious channel; carries the notified device UIDs.
  • id 5 (Broadcast): sent over an asymmetric (public-key) channel to a member we have NO oblivious channel with — so a freshly-added member receives the invitation immediately, without waiting for a channel to be established. Omits the device-UID list.
  • id 6 (Propagated): sent to our own other devices; may name the inviter.

A sender picks id 4 when it holds a channel to the member and id 5 (broadcast) otherwise; see client.Session.DeliverGroupInvitation, which encapsulates that choice.

View Source
const (
	GroupPermissionAdmin                 = "ga" // update the group blob
	GroupPermissionRemoteDeleteAnything  = "rd" // remote-delete anyone's messages
	GroupPermissionEditOrRemoteDeleteOwn = "eo" // edit/remote-delete own messages
	GroupPermissionChangeSettings        = "cs" // change shared (ephemeral) settings
	GroupPermissionSendMessage           = "sm" // post messages in the group
)

Group member permission strings (spec §34, "Group member permissions").

View Source
const (
	GroupCategoryServer   int64 = 0
	GroupCategoryKeycloak int64 = 1
)

Group identifier categories (spec §34, GroupV2.Identifier).

View Source
const (
	GroupInvitationNonceLength = 16
	GroupLockNonceLength       = 32
)

Lengths (spec datatypes/Constants).

View Source
const (
	IdentityDetailsMsgInitial        = 0 // local trigger (we don't use the state machine form)
	IdentityDetailsMsgServerPutPhoto = 1 // photo upload (unused: no photo support)
	IdentityDetailsMsgSendDetails    = 2 // to a contact: here are my new published details
	IdentityDetailsMsgPropagateOwn   = 3 // to our own other devices: here are our new details
)

Message IDs of the identity-details-publication protocol.

View Source
const (
	IntroMsgInitial            = 0 // local trigger (mediator); we expose IntroduceContacts instead
	IntroMsgMediatorInvitation = 1 // mediator → invitee: here is someone to connect with
	IntroMsgDialogAccept       = 2 // (unused) UI dialog response
	IntroMsgPropagateConfirm   = 3 // (unused) propagate accept/reject to own devices
	IntroMsgNotifyAccepted     = 4 // invitee → the other: my devices + signature over the triple
	IntroMsgPropagateNotify    = 5 // (unused) propagate the notification to own devices
	IntroMsgAck                = 6 // the other → invitee: trust established on my side
	IntroMsgTrustLevelIncrease = 7 // (unused) local re-evaluation trigger
)

Message IDs of the contact-mutual-introduction protocol.

View Source
const (
	ReturnReceiptStatusDelivered = 1
	ReturnReceiptStatusRead      = 2
)

Return-receipt statuses (spec §50.6).

View Source
const (
	ProtocolDeviceDiscovery              = 0
	ProtocolChannelCreation              = 2
	ProtocolDeviceDiscoveryChild         = 3
	ProtocolContactMutual                = 4
	ProtocolIdentityDetailPublication    = 6
	ProtocolContactPictureDownloadChild  = 7
	ProtocolGroupInvitation              = 8
	ProtocolGroupManagement              = 9
	ProtocolContactManagement            = 10
	ProtocolTrustEstablishmentSAS        = 11
	ProtocolTrustEstablishmentMutualScan = 12
	ProtocolFullRatchet                  = 13
	ProtocolGroupPictureDownloadChild    = 14
	ProtocolDeviceCapabilitiesDiscovery  = 16
	ProtocolGroupsV2                     = 18
	ProtocolOwnedIdentityDeletion        = 20
	ProtocolOwnedDeviceDiscovery         = 21
	ProtocolChannelCreationWithOwned     = 22
	ProtocolSynchronization              = 25
)
View Source
const (
	SyncMsgInitiateSingleItem = 0 // local trigger: this device asks itself to broadcast
	SyncMsgSingleItem         = 1 // over channel: broadcast an atom to other owned devices
	SyncMsgSnapshot           = 2 // over channel: a full profile snapshot for reconciliation
)

Synchronization protocol message ids (ref SynchronizationProtocol).

View Source
const (
	MessageTypeProtocol    = 0
	MessageTypeApplication = 1
)

Message types (spec §22, Olvid MessageType).

View Source
const (
	SettingAutoJoinGroups          = "auto_join_groups"
	SettingSendReadReceipt         = "send_read_receipt"
	SettingUnarchiveOnNotification = "unarchive_on_notification"
)
View Source
const (
	SyncContactNicknameChange          = 0
	SyncGroupV1NicknameChange          = 1
	SyncGroupV2NicknameChange          = 2
	SyncContactPersonalNoteChange      = 3
	SyncGroupV1PersonalNoteChange      = 4
	SyncGroupV2PersonalNoteChange      = 5
	SyncOwnProfileNicknameChange       = 6
	SyncContactCustomHueChange         = 7
	SyncContactSendReadReceiptChange   = 8
	SyncGroupV1SendReadReceiptChange   = 9
	SyncGroupV2SendReadReceiptChange   = 10
	SyncPinnedDiscussionsChange        = 11 // deferred: needs DiscussionIdentifier sub-encoding
	SyncTrustContactDetails            = 12 // identity-level (see IsAppSyncItem)
	SyncTrustGroupV1Details            = 13 // identity-level
	SyncTrustGroupV2Details            = 14 // identity-level
	SyncSettingDefaultSendReadReceipts = 15
	SyncSettingAutoJoinGroups          = 16
	SyncBookmarkedMessageChange        = 17 // deferred: needs MessageIdentifier sub-encoding
	SyncArchivedDiscussionsChange      = 18 // deferred: needs DiscussionIdentifier sub-encoding
	SyncDiscussionsMuteChange          = 19 // deferred: needs MuteNotification sub-encoding
	SyncSettingUnarchiveOnNotification = 20
	SyncSettingLastRating              = 21
)

Multi-device synchronization sync atoms (ref ObvSyncAtom; see SYNC.md).

A SyncAtom is a self-describing delta of an owned identity's *personal* view of a conversation — a nickname, a note, a per-contact setting — shared between that identity's own devices. It never carries message content. On the wire an atom is the TLV list encodeList(type, field...), matching the Android reference byte-for-byte so a peer device decodes exactly what we encode.

View Source
const BackupJSONVersion = 0
View Source
const BackupSeedLength = 20

BackupSeedLength is the seed length in bytes (160 bits).

View Source
const (
	//ErrEncoding = Error("encoding/decoding error")
	ErrCrypt = Error("encryption error")
)
View Source
const GroupV2MsgInvitationRejectedBroadcast = 16

Groups v2 invitation-rejected / group-left broadcast message id (reference GroupsV2Protocol.INVITATION_REJECTED_BROADCAST_MESSAGE_ID): a member broadcasts it to the other members when they LEAVE a group (or reject an invitation to it). Recipients re-download the blob, whose leave-log consolidation drops the departed member. It carries only the group identifier.

View Source
const GroupV2MsgKick = 13

Groups v2 kick message id (reference GroupsV2Protocol.KICK_MESSAGE_ID).

View Source
const OwnedIdentityDeletionMsgContactDeleted = 1

OwnedIdentityDeletionMsgContactDeleted is the message a deleting identity broadcasts to its contacts (reference CONTACT_OWNED_IDENTITY_WAS_DELETED_MESSAGE_ID): [deletedIdentity, signature].

View Source
const SnapshotTagSettings = "settings"

Variables

Default permission sets used by the "Standard" preset group type (spec §34, GroupV2.Permission.DEFAULT_*).

Functions

func AttachmentSHA256

func AttachmentSHA256(plaintext []byte) []byte

AttachmentSHA256 returns the SHA-256 of an attachment's plaintext, for the metadata's integrity field.

func AttachmentSizing

func AttachmentSizing(plaintextLen int64, dataChunkSize int) (numChunks int, fullChunkCipherLen, totalCipherLen int64)

AttachmentSizing computes, for a plaintext of plaintextLen split into dataChunkSize pieces, the number of chunks, the encrypted length of a full chunk, and the total encrypted length. It is deterministic, so a streaming sender can declare an attachment's size to the server without buffering it.

func AuthenticationCheck

func AuthenticationCheck(response, challenge, prefix []byte, pk *PublicKeyOverEC) bool

AuthenticationCheck verifies a challenge response (spec §15, AuthenticationOverEC.check).

func AuthenticationSolve

func AuthenticationSolve(sk *PrivateKeyOverEC, challenge, prefix []byte, pk *PublicKeyOverEC, rnd prng.PRNG) (response []byte, err error)

AuthenticationSolve produces a response to a challenge (spec §15, AuthenticationOverEC.solve):

suffix   <- prng.bytes(16)
response <- suffix || sign(sk_sig, prefix||challenge||suffix, pk_sig, prng)

func ComputeChannelSeed

func ComputeChannelSeed(k1, k2 *AuthEncKey) ([]byte, error)

ComputeChannelSeed derives the shared oblivious-channel seed from the two KEM-exchanged keys k1 and k2 (spec §26). It is Seed.of(k1, k2).

func ComputeDoubleSAS

func ComputeDoubleSAS(seedAlice, seedBob, identity []byte, numberOfDigits int) ([]byte, error)

computeDoubleSAS implements SAS.computeDouble (spec §25), byte-exact with the reference. ComputeDoubleSAS is the byte-exact Olvid double-SAS derivation (reference crypto/SAS.computeDouble): SHA256(identity ‖ seedAlice) XOR seedBob → PRNG_HMAC_SHA256 → bigInt in [10^2n, 2·10^2n) whose leading digit is dropped, yielding 2·numberOfDigits digits. The first numberOfDigits are one party's SAS, the last numberOfDigits the other's. It underpins both Trust Establishment with SAS (§25) and the device-transfer protocol (§ OwnedIdentityTransfer); exposed so any client can drive a SAS comparison. Verified against the official vectors.

func ComputeFullRatchetInstanceUID

func ComputeFullRatchetInstanceUID(aliceIdentity, bobIdentity, aliceDeviceUID, bobDeviceUID []byte) ([32]byte, error)

ComputeFullRatchetInstanceUID derives the protocol-instance UID for a full ratchet run (reference FullRatchetProtocol.computeProtocolUid): a default PRNG seeded with aliceIdentity‖bobIdentity‖aliceDeviceUID‖bobDeviceUID (raw concatenation, matching Seed(Seed…)), read for 32 bytes. Alice is the initiator (whose send seed is refreshed).

func CurrentCapabilities added in v0.3.0

func CurrentCapabilities() []string

CurrentCapabilities returns a copy of the capability set this client advertises to its peers.

func DecryptAttachment

func DecryptAttachment(key *AuthEncKey, chunks [][]byte) ([]byte, error)

DecryptAttachment decrypts and reassembles the plaintext from encrypted chunks (spec §23.3). Chunks are reordered by their embedded chunk number, so they may be supplied in any order. This buffers everything — for large files, decrypt chunk-by-chunk with DecryptAttachmentChunk to an io.Writer.

func DecryptAttachmentChunk

func DecryptAttachmentChunk(key *AuthEncKey, encryptedChunk []byte) (chunkNumber int64, data []byte, err error)

DecryptAttachmentChunk decrypts one chunk, returning its number and data.

func DecryptBackup

func DecryptBackup(blob []byte, keys *BackupDerivedKeys) ([]byte, error)

DecryptBackup reverses EncryptBackup (spec §36.3): verify the appended MAC, then KEM-decrypt. If the recovered plaintext looks raw-deflate compressed (a legacy backup), it is inflated. The MAC is checked in constant time before any decryption.

func DecryptDeviceName added in v0.3.0

func DecryptDeviceName(owned *OwnedCryptoIdentity, encrypted []byte) (string, error)

DecryptDeviceName reverses EncryptDeviceName: decrypt the blob with our own KEM private key, decode the padded list, and return the UTF-8 device name (empty if cleared). Used to display another of our devices' names.

func DecryptMessageAsOwner

func DecryptMessageAsOwner(header, ciphertext []byte, owned *OwnedCryptoIdentity) (encodedPayload []byte, err error)

DecryptMessageAsOwner reverses EncryptMessageForIdentity: it unwraps the message key with the owned KEM private key, decrypts the content, verifies the GkmV2 binding, and strips the padding, returning the encoded payload.

func DecryptReturnReceipt

func DecryptReturnReceipt(key *AuthEncKey, encryptedPayload []byte) (readerIdentity []byte, status int64, err error)

DecryptReturnReceipt decrypts a return-receipt payload with the key the sender kept (from NewReturnReceiptKey) and returns who acknowledged it and the status (ReturnReceiptStatusDelivered / ...Read).

func DecryptServerBlob

func DecryptServerBlob(ciphertext, mainSeed, versionSeed, expectedGroupUID []byte) (blob *ServerBlob, signer *CryptoIdentity, err error)

DecryptServerBlob decrypts, unpads, decodes and verifies a downloaded blob (spec GroupsV2Protocol, blob download). It checks the "groupBlob" signature and that the signer is an administrator of the chain's last block, and validates the administrators-chain integrity against expectedGroupUID.

func DeserializeCapabilities added in v0.3.0

func DeserializeCapabilities(blob []byte) []string

DeserializeCapabilities reverses SerializeCapabilities, keeping unknown/forward-compatible names. A nil blob stays nil ("unknown"); an empty blob is an empty (non-nil) set.

func DisplayNameFromSerializedDetails

func DisplayNameFromSerializedDetails(s string) string

DisplayNameFromSerializedDetails parses a JsonIdentityDetails JSON string into a human-readable display name (first + last, else company). If the input is not valid JSON it is returned unchanged, tolerating a peer that sent a bare name.

func EncodeAttachmentDescriptor

func EncodeAttachmentDescriptor(key *AuthEncKey, metadataJSON []byte) []byte

EncodeAttachmentDescriptor encodes the per-attachment entry carried in the application-message payload (spec §22.2): encodeList(encodeSymKey(key), encodeString(metadataJSON)).

func EncodeGroupAdminPublicKey

func EncodeGroupAdminPublicKey(pk *PublicKeyOverEC) []byte

EncodeGroupAdminPublicKey encodes the group administration public key as it is uploaded to / stored on the server (encoding 0x91).

func EncryptAdminChain

func EncryptAdminChain(chain *AdministratorsChain, mainSeed []byte, rnd prng.PRNG) ([]byte, error)

EncryptAdminChain encrypts an administrators chain for a kick message.

func EncryptAttachment

func EncryptAttachment(key *AuthEncKey, plaintext []byte, dataChunkSize int, rnd prng.PRNG) ([][]byte, error)

EncryptAttachment splits plaintext into chunks of dataChunkSize plaintext bytes and encrypts each independently (spec §23.3). It returns the encrypted chunks; every full chunk has the same encrypted length (the last may be smaller). This buffers everything — for large files use EncryptAttachmentStream.

func EncryptAttachmentChunk

func EncryptAttachmentChunk(key *AuthEncKey, chunkNumber int, data []byte, rnd prng.PRNG) ([]byte, error)

EncryptAttachmentChunk encrypts one attachment chunk (spec §23.3): AuthEnc(key, encodeList(chunkNumber, data)). The encrypted length is len(data) + chunkEncodingOverhead + attachmentAuthEncOverhead.

func EncryptAttachmentStream

func EncryptAttachmentStream(key *AuthEncKey, r io.Reader, dataChunkSize int, rnd prng.PRNG, emit func(encryptedChunk []byte) error) (int, error)

EncryptAttachmentStream reads plaintext from r in dataChunkSize pieces, encrypts each and hands it to emit (spec §23.3). Peak memory is one chunk — use it for large files. It returns the number of chunks emitted.

func EncryptBackup

func EncryptBackup(payload []byte, keys *BackupDerivedKeys, rnd prng.PRNG) ([]byte, error)

EncryptBackup encrypts a backup payload under the seed-derived keys (spec §36.2): ciphertext = PublicKeyEncrypt(encPub, payload); return ciphertext ∥ HMAC(macKey, ciphertext). The payload is not compressed (matching the current reference; decryption still accepts legacy compressed backups).

func EncryptDeviceName added in v0.3.0

func EncryptDeviceName(owned *OwnedCryptoIdentity, name string, rnd prng.PRNG) ([]byte, error)

EncryptDeviceName produces the encrypted device-name blob for a device-management rename (reference OwnedDeviceManagementProtocol.SendRequestStep, ACTION_SET_NICKNAME): the UTF-8 name is wrapped as Encoded.of([Encoded.of(name)]), zero-padded up to the next multiple of 128 bytes, then public-key- encrypted to the identity's OWN encryption key — so only this identity's devices can read it. An empty name is allowed (clears the name).

func EncryptMessageForIdentity

func EncryptMessageForIdentity(encodedPayload []byte, recipient *CryptoIdentity, rnd prng.PRNG) (header, ciphertext []byte, err error)

EncryptMessageForIdentity encrypts an encoded message payload for a recipient identity on an asymmetric channel (spec §23.1). It returns the per-device header (the wrapped message key) and the shared encrypted content.

func EncryptMessageForIdentityWithExtended

func EncryptMessageForIdentityWithExtended(encodedPayload, extendedPayload []byte, recipient *CryptoIdentity, rnd prng.PRNG) (header, ciphertext, encryptedExtended []byte, err error)

EncryptMessageForIdentityWithExtended is like EncryptMessageForIdentity but, when extendedPayload is non-nil, also returns it encrypted under the key derived from the message key (spec §23.1, §23.2). encryptedExtended is nil when extendedPayload is nil.

func EncryptReturnReceipt

func EncryptReturnReceipt(key *AuthEncKey, senderIdentity []byte, status int64, rnd prng.PRNG) ([]byte, error)

EncryptReturnReceipt builds and encrypts a return-receipt payload (spec §49.1 / §50.6): AuthEnc-encrypt encodeList(senderIdentity, status) under the key the original application message advertised (identified by its nonce).

func EncryptReturnReceiptWithKey

func EncryptReturnReceiptWithKey(encodedKey, senderIdentity []byte, status int64, rnd prng.PRNG) ([]byte, error)

EncryptReturnReceiptWithKey is EncryptReturnReceipt taking the receipt key as the encoded AuthEncKey bytes carried in a received message's rr.key field (a symmetric-key encoding), so callers outside this package need not decode it.

func EncryptServerBlob

func EncryptServerBlob(blob *ServerBlob, signer *OwnedCryptoIdentity, mainSeed, versionSeed []byte, rnd prng.PRNG) ([]byte, error)

EncryptServerBlob builds the signed, padded and encrypted blob ready for upload (spec GroupsV2Protocol, group creation / update). The signature over the encoded blob is produced with signer's authentication key under the "groupBlob" context; the signed blob is encodeList(blob, signerIdentity, signature), zero-padded to a multiple of 4096, then AuthEnc-encrypted.

func GenerateAuthenticationKeyPair

func GenerateAuthenticationKeyPair(rnd prng.PRNG, curve *ec.Curve) (pk *PublicKeyOverEC, sk *PrivateKeyOverEC, err error)

GenerateAuthenticationKeyPair produces an authentication key pair over the given curve (spec §15, AuthenticationOverEC.generateKeyPair).

func GenerateGroupAdminKeyPair

func GenerateGroupAdminKeyPair(rnd prng.PRNG) (pk *PublicKeyOverEC, sk *PrivateKeyOverEC, err error)

GenerateGroupAdminKeyPair produces the group administration authentication key pair (spec GroupsV2Protocol: generateServerAuthenticationKeyPair, default ECSDSA over MDC).

func GenerateKEMKeyPair

func GenerateKEMKeyPair(rnd prng.PRNG, curve *ec.Curve) (pk *PublicKeyOverEC, sk *PrivateKeyOverEC, err error)

GenerateKEMKeyPair produces a KEM key pair over the given curve (spec §16, KEMOverEC.generateKeyPair).

func GeneratePreKey

func GeneratePreKey(owned *OwnedCryptoIdentity, deviceUID []byte, expiration int64, capabilities []string, rnd prng.PRNG) (signedPreKey []byte, private *PrivateKeyOverEC, pk *PreKey, err error)

GeneratePreKey creates a fresh pre-key for a device: it generates a KEM key pair (over Curve25519, like the identity's encryption key), builds and signs the encoded pre-key, and returns the encoded signed pre-key (ready for upload), the matching KEM private key, and the PreKey.

func GenerateSignatureKeyPair

func GenerateSignatureKeyPair(rnd prng.PRNG, curve *ec.Curve) (pk *PublicKeyOverEC, sk *PrivateKeyOverEC, err error)

GenerateSignatureKeyPair produces a signature key pair over the given curve (spec §14, SignatureOverEC.generateKeyPair).

func IntersectCapabilities added in v0.3.0

func IntersectCapabilities(deviceSets [][]string) []string

IntersectCapabilities computes a contact/own effective capability set from the per-device sets: a capability counts only if EVERY known device reports it. A device with a nil set is skipped (unknown); a device with an empty set forces the result empty (reference intersection semantics). deviceSets holds one entry per device (nil = unknown). Returns a sorted set.

func IsGroupInvitationMessage

func IsGroupInvitationMessage(pm *ProtocolMessage) bool

IsGroupInvitationMessage reports whether pm is any of the three invitation/members-update variants.

func IsIntroductionAck

func IsIntroductionAck(pm *ProtocolMessage) bool

IsIntroductionAck reports whether pm is a well-formed introduction Ack.

func IsSASCommitment

func IsSASCommitment(m *ProtocolMessage) bool

IsSASCommitment reports whether a decoded protocol message is a trust-establishment commitment (the message that opens a responder-from-inbound exchange).

func IsSASPropagatedCommitment added in v0.3.7

func IsSASPropagatedCommitment(m *ProtocolMessage) bool

IsSASPropagatedCommitment reports whether a message is a PropagateCommitmentToBobDevices (id 4) — the responder-side propagation our answering device sends to our other devices so they mirror the accept.

func IsSASPropagatedConfirmation added in v0.3.7

func IsSASPropagatedConfirmation(m *ProtocolMessage) bool

IsSASPropagatedConfirmation reports whether a message is a PropagateConfirmationToBobDevices (id 6).

func IsSASPropagatedEnteredSAS added in v0.3.7

func IsSASPropagatedEnteredSAS(m *ProtocolMessage) bool

IsSASPropagatedEnteredSAS reports whether a message is a PropagateEnteredSasToOtherDevices (id 12).

func IsSASPropagatedInvitation added in v0.3.7

func IsSASPropagatedInvitation(m *ProtocolMessage) bool

IsSASPropagatedInvitation reports whether a message is a PropagateInvitationToAliceDevices (id 2) — the multi-device propagation our initiating device sends to our other devices so they mirror the add.

func KEMDecrypt

func KEMDecrypt(sk *PrivateKeyOverEC, c []byte, keyLen uint32) (key []byte, err error)

KEMDecrypt recovers the encapsulated key from ciphertext c using sk (spec §16, KEMOverEC.decrypt).

func KEMEncrypt

func KEMEncrypt(pk *PublicKeyOverEC, rnd prng.PRNG, keyLen uint32) (c, key []byte, err error)

KEMEncrypt encapsulates a fresh symmetric key of keyLen bytes under pk, returning the ciphertext c and the derived key (spec §16, KEMOverEC.encrypt):

repeat r <- prng.bigInt(q) until r != 0
By   <- scalarMultiplication(r, G.y);  Dy <- scalarMultiplication(r, pk.y)
c    <- bytesFromBigUInt(By, len(p))
seed <- c || bytesFromBigUInt(Dy, len(p))
key  <- KDF(seed, keyLen)

func MarshalInteropBackup

func MarshalInteropBackup(owned []OwnedIdentityBackup, timestampMillis int64) ([]byte, error)

MarshalInteropBackup produces the spec §36.1 JSON plaintext for the given owned identities at the given timestamp (unix millis).

func NewSASFromPropagatedCommitment added in v0.3.7

func NewSASFromPropagatedCommitment(owned *OwnedCryptoIdentity, ownDeviceUIDs [][]byte, ownDetails string, pm *ProtocolMessage, rnd prng.PRNG) (party *SASParty, peer *CryptoIdentity, err error)

NewSASFromPropagatedCommitment builds a Bob-side party on one of our OTHER devices from a PropagateCommitmentToBobDevices message (id 4, reference StoreCommitmentAndAskForConfirmationStep) that our answering device broadcast to us: it stores the contact's commitment, details and device UIDs and waits for the propagated accept/reject (id 6). Inputs: [contactIdentity, contactSerializedDetails, contactDeviceUids, commitment]. See CONTACT_SYNC.md.

func NewSASFromPropagatedInvitation added in v0.3.7

func NewSASFromPropagatedInvitation(owned *OwnedCryptoIdentity, ownDeviceUIDs [][]byte, ownDetails string, pm *ProtocolMessage, rnd prng.PRNG) (party *SASParty, peer *CryptoIdentity, displayName string, err error)

NewSASFromPropagatedInvitation builds an Alice-side party on one of our OTHER devices from a PropagateInvitationToAliceDevices message (id 2, reference StoreDecommitmentStep) that our initiating device broadcast to us over an own-device channel. Instead of generating a commitment, it ADOPTS the decommitment + seedAlice from the message and starts in WAITING_FOR_SEED, so the exchange completes here in parallel: Bob's seed (id8) and confirmation (id13) arrive directly (Bob addresses all our devices) and the entered SAS (id12) is propagated. Inputs: [contactIdentity, contactDisplayName, decommitment, seedAliceForSas]. Returns the party, the contact identity, and the contact's display name (for labelling).

func NewSASResponderFromCommitment

func NewSASResponderFromCommitment(owned *OwnedCryptoIdentity, ownDeviceUIDs [][]byte, ownDetails string, commitment *ProtocolMessage, rnd prng.PRNG) (party *SASParty, peer *CryptoIdentity, peerDeviceUIDs [][]byte, reply []OutgoingMessage, err error)

NewSASResponderFromCommitment builds a responding party from an inbound SEND_COMMITMENT protocol message (the responder-from-inbound path: a peer initiated trust toward us). It extracts the peer identity, display-name details, device UIDs and instance UID from the message, processes the commitment, and returns the party, the peer identity + device UIDs (so replies can be addressed) and the SEND_BOB_SEED reply to transport.

func ParseCapabilitiesMessage added in v0.3.0

func ParseCapabilitiesMessage(pm *ProtocolMessage) (rawCaps []string, isResponse, toSelf bool, err error)

ParseCapabilitiesMessage extracts the announced capabilities and flags from an own-capabilities channel message (id 3 from a contact, or id 4 from an own device). Raw names are preserved (unknown/ future capabilities pass through untouched, matching the reference).

func ParseContactChannelCreationPing

func ParseContactChannelCreationPing(pm *ProtocolMessage) (senderIdentity, senderDevice []byte, err error)

ParseContactChannelCreationPing extracts the sender's identity and device UID from a contact channel-creation ping (protocol 2, message 1). A peer sends this to start establishing a channel; a client that has no exchange in flight can use it to begin its own side. Returns an error for any other message.

func ParseContactMgmtPropagatedIdentity added in v0.3.0

func ParseContactMgmtPropagatedIdentity(pm *ProtocolMessage) ([]byte, error)

ParseContactMgmtPropagatedIdentity extracts the contact identity from a propagate-to-own-devices message (id 2 or 5).

func ParseGroupInvitationMessage

func ParseGroupInvitationMessage(m *ProtocolMessage) (gid GroupIdentifier, version int64, keys *BlobKeys, deviceUIDs [][]byte, err error)

ParseGroupInvitationMessage parses any of the three invitation/members-update variants (id 4/5/6), returning the common fields. deviceUIDs is populated only for the oblivious variant (id 4); it is empty for the broadcast/propagated variants, which omit the device-UID list.

func ParseIdentityDetailsMessage

func ParseIdentityDetailsMessage(pm *ProtocolMessage) (string, error)

ParseIdentityDetailsMessage extracts the details+version JSON string from a SEND_DETAILS or PROPAGATE_OWN_DETAILS message. It rejects any other protocol/message id or a malformed input.

func ParseMediatorInvitationMessage

func ParseMediatorInvitationMessage(pm *ProtocolMessage) (contactIdentity []byte, serializedDetails string, err error)

ParseMediatorInvitationMessage extracts the introduced contact's identity and details.

func ParseNotifyAcceptedMessage

func ParseNotifyAcceptedMessage(pm *ProtocolMessage) (deviceUIDs [][]byte, signature []byte, err error)

ParseNotifyAcceptedMessage extracts the sender's device UIDs and signature.

func ParseOwnedDeviceChannelCreationPing added in v0.2.1

func ParseOwnedDeviceChannelCreationPing(pm *ProtocolMessage) (senderDevice []byte, err error)

ParseOwnedDeviceChannelCreationPing extracts the sender device UID from an own-device channel- creation ping (protocol 22, message 1). The remote is always our own identity, so the ping omits the leading identity element (inputs are [deviceUID, sig]); the caller establishes the sender's identity from the channel it must be responded to (ours). Returns an error for any other message.

func ParseOwnedIdentityDeletedMessage added in v0.3.0

func ParseOwnedIdentityDeletedMessage(pm *ProtocolMessage) (deletedIdentity, signature []byte, err error)

ParseOwnedIdentityDeletedMessage extracts the deleter's identity and the signature from a ContactOwnedIdentityWasDeleted message (id 1).

func ParseReturnReceiptPayload

func ParseReturnReceiptPayload(decrypted []byte) (senderIdentity []byte, status int64, attachmentNumber int64, hasAttachment bool, err error)

ParseReturnReceiptPayload decodes a decrypted return-receipt payload (spec §50.6): an encoded list of [senderIdentity, status] (optionally followed by an attachment number). Decrypt the WebSocket return receipt's encryptedPayload with the AuthEncKey identified by its nonce (key.Decrypt) before calling this.

func PublicKeyDecrypt

func PublicKeyDecrypt(sk *PrivateKeyOverEC, ct []byte) (plaintext []byte, err error)

PublicKeyDecrypt decrypts a ciphertext produced by PublicKeyEncrypt using the matching KEM private key (spec §23.1).

func PublicKeyEncrypt

func PublicKeyEncrypt(pk *PublicKeyOverEC, plaintext []byte, rnd prng.PRNG) (ct []byte, err error)

PublicKeyEncrypt encrypts plaintext to a KEM public key (spec §23.1).

func RunChannelCreation

func RunChannelCreation(alice, bob *ChannelCreationParty) error

RunChannelCreation drives both parties to completion over an in-memory router (real asymmetric + oblivious channel crypto). It returns an error if the protocol fails or does not confirm on both sides.

func RunFullRatchet

func RunFullRatchet(initiator, responder *FullRatchetParty) error

RunFullRatchet drives the protocol between the initiator and the responder to completion over their existing oblivious channels.

func RunTrustEstablishmentSAS

func RunTrustEstablishmentSAS(alice, bob *SASParty) error

RunTrustEstablishmentSAS drives Alice and Bob through the full exchange (over asymmetric channels), performs the out-of-band SAS comparison, and exchanges the mutual-trust confirmations. Both parties end MutualTrustConfirmed iff no tampering occurred.

func SASCommitmentPeerIdentity

func SASCommitmentPeerIdentity(m *ProtocolMessage) ([]byte, error)

SASCommitmentPeerIdentity returns the initiating peer's identity bytes from an inbound SEND_COMMITMENT message (input[0]) without any side effect, so a caller can decide whether the peer is already a known contact before starting a responder exchange.

func SASMessageFromOwnDevice added in v0.3.7

func SASMessageFromOwnDevice(messageID int) bool

SASMessageFromOwnDevice reports whether a trust-establishment message id is a multi-device propagation message (sent over own-device channels), so the router gates it RecvFromOwnDevice rather than RecvAsymmetric.

func SASPropagatedCommitmentPeer added in v0.3.7

func SASPropagatedCommitmentPeer(m *ProtocolMessage) ([]byte, error)

SASPropagatedCommitmentPeer returns the contact identity from a PropagateCommitmentToBobDevices message (input[0]) without side effects, so a caller can skip an add for an already-known contact.

func SASPropagatedInvitationPeer added in v0.3.7

func SASPropagatedInvitationPeer(m *ProtocolMessage) ([]byte, error)

SASPropagatedInvitationPeer returns the contact identity from a PropagateInvitationToAliceDevices message (input[0]) without side effects, so a caller can skip an add for an already-known contact.

func SerializeCapabilities added in v0.3.0

func SerializeCapabilities(caps []string) []byte

SerializeCapabilities encodes a capability set as the reference on-disk blob: the names sorted ascending and joined with a single NUL byte, UTF-8. nil stays nil ("unknown"); an empty slice becomes an empty (non-nil) blob ("known, no capabilities") — a distinction the intersection logic relies on.

func SerializeDisplayName

func SerializeDisplayName(name string) string

SerializeDisplayName builds a minimal JsonIdentityDetails JSON string carrying the given display name as the first name — the common case for a headless client with only a nick. The reference peer parses this to render the contact's name; a bare (non-JSON) string would make its JsonIdentityDetails parse throw and silently abort the exchange.

func SerializeIdentityDetails

func SerializeIdentityDetails(d SerializedIdentityDetails) string

SerializeIdentityDetails renders a full JsonIdentityDetails object to its JSON string (the form stored in a contact's PublishedDetails), with null/empty fields omitted like the reference.

func SerializeIdentityDetailsWithVersion

func SerializeIdentityDetailsWithVersion(details SerializedIdentityDetails, version int) string

SerializeIdentityDetailsWithVersion renders the details+version JSON carried by a SEND_DETAILS message (the exact string the reference peer parses).

func SignChannelCreationPing

func SignChannelCreationPing(sender *OwnedCryptoIdentity, senderDeviceUID []byte, recipient *CryptoIdentity, recipientDeviceUID []byte, rnd prng.PRNG) ([]byte, error)

SignChannelCreationPing signs a channel-creation ping with the sender's authentication key (reusing the authentication scheme, spec §15/§26).

func SignGroupDelete

func SignGroupDelete(adminPk *PublicKeyOverEC, adminSk *PrivateKeyOverEC, rnd prng.PRNG) ([]byte, error)

SignGroupDelete signs a blob deletion (spec §47.6): prefix "deleteGroup", empty challenge.

func SignGroupJoinPing

func SignGroupJoinPing(gid GroupIdentifier, ownNonce []byte, recipient *CryptoIdentity, signer *OwnedCryptoIdentity, rnd prng.PRNG) ([]byte, error)

SignGroupJoinPing signs a join ping bound to a specific recipient (reference signGroupInvitationNonce with GROUP_JOIN_NONCE): data = gid || ownNonce || recipientIdentity, signed with the signer's authentication key.

func SignGroupKick

func SignGroupKick(encryptedChain, kickedNonce []byte, signer *OwnedCryptoIdentity, rnd prng.PRNG) ([]byte, error)

SignGroupKick signs a kick targeting a specific member (reference signBlock with GROUP_KICK): data = encryptedChain || kickedMemberNonce.

func SignGroupLeaveLog

func SignGroupLeaveLog(gid GroupIdentifier, invitationNonce []byte, leaver *OwnedCryptoIdentity, rnd prng.PRNG) ([]byte, error)

SignGroupLeaveLog builds the log item proving a member left a group (spec §34 "Group v2 log", §47.5). It signs groupIdentifier || invitationNonce with the leaver's own authentication key under the "groupLeave" context. The server stores only this signature, never what was signed.

func SignGroupLock

func SignGroupLock(nonce []byte, adminPk *PublicKeyOverEC, adminSk *PrivateKeyOverEC, rnd prng.PRNG) ([]byte, error)

SignGroupLock signs a lock nonce to acquire the server lock (spec §47.3): AuthenticationOverEC.solve with the group admin key, prefix "lockNonce", challenge = nonce.

func SignGroupUpdate

func SignGroupUpdate(nonce, encryptedBlob, encodedNewAdminPublicKey []byte, adminPk *PublicKeyOverEC, adminSk *PrivateKeyOverEC, rnd prng.PRNG) ([]byte, error)

SignGroupUpdate signs a blob update (spec §47.4): prefix "updateGroup", challenge = nonce || encryptedBlob || encodedNewAdminPublicKey.

func SignMutualIntroduction

func SignMutualIntroduction(signer *OwnedCryptoIdentity, id0, id1, id2 []byte, rnd prng.PRNG) ([]byte, error)

SignMutualIntroduction signs the ordered identity triple with the signer's authentication key. When accepting an introduction, the triple is [mediator, other, self].

func SignOwnedIdentityDeletion added in v0.3.0

func SignOwnedIdentityDeletion(recipientIdentity []byte, deleter *OwnedCryptoIdentity, rnd prng.PRNG) ([]byte, error)

SignOwnedIdentityDeletion signs the deletion notification bound to one recipient: the recipient's identity bytes, signed with the deleter's authentication key.

func SignatureSign

func SignatureSign(sk *PrivateKeyOverEC, m []byte, pk *PublicKeyOverEC, rnd prng.PRNG) (sigma []byte, err error)

SignatureSign computes the signature of m under sk (associated to pk), using prng for the ephemeral key pair (spec §14, SignatureOverEC.sign).

(pk', sk') <- generateKeyPair(prng, curve)
e          <- SHA256( P'.y || pk.y || m )     (as a big integer)
y          <- (sk'.scalar - sk.scalar * e) mod q
sigma      <- e_bytes(32) || bytesFromBigUInt(y, len(p))

func SignatureVerify

func SignatureVerify(pk *PublicKeyOverEC, m, sigma []byte) bool

SignatureVerify checks signature sigma of m under pk (spec §14, SignatureOverEC.verify).

func VerifyChannelCreationPing

func VerifyChannelCreationPing(signature []byte, self *CryptoIdentity, selfDeviceUID []byte, contact *CryptoIdentity, contactDeviceUID []byte) bool

VerifyChannelCreationPing verifies a ping signature from a contact (self = verifier, contact = signer).

func VerifyGroupJoinPing

func VerifyGroupJoinPing(gid GroupIdentifier, senderNonce []byte, self *CryptoIdentity, sender *CryptoIdentity, sig []byte) bool

VerifyGroupJoinPing verifies a join ping we received (reference Signature.verify with GROUP_JOIN_NONCE): the recipient is us (self), the signer is the candidate member.

func VerifyGroupKick

func VerifyGroupKick(encryptedChain, ownNonce []byte, signerAuth *PublicKeyOverEC, sig []byte) bool

VerifyGroupKick verifies a kick against a candidate kicker's authentication key using our own invitation nonce (reference GetKickedStep).

func VerifyGroupLeaveLog

func VerifyGroupLeaveLog(gid GroupIdentifier, member *GroupMember, logItem []byte) bool

VerifyGroupLeaveLog checks a leave log item against a candidate member (spec §34, consolidateWithLogEntries).

func VerifyJWS

func VerifyJWS(compact string, jwk *JSONWebKey) ([]byte, error)

VerifyJWS verifies a compact JWS (header.payload.signature) against jwk and returns the decoded payload bytes. It errors on any malformed input, an unsupported algorithm, or an invalid signature.

func VerifyMessageKey

func VerifyMessageKey(ae *AuthEncKey, paddedPlaintext []byte) bool

VerifyMessageKey checks that ae was produced by GenerateMessageKey for paddedPlaintext (spec §23.1). Used on decryption to authenticate the header against the message body.

func VerifyMutualIntroduction

func VerifyMutualIntroduction(signerAuth *PublicKeyOverEC, id0, id1, id2, sig []byte) bool

VerifyMutualIntroduction verifies a signature against the signer's authentication public key. When verifying an inbound notification, the triple is [mediator, self, sender].

func VerifyOwnedIdentityDeletion added in v0.3.0

func VerifyOwnedIdentityDeletion(recipientIdentity, signature []byte, deleterAuth *PublicKeyOverEC) bool

VerifyOwnedIdentityDeletion checks a deletion signature: it must sign OUR (the recipient's) identity bytes under the deleter's authentication key.

Types

type AES256CtrKey

type AES256CtrKey types.SymmetricKey

AES256CtrKey is a 256-bit AES-CTR symmetric encryption key (spec crypto/SymEncKey), backed by a SymmetricKey whose "enckey" dict entry holds the encoded 32-byte key.

func NewAES256Ctr

func NewAES256Ctr(key []byte) (*AES256CtrKey, error)

func (*AES256CtrKey) CtLen

func (aesk *AES256CtrKey) CtLen(l uint32) (lo uint32)

func (*AES256CtrKey) Decrypt

func (aesk *AES256CtrKey) Decrypt(ct []byte) (pt []byte, err error)

func (*AES256CtrKey) Encrypt

func (aesk *AES256CtrKey) Encrypt(iv, pt []byte) (ct []byte, err error)

func (*AES256CtrKey) PtLen

func (aesk *AES256CtrKey) PtLen(l uint32) (lo uint32, err error)

type AdminChainBlock

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

AdminChainBlock is one block of the administrators chain.

type AdministratorsChain

type AdministratorsChain struct {
	GroupUID []byte
	Blocks   []*AdminChainBlock
}

AdministratorsChain is the ordered list of blocks (spec §34).

func DecodeAdministratorsChain

func DecodeAdministratorsChain(b []byte) (*AdministratorsChain, error)

DecodeAdministratorsChain parses a chain and recomputes its groupUid from the first block (spec §34, AdministratorsChain.of).

func DecryptAdminChain

func DecryptAdminChain(ciphertext, mainSeed []byte) (*AdministratorsChain, error)

DecryptAdminChain decrypts and parses the administrators chain from a kick.

func StartNewAdminChain

func StartNewAdminChain(owner *OwnedCryptoIdentity, otherAdmins []*CryptoIdentity, rnd prng.PRNG) (*AdministratorsChain, error)

StartNewAdminChain creates the first block of a new chain, signed by the group creator (spec §34, AdministratorsChain.startNewChain). The returned groupUid is SHA256 of the encoded first block.

func (*AdministratorsChain) Admins

func (c *AdministratorsChain) Admins() []*CryptoIdentity

Admins returns the administrator identities of the last block.

func (*AdministratorsChain) AppendBlock

func (c *AdministratorsChain) AppendBlock(owner *OwnedCryptoIdentity, otherAdmins []*CryptoIdentity, rnd prng.PRNG) (*AdministratorsChain, error)

AppendBlock returns a new chain with an extra block updating the administrator list, signed by owner (who must be an administrator of the current last block) (spec §34, buildNewChainByAppendingABlock).

func (*AdministratorsChain) CheckIntegrity

func (c *AdministratorsChain) CheckIntegrity(expectedGroupUID []byte) error

CheckIntegrity validates the whole chain: groupUid matches SHA256(block0), each block chains to the previous by hash, and every block's signature is valid against the administrators of the previous block (spec §34, withCheckedIntegrity, full-verification branch).

func (*AdministratorsChain) CheckIntegrityWithPrefix

func (c *AdministratorsChain) CheckIntegrityWithPrefix(expectedGroupUID []byte, trustedPrefix *AdministratorsChain) error

CheckIntegrityWithPrefix validates a chain that must extend an already-trusted prefix (reference AdministratorsChain.withCheckedIntegrity, prefix branch): the prefix must be a real prefix and only the new blocks are re-verified. With a nil/empty prefix it falls back to a full CheckIntegrity.

func (*AdministratorsChain) IsPrefixedBy

func (c *AdministratorsChain) IsPrefixedBy(prefix *AdministratorsChain) bool

IsPrefixedBy reports whether prefix is an exact block-prefix of this chain (reference AdministratorsChain.isPrefixedBy): same groupUid, no more blocks than us, and every prefix block's encoded inner data matches ours.

type AttachmentMetadata

type AttachmentMetadata struct {
	Type     string `json:"type"` // MIME type
	FileName string `json:"file_name"`
	SHA256   []byte `json:"sha256"`
}

AttachmentMetadata is the per-attachment metadata JSON (spec §22.2, "Attachment metadata JSON"). The JSON keys match the reference exactly (olvid-android AttachmentKeyAndMetadata / EngineNotificationProcessorForMessages): the filename key is snake_case "file_name", NOT "fileName" — a mismatch makes the peer's app unable to read the filename and drop the attachment.

func ParseAttachmentMetadata

func ParseAttachmentMetadata(b []byte) (*AttachmentMetadata, error)

ParseAttachmentMetadata decodes an attachment metadata JSON.

func (*AttachmentMetadata) Marshal

func (m *AttachmentMetadata) Marshal() ([]byte, error)

Marshal serializes the metadata to its JSON form.

type AuthEnc

type AuthEnc interface {
	Encrypt(pt []byte, rnd prng.PRNG) (ct []byte, err error)
	Decrypt(ct []byte) (pt []byte, err error)
	CtLen(ptlen uint32) (ctlen uint32)
	PtLen(ctlen uint32) (ptlen uint32, err error)
}

type AuthEncKey

type AuthEncKey struct {
	*types.CryptographicKey
	// contains filtered or unexported fields
}

func DecodeAttachmentDescriptor

func DecodeAttachmentDescriptor(b []byte) (key *AuthEncKey, metadataJSON []byte, err error)

DecodeAttachmentDescriptor is the inverse of EncodeAttachmentDescriptor.

func DecodeReturnReceiptKey added in v0.3.2

func DecodeReturnReceiptKey(encodedKey []byte) (*AuthEncKey, error)

DecodeReturnReceiptKey decodes the rr.key field carried in a message's return-receipt block back into the AuthEncKey needed to decrypt the acknowledgements. Used to register a receipt reflected from another of our own devices, so this device can also decrypt the single receipt the recipient posts (multi-device receipt convergence; see MESSAGE_SYNC.md).

func DeriveExtendedPayloadKey

func DeriveExtendedPayloadKey(msgKey *AuthEncKey) (*AuthEncKey, error)

DeriveExtendedPayloadKey derives the extended-payload AuthEnc key from a message key (spec §23.2, DeriveExtendedPayloadKey):

seed    <- Seed.of(msgKey)                 (deterministic, see seedOf)
keySeed <- PRNG(seed).bytes(32)
return  <- AES256CTRHMACSHA256.generateKey(keySeed)

func ExtendedPayloadKeyForOwner

func ExtendedPayloadKeyForOwner(header []byte, owned *OwnedCryptoIdentity) (*AuthEncKey, error)

ExtendedPayloadKeyForOwner recovers the message key from a per-device header and derives the extended-payload key (spec §23.2). Use it to decrypt content fetched from /downloadMessageExtendedContent.

func GenerateAttachmentKey

func GenerateAttachmentKey(rnd prng.PRNG) (*AuthEncKey, error)

GenerateAttachmentKey creates a random AuthEnc key for an attachment.

func GenerateMessageKey

func GenerateMessageKey(rnd prng.PRNG, paddedPlaintext []byte) (*AuthEncKey, error)

GenerateMessageKey derives a per-message AuthEncKey tied to paddedPlaintext (spec §23.1, GkmV2 GenerateMessageKey):

seedEnc <- prng.bytes(32)
keyEnc  <- KDF(seedEnc, 32)                 (AES-256-CTR key)
keyMac  <- KDF(keyEnc || paddedPlaintext, 32) (HMAC-SHA-256 key)
return AuthEncKey(keyMac || keyEnc)

func GroupBlobEncryptionKey

func GroupBlobEncryptionKey(mainSeed, versionSeed []byte) (*AuthEncKey, error)

GroupBlobEncryptionKey derives the AuthEnc key protecting a blob from the main and version seeds (spec §34, getSharedBlobSecretKey): KDF_SHA256(mainSeed || versionSeed).

func NewAES256CtrHmacSha256KeyFromBytes

func NewAES256CtrHmacSha256KeyFromBytes(b []byte) (ae *AuthEncKey, err error)

func NewAES256CtrHmacSha256KeyFromDict

func NewAES256CtrHmacSha256KeyFromDict(dict types.Dict) (ae *AuthEncKey, err error)

func NewAES256CtrHmacSha256KeyFromSeed

func NewAES256CtrHmacSha256KeyFromSeed(seed []byte) (ae *AuthEncKey, err error)

NewAES256CtrHmacSha256KeyFromSeed implements AES256CTRHMACSHA256.generateKey (spec Section 11.1): kdf.compute(seed, AES256CTRHMACSHA256Key).

func NewReturnReceiptKey

func NewReturnReceiptKey(rnd prng.PRNG) (nonce, encodedKey []byte, key *AuthEncKey, err error)

NewReturnReceiptKey mints the material a sender attaches to an outgoing message so recipients can acknowledge it (spec §22.2 "Return receipt"): a random nonce, a fresh AuthEncKey encoded for the message's rr.key field, and the key itself, which the sender keeps to decrypt the receipts that come back (they are encrypted under this key by the recipient).

func (*AuthEncKey) CtLen

func (ae *AuthEncKey) CtLen(ptlen uint32) (ctlen uint32)

CtLen returns the ciphertext length for a plaintext of length ptlen: inner AES-CTR output (iv + ptlen) plus the MAC tag.

func (*AuthEncKey) Decrypt

func (ae *AuthEncKey) Decrypt(ct []byte) (pt []byte, err error)

Decrypt verifies the MAC (in constant time) then decrypts. The inner ciphertext c0 = iv || AES-CTR(m) carries its own IV, so ke.decrypt strips it.

func (*AuthEncKey) Encrypt

func (ae *AuthEncKey) Encrypt(pt []byte, rnd prng.PRNG) (ct []byte, err error)

Encrypt implements Encrypt-then-MAC (spec Section 11.1):

c0 <- ke.encrypt(iv, m)   where iv <- prng.bytes(8), so c0 = iv || AES-CTR(m)
t  <- ka.compute(c0)      HMAC-SHA-256 over the full inner ciphertext
return c0 || t

func (*AuthEncKey) PtLen

func (ae *AuthEncKey) PtLen(ctlen uint32) (ptlen uint32, err error)

PtLen returns the plaintext length for a ciphertext of length ctlen.

func (*AuthEncKey) Wipe

func (ae *AuthEncKey) Wipe()

Wipe best-effort zeroizes the key material this key holds (its encryption and MAC key bytes live in the shared Dict, from which Encrypt/Decrypt read). It is defense-in-depth for forward secrecy — Go's GC may have copied the bytes elsewhere, so this is not a guarantee. The key must not be used after Wipe.

type BackupDerivedKeys

type BackupDerivedKeys struct {
	KeyUID  []byte           // 32-byte backup key UID
	EncPub  *PublicKeyOverEC // KEM (ECIES) public key over Curve25519
	EncPriv *PrivateKeyOverEC
	MacKey  []byte // HMAC-SHA-256 key (32 bytes)
}

BackupDerivedKeys are the keys derived from a backup seed (spec §35.2). Only KeyUID, EncPub and MacKey are meant to be stored; EncPriv (and the seed) must be discarded.

type BackupEngine

type BackupEngine struct {
	IdentityManager []OwnedIdentityBackup `json:"identity_manager"`
}

type BackupFormat

type BackupFormat int

BackupFormat selects the plaintext layout inside a backup.

const (
	// BackupFormatOlvidInterop produces the spec §36.1 JSON (a '{' first byte), which a
	// real Olvid app (Android or iOS) can restore.
	BackupFormatOlvidInterop BackupFormat = iota
	// BackupFormatLibrary produces this library's snapshot pack (an encoded dict, 0x04
	// first byte) — self-contained, not cross-restorable by Olvid.
	BackupFormatLibrary
)

func BackupFormatOf

func BackupFormatOf(plaintext []byte) (BackupFormat, error)

BackupFormatOf reports the payload format from a decrypted backup's first byte.

func (BackupFormat) String

func (f BackupFormat) String() string

type BackupJSON

type BackupJSON struct {
	Engine            BackupEngine `json:"engine"`
	BackupJSONVersion int          `json:"backup_json_version"`
	BackupTimestamp   int64        `json:"backup_timestamp"`
}

func ParseInteropBackup

func ParseInteropBackup(jsonBytes []byte) (*BackupJSON, error)

ParseInteropBackup parses a spec §36.1 JSON backup plaintext.

type BackupSeed

type BackupSeed []byte

BackupSeed is a 160-bit Olvid backup key.

func GenerateBackupSeed

func GenerateBackupSeed(rnd prng.PRNG) (BackupSeed, error)

GenerateBackupSeed draws a fresh random backup seed.

func ParseBackupSeed

func ParseBackupSeed(s string) (BackupSeed, error)

ParseBackupSeed decodes a user-entered backup key string into a seed (spec §35.1). Non-alphabet characters (spaces, dashes) are ignored; case and the ambiguous letters I/O/S/Z are accepted.

func (BackupSeed) DeriveKeys

func (s BackupSeed) DeriveKeys() (*BackupDerivedKeys, error)

DeriveKeys derives the backup keys from the seed (spec §35.2): the seed is 0-padded to 32 bytes and used to seed a PRNGWithHMACWithSHA256, from which are drawn — in order — the 32-byte key UID, the KEM key pair over Curve25519, and the MAC key (KDF(prng.bytes(32), 32)). The draw order and consumption match the reference exactly.

func (BackupSeed) String

func (s BackupSeed) String() string

String renders the seed as 8 groups of 4 characters separated by spaces (spec §35.1).

type BlobKeys

type BlobKeys struct {
	BlobMainSeed         []byte            // may be nil over an asymmetric channel
	BlobVersionSeed      []byte            // never nil
	GroupAdminPrivateKey *PrivateKeyOverEC // may be nil for non-administrators
}

BlobKeys carries the secrets needed to read/update a group blob.

func DecodeBlobKeys

func DecodeBlobKeys(b []byte) (*BlobKeys, error)

func (*BlobKeys) Encode

func (k *BlobKeys) Encode() []byte

type ChannelCreationParty

type ChannelCreationParty struct {

	// Confirmed / Channel expose the result once the protocol completes.
	Confirmed bool
	Channel   *ObliviousChannel
	// contains filtered or unexported fields
}

ChannelCreationParty is one device running the protocol against a single contact device.

func NewChannelCreationParty

func NewChannelCreationParty(owned *OwnedCryptoIdentity, deviceUID []byte, contact *CryptoIdentity, contactDeviceUID []byte, instanceUID [32]byte, rnd prng.PRNG) *ChannelCreationParty

NewChannelCreationParty creates a party for establishing a channel from `owned`/`deviceUID` to `contact`/`contactDeviceUID`.

func NewOwnedDeviceChannelCreationParty

func NewOwnedDeviceChannelCreationParty(owned *OwnedCryptoIdentity, deviceUID, otherDeviceUID []byte, instanceUID [32]byte, rnd prng.PRNG) *ChannelCreationParty

NewOwnedDeviceChannelCreationParty creates a party for an own-device channel (spec §26, protocol ID 22): the same handshake, but `contact` is our own identity and `contactDeviceUID` is one of our other devices. The resulting channel should be registered as an own-device channel.

func (*ChannelCreationParty) Begin

func (p *ChannelCreationParty) Begin() ([]OutgoingMessage, error)

Begin starts the protocol (the SendPing step) and returns the first outgoing message(s) to transport to the contact.

func (*ChannelCreationParty) Contact

func (p *ChannelCreationParty) Contact() *CryptoIdentity

Contact returns the contact identity this party is talking to.

func (*ChannelCreationParty) ContactDeviceUID

func (p *ChannelCreationParty) ContactDeviceUID() []byte

ContactDeviceUID returns the contact device this party is talking to.

func (*ChannelCreationParty) IsOwnedDevice added in v0.2.1

func (p *ChannelCreationParty) IsOwnedDevice() bool

IsOwnedDevice reports whether this party is establishing a channel to one of our OWN other devices (protocol 22) rather than to a contact device (protocol 2).

func (*ChannelCreationParty) NascentChannel added in v0.2.0

func (p *ChannelCreationParty) NascentChannel() *ObliviousChannel

NascentChannel returns the oblivious channel as soon as it has been created mid-handshake (before the ack round confirms it), or nil. It exists so a dispatcher can register the channel early — the acks (FirstAck/SecondAck) are sent over it, so they can only be decrypted once it is registered. The exported Channel field, by contrast, is populated only on Confirmed.

func (*ChannelCreationParty) Receive

func (p *ChannelCreationParty) Receive(header, ciphertext []byte) ([]OutgoingMessage, error)

Receive processes one incoming channel-encrypted (header, ciphertext) pair arriving from the contact, auto-detecting whether it came on the asymmetric channel or the oblivious channel. Returns the message(s) to transport back. A message that is not for this protocol/state is consumed with no output.

func (*ChannelCreationParty) ReceiveParsed added in v0.2.0

func (p *ChannelCreationParty) ReceiveParsed(m *ProtocolMessage) ([]OutgoingMessage, error)

ReceiveParsed processes an already-decrypted protocol message directly (bypassing decryption), and returns the reply(s) to transport. It is used to respond to a peer-initiated channel-creation ping that the caller obtained from the normal receive dispatch: creating the party with the PEER's instance UID and feeding it the ping makes us a proper responder in the peer's own protocol instance, so both sides derive the SAME oblivious channel (spec §26; the reference runs SendPingOrEphemeralKey in the received ping's protocol instance). Starting our own instance instead would derive an incompatible channel and stall.

func (*ChannelCreationParty) Start

func (p *ChannelCreationParty) Start() ([]ccpOutgoing, error)

Start runs the SendPing step (spec §26): sign and send the initial ping.

type Committer

type Committer struct {
	prng.PRNG
	// contains filtered or unexported fields
}

Committer implements the extractable random-oracle commitment of spec Section 9.1 (CommitmentWithSHA256), parameterised by its hash function.

commit(tag, value, prng):
    e          <- prng.bytes(hash.Size)
    d          <- value || e
    commitment <- H(tag || d)
    return (commitment, d)

open(commitment, tag, d):
    if H(tag || d) != commitment: fail
    parse d as value || e with len(e) = hash.Size
    return value

func NewCommitter

func NewCommitter(fn hashFunc, rnd prng.PRNG) (c *Committer, err error)

func (*Committer) Commit

func (c *Committer) Commit(tag, val []byte) (com, token []byte, err error)

Commit returns a commitment on (tag, val) and the decommit token needed to open it. token = val || e where e is hash.Size random bytes.

func (*Committer) Open

func (c *Committer) Open(com, tag, token []byte) (val []byte, err error)

Open verifies com against (tag, token) and returns the committed value. The token must be at least hash.Size bytes (an empty committed value is allowed, giving a token of exactly hash.Size bytes).

type ContactGroupBackup

type ContactGroupBackup struct {
	GroupUID            []byte                     `json:"group_uid"`
	PublishedDetails    GroupDetailsBackup         `json:"published_details"`
	LatestDetails       *GroupDetailsBackup        `json:"latest_details,omitempty"`
	TrustedDetails      *GroupDetailsBackup        `json:"trusted_details,omitempty"`
	GroupMembersVersion int                        `json:"group_members_version"`
	Members             []GroupMemberBackup        `json:"members"`
	PendingMembers      []PendingGroupMemberBackup `json:"pending_members"`
}

type ContactIdentityBackup

type ContactIdentityBackup struct {
	ContactIdentity   []byte                `json:"contact_identity"`
	TrustedDetails    IdentityDetailsBackup `json:"trusted_details"`
	PublishedDetails  IdentityDetailsBackup `json:"published_details"`
	TrustLevel        string                `json:"trust_level"`
	TrustOrigins      []ContactTrustOrigin  `json:"trust_origins"`
	ContactGroups     []ContactGroupBackup  `json:"contact_groups"`
	Revoked           bool                  `json:"revoked"`
	ForcefullyTrusted bool                  `json:"forcefully_trusted"`
	OneToOne          bool                  `json:"one_to_one"`
}

type ContactTrustOrigin

type ContactTrustOrigin struct {
	TrustType                           int    `json:"trust_type"`
	MediatorOrGroupOwnerIdentity        []byte `json:"mediator_or_group_owner_identity,omitempty"`
	MediatorOrGroupOwnerTrustLevelMajor int    `json:"mediator_or_group_owner_trust_level_major,omitempty"`
	IdentityServer                      string `json:"identity_server,omitempty"`
	Timestamp                           int64  `json:"timestamp,omitempty"`
}

type CryptoIdentity

type CryptoIdentity struct {
	ServerURL []byte
	Auth      *PublicKeyOverEC // AuthenticationPublicKeyOverEC (class 0x14)
	KEM       *PublicKeyOverEC // KEMPublicKeyOverEC (class 0x12)
}

CryptoIdentity (spec Section 17) is the public identity of an Olvid user: a server URL plus the two public keys used to reach them (authentication and KEM). Its byte serialization ("identity") is what other users store and address messages to.

func CryptoIdentityFromBytes

func CryptoIdentityFromBytes(identity []byte) (*CryptoIdentity, error)

CryptoIdentityFromBytes parses a serialized identity (spec §17, second CryptoIdentity initializer).

func NewCryptoIdentity

func NewCryptoIdentity(serverURL []byte, auth, kem *PublicKeyOverEC) *CryptoIdentity

NewCryptoIdentity builds a CryptoIdentity from a server URL and the two public keys (spec §17, CryptoIdentity initializer).

func (*CryptoIdentity) GetIdentity

func (id *CryptoIdentity) GetIdentity() []byte

GetIdentity returns the byte-array representation of the identity (spec §17, cryptoIdentity.getIdentity):

serverURL || 0x00 || auth.getCompactKey() || kem.getCompactKey()

type DeviceTransferParty

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

DeviceTransferParty is one side of an owned-identity device transfer. Construct it with NewDeviceTransferSource (an existing device, holding the identity + a snapshot to send) or NewDeviceTransferTarget (the joining device). Call the role's methods in the sequence above.

func NewDeviceTransferSource

func NewDeviceTransferSource(owned *OwnedCryptoIdentity, snapshot []byte, connID string, rnd prng.PRNG) *DeviceTransferParty

NewDeviceTransferSource builds the source (existing device) role. snapshot is the encoded ObvSyncSnapshot dictionary to hand the new device; connID is this device's relay connection id (from the transport). The identity's private keys are used to decrypt the target's seed.

func NewDeviceTransferTarget

func NewDeviceTransferTarget(deviceName string, serverURL []byte, rnd prng.PRNG) (*DeviceTransferParty, error)

NewDeviceTransferTarget builds the target (joining device) role, generating a throwaway ephemeral identity whose KEM key wraps the confidential transfer payloads. serverURL seeds that ephemeral identity (cosmetic — only the ephemeral key matters, and its exact bytes are sent to the source).

func (*DeviceTransferParty) CheckSAS

func (p *DeviceTransferParty) CheckSAS(entered []byte) bool

CheckSAS reports whether the digits the user confirmed match this party's SAS. The comparison is constant-time (subtle.ConstantTimeCompare): the SAS is the ceremony's authentication value, so it is matched like the commitment/signature checks beside it rather than with a short-circuiting bytes.Equal.

func (*DeviceTransferParty) CommitmentConnID added in v0.2.2

func (p *DeviceTransferParty) CommitmentConnID() string

CommitmentConnID returns the relay connection id the source embedded in its commitment message (nil/empty before ReceiveCommitment). The reference cross-checks it against the connection id the relay routed the frame from, binding the commitment to that routed source connection and catching a relay that mixes up connections. The engine is transport-agnostic, so the CALLER (which owns the transport and knows the frame's connection id) performs the comparison.

func (*DeviceTransferParty) CommitmentPayload

func (p *DeviceTransferParty) CommitmentPayload() ([]byte, error)

CommitmentPayload commits to a fresh source seed under the source's own identity and returns the {connId, ownedIdentity, commitment} list encrypted to the target's ephemeral key.

func (*DeviceTransferParty) DecommitmentPayload

func (p *DeviceTransferParty) DecommitmentPayload() ([]byte, error)

DecommitmentPayload returns the decommitment encrypted to the target's ephemeral key.

func (*DeviceTransferParty) DeviceName

func (p *DeviceTransferParty) DeviceName() string

DeviceName returns the peer's device name learned during the exchange (target's, from the source's side; empty on the target).

func (*DeviceTransferParty) EphemeralIdentityPayload

func (p *DeviceTransferParty) EphemeralIdentityPayload() []byte

EphemeralIdentityPayload is the target's first message: its ephemeral public identity. (No encryption — it is the key the source will encrypt back to.)

func (*DeviceTransferParty) KeepActiveDevice

func (p *DeviceTransferParty) KeepActiveDevice() []byte

KeepActiveDevice returns the source-designated device UID to keep active (single-device profiles), or nil. The joining device should SetNonExpiring it after registering.

func (*DeviceTransferParty) ReceiveCommitment

func (p *DeviceTransferParty) ReceiveCommitment(payload []byte) error

ReceiveCommitment is the target's handler: decrypt with the ephemeral key, learn the source's identity and the commitment.

func (*DeviceTransferParty) ReceiveDecommitment

func (p *DeviceTransferParty) ReceiveDecommitment(payload []byte) error

ReceiveDecommitment is the target's handler: decrypt, open the commitment to recover the source seed, and compute the shared SAS.

func (*DeviceTransferParty) ReceiveEphemeralIdentity

func (p *DeviceTransferParty) ReceiveEphemeralIdentity(payload []byte) error

ReceiveEphemeralIdentity is the source's handler for the target's first message.

func (*DeviceTransferParty) ReceiveSeed

func (p *DeviceTransferParty) ReceiveSeed(payload []byte) error

ReceiveSeed is the source's handler: decrypt with its own key, learn the target device name + seed, and compute the shared SAS.

func (*DeviceTransferParty) ReceiveSnapshot

func (p *DeviceTransferParty) ReceiveSnapshot(payload []byte) ([]byte, error)

ReceiveSnapshot is the target's final handler: decrypt and return the encoded snapshot dictionary (decode + restore into a store is the caller's job). A deviceUidToKeepActive, if present, is exposed via KeepActiveDevice.

func (*DeviceTransferParty) SAS

func (p *DeviceTransferParty) SAS() []byte

SAS returns the 8 digits both devices show once the seed+decommitment exchange completes (nil before then). The user compares the two screens out of band.

func (*DeviceTransferParty) SeedPayload

func (p *DeviceTransferParty) SeedPayload() ([]byte, error)

SeedPayload derives the target seed (deterministically from the ephemeral MAC key and the source commitment, per the reference) and returns {deviceName, seedTarget} encrypted to the transferred (source) identity's key.

func (*DeviceTransferParty) SnapshotPayload

func (p *DeviceTransferParty) SnapshotPayload(deviceUIDToKeepActive []byte) ([]byte, error)

SnapshotPayload returns the transfer snapshot (optionally with a device UID to keep active on a single-device profile) encrypted to the target's ephemeral key. Call after the SAS is confirmed.

type Error

type Error string

func (Error) Error

func (e Error) Error() string

type FullRatchetParty

type FullRatchetParty struct {

	// Done is set once the party has updated its seed.
	Done bool
	// contains filtered or unexported fields
}

FullRatchetParty is one device running the Full Ratchet protocol over an existing oblivious channel.

func NewFullRatchetParty

func NewFullRatchetParty(owned *OwnedCryptoIdentity, deviceUID []byte, contact *CryptoIdentity, contactDeviceUID []byte, channel *ObliviousChannel, instanceUID [32]byte, initiator bool, rnd prng.PRNG) *FullRatchetParty

NewFullRatchetParty creates a party. Exactly one of the two parties in a run must be the initiator (whose send direction is refreshed).

func (*FullRatchetParty) Begin

func (p *FullRatchetParty) Begin() ([]OutgoingMessage, error)

Begin starts the initiator and returns the outgoing AliceEphemeral message (sent over the existing oblivious channel).

func (*FullRatchetParty) Cancelled

func (p *FullRatchetParty) Cancelled() bool

Cancelled reports whether the run aborted (e.g. instance-UID mismatch).

func (*FullRatchetParty) ContactDeviceUID

func (p *FullRatchetParty) ContactDeviceUID() []byte

ContactDeviceUID returns the peer device UID this run refreshes against.

func (*FullRatchetParty) InstanceUID

func (p *FullRatchetParty) InstanceUID() [32]byte

InstanceUID returns the protocol-instance UID of this run.

func (*FullRatchetParty) IsDone

func (p *FullRatchetParty) IsDone() bool

IsDone reports whether this party has committed its seed refresh.

func (*FullRatchetParty) ReceiveDecoded

func (p *FullRatchetParty) ReceiveDecoded(m *ProtocolMessage) ([]OutgoingMessage, error)

ReceiveDecoded feeds an already-decrypted full-ratchet protocol message to the party (the oblivious channel layer decrypted it) and returns any replies. Use this from a client that has already decrypted the envelope, rather than the in-memory deliver() which decrypts itself.

func (*FullRatchetParty) Restart

func (p *FullRatchetParty) Restart() ([]ccpOutgoing, error)

Restart re-sends Alice's ephemeral key with the counter incremented (same nonce), for when a run stalls (reference AliceResendEphemeralKeyStep, driven by the stuck-ratchet restart threshold). Only valid for the initiator while awaiting K1 or the ack; a no-op otherwise.

func (*FullRatchetParty) RestartOutgoing

func (p *FullRatchetParty) RestartOutgoing() ([]OutgoingMessage, error)

RestartOutgoing re-sends the initiator's ephemeral key with the counter incremented, for a stalled run within the same instance.

func (*FullRatchetParty) SetNow

func (p *FullRatchetParty) SetNow(nowMs int64)

SetNow sets the wall-clock timestamp (ms since epoch) used when this party commits a send-seed full ratchet (reference updateSendSeed resets the validity clock to "now").

func (*FullRatchetParty) Start

func (p *FullRatchetParty) Start() ([]ccpOutgoing, error)

Start runs the AliceSendEphemeralKey step (spec §33): generate an ephemeral KEM key and send it over the oblivious channel.

type GroupDetailsBackup

type GroupDetailsBackup struct {
	Version           int    `json:"version"`
	SerializedDetails string `json:"serialized_details"`
	PhotoServerLabel  []byte `json:"photo_server_label,omitempty"`
	PhotoServerKey    []byte `json:"photo_server_key,omitempty"`
}

type GroupIdentifier

type GroupIdentifier struct {
	GroupUID  []byte // 32-byte SHA256 of the first administrators-chain block
	ServerURL string
	Category  int64
}

GroupIdentifier uniquely identifies a group v2 (spec §34, GroupV2.Identifier).

func DecodeGroupIdentifier

func DecodeGroupIdentifier(b []byte) (GroupIdentifier, error)

DecodeGroupIdentifier is the inverse of Encode.

func ParseGroupLeftBroadcast added in v0.2.5

func ParseGroupLeftBroadcast(m *ProtocolMessage) (gid GroupIdentifier, err error)

ParseGroupLeftBroadcast extracts the group identifier from an invitation-rejected / group-left broadcast message (id 16). The message carries no blob keys — the recipient re-fetches the group with the keys it already holds.

func ParseKickMessage

func ParseKickMessage(m *ProtocolMessage) (gid GroupIdentifier, encryptedChain, signature []byte, err error)

ParseKickMessage parses a Kick protocol message.

func ParsePingMessage

func ParsePingMessage(m *ProtocolMessage) (gid GroupIdentifier, invitationNonce, signature []byte, isResponse bool, err error)

ParsePingMessage parses a Ping protocol message.

func (GroupIdentifier) Bytes

func (g GroupIdentifier) Bytes() []byte

Bytes is the byte representation used inside signatures (== Encode).

func (GroupIdentifier) Encode

func (g GroupIdentifier) Encode() []byte

Encode serializes the identifier as encodeList(groupUid, serverURL, category) (spec §34, Identifier.encode).

func (GroupIdentifier) ProtocolInstanceUID

func (g GroupIdentifier) ProtocolInstanceUID() ([32]byte, error)

ProtocolInstanceUID derives the 32-byte protocol-instance UID identifying this group's protocol runs (reference GroupV2.Identifier.computeProtocolInstanceUid): a default PRNG seeded with the encoded identifier, read for 32 bytes.

type GroupMember

type GroupMember struct {
	Identity             *CryptoIdentity
	Permissions          []string
	SerializedDetails    string
	GroupInvitationNonce []byte // 16 bytes
}

GroupMember is a member entry stored inside the blob (spec §34, IdentityAndPermissionsAndDetails).

func (*GroupMember) IsAdmin

func (m *GroupMember) IsAdmin() bool

IsAdmin reports whether the member holds the group-admin permission.

type GroupMemberBackup

type GroupMemberBackup struct {
	ContactIdentity []byte `json:"contact_identity"`
}

type GroupV2Backup

type GroupV2Backup struct {
	Version                  int64                        `json:"version"`
	Category                 int64                        `json:"category"`
	GroupUID                 []byte                       `json:"group_uid"`
	ServerURL                string                       `json:"server_url"`
	InvitationNonce          []byte                       `json:"invitation_nonce,omitempty"`
	MainSeed                 []byte                       `json:"main_seed,omitempty"`
	VersionSeed              []byte                       `json:"version_seed,omitempty"`
	Permissions              []string                     `json:"permissions,omitempty"`
	EncodedAdminKey          []byte                       `json:"encoded_admin_key,omitempty"`
	VerifiedAdminChain       []byte                       `json:"verified_admin_chain,omitempty"`
	SerializedSharedSettings string                       `json:"serialized_shared_settings,omitempty"`
	Members                  []GroupV2MemberBackup        `json:"members"`
	PendingMembers           []GroupV2PendingMemberBackup `json:"pending_members"`
	Details                  GroupDetailsBackup           `json:"details"`
	TrustedDetails           *GroupDetailsBackup          `json:"trusted_details,omitempty"`
	SerializedGroupType      string                       `json:"serialized_group_type,omitempty"`
}

GroupV2Backup is a groups-v2 entry (ref ContactGroupV2 backup snapshot). Field names match the reference so a real Olvid app can restore it. It is populated directly from the library's live group state (GroupIdentifier + BlobKeys + ServerBlob).

func GroupV2BackupFrom

func GroupV2BackupFrom(gid GroupIdentifier, keys *BlobKeys, blob *ServerBlob, ownNonce []byte, ownPermissions []string) GroupV2Backup

GroupV2BackupFrom converts the library's live group-v2 state into a backup node (ref ContactGroupV2 snapshot). ownNonce/ownPermissions describe this identity's own membership; keys and blob may carry nil fields (e.g. a non-admin has no admin key).

type GroupV2MemberBackup

type GroupV2MemberBackup struct {
	ContactIdentity []byte   `json:"contact_identity"`
	Permissions     []string `json:"permissions"`
	InvitationNonce []byte   `json:"invitation_nonce,omitempty"`
}

type GroupV2PendingMemberBackup

type GroupV2PendingMemberBackup struct {
	ContactIdentity   []byte   `json:"contact_identity"`
	Permissions       []string `json:"permissions"`
	InvitationNonce   []byte   `json:"invitation_nonce,omitempty"`
	SerializedDetails string   `json:"serialized_details,omitempty"`
}

type IdentityDetailsBackup

type IdentityDetailsBackup struct {
	Version           int    `json:"version"`
	SerializedDetails string `json:"serialized_details"`
	PhotoServerLabel  []byte `json:"photo_server_label,omitempty"`
	PhotoServerKey    []byte `json:"photo_server_key,omitempty"`
}

type IdentityDetailsWithVersion

type IdentityDetailsWithVersion struct {
	Version int                       `json:"version"`
	Details SerializedIdentityDetails `json:"details"`
}

IdentityDetailsWithVersion mirrors the reference JsonIdentityDetailsWithVersionAndPhoto: the published details plus a monotonic version the receiver uses to reject a stale update (it accepts only a version strictly greater than the one it already stored). Photo fields are omitted — this library carries no identity photos.

type JSONWebKey

type JSONWebKey struct {
	Kty string `json:"kty"` // "RSA" or "EC"
	// RSA public key
	N string `json:"n"`
	E string `json:"e"`
	// EC public key
	Crv string `json:"crv"` // "P-256" / "P-384" / "P-521"
	X   string `json:"x"`
	Y   string `json:"y"`
}

JSONWebKey is a public key in JWK form (RFC 7517), enough to verify a JWS.

type KDF

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

KDF implements the spec's KDFFromPRNGWithHMACWithSHA256 (Section 8.1).

procedure KDFFromPRNGWithHMACWithSHA256.compute(seed, T)
    prng = PRNGWithHMACWithSHA256(seed)
    b    <- prng.bytes(T.length)
    return T(b)

Compute only produces the raw key material of the requested length; the caller wraps the bytes into the concrete SymmetricKey subtype T. This keeps the KDF decoupled from the individual key constructors.

func NewKDFFromPRNGWithHMACWithSHA256

func NewKDFFromPRNGWithHMACWithSHA256() (kdf *KDF)

NewKDFFromPRNGWithHMACWithSHA256 returns the SHA-256 based KDF.

func (*KDF) Compute

func (kdf *KDF) Compute(seed []byte, length uint32) (b []byte, err error)

Compute derives length bytes of key material from seed. It fails (as per the spec) when the seed is too short to instantiate the underlying PRNG.

type MAC

type MAC interface {
	Sum(m []byte) (out []byte) // compute() in spec
	Len() (l uint32)           // finalOutputSize() in spec
}

XXX the underlying implementation should take a MACKey when initializing

type MacKey

type MacKey struct {
	*types.SymmetricKey
	// contains filtered or unexported fields
}

func NewHmacSha256KeyFromBytes

func NewHmacSha256KeyFromBytes(b []byte) (mk *MacKey, err error)

func NewHmacSha256KeyFromKDF

func NewHmacSha256KeyFromKDF(seed []byte) (mk *MacKey, err error)

func NewHmacSha256KeyFromPRNG

func NewHmacSha256KeyFromPRNG(rnd prng.PRNG) (mk *MacKey, err error)

func (*MacKey) Len

func (mk *MacKey) Len() (l uint32)

func (*MacKey) Sum

func (mk *MacKey) Sum(m []byte) (out []byte)

type ObliviousChannel

type ObliviousChannel struct {
	LookAhead int
	// contains filtered or unexported fields
}

ObliviousChannel is one party's view of a bidirectional oblivious channel.

func DecodeObliviousChannel

func DecodeObliviousChannel(b []byte) (*ObliviousChannel, error)

DecodeObliviousChannel reconstructs a channel from Encode's output. It accepts three forms: 4 = legacy (single receive chain, no trigger counters), 9 = with trigger counters, 10 = with the full receive-provisions list.

func EstablishObliviousChannelPair

func EstablishObliviousChannelPair(k1, k2 *AuthEncKey, aliceDeviceUID, bobDeviceUID []byte) (alice, bob *ObliviousChannel, err error)

EstablishObliviousChannelPair builds both parties' channels from the two KEM-exchanged keys and the two device UIDs (test/utility helper mirroring the end of the Channel Creation protocol, spec §26).

func NewObliviousChannel

func NewObliviousChannel(seed, selfDeviceUID, remoteDeviceUID []byte) (*ObliviousChannel, error)

NewObliviousChannel builds one party's channel from the shared seed and the device UIDs (self = this party, remote = peer). The send direction is diversified with the sender's own UID so it lines up with the peer's receive direction.

func (*ObliviousChannel) DecryptMessage

func (c *ObliviousChannel) DecryptMessage(header, ciphertext []byte) (encodedPayload []byte, err error)

DecryptMessage reverses EncryptMessage on the receiving party's channel.

func (*ObliviousChannel) Encode

func (c *ObliviousChannel) Encode() []byte

Encode serializes the channel's ratchet state for local persistence: send seed, look-ahead, full-ratchet trigger counters, and the list of receive provisions. It holds only the *current* seeds, preserving forward secrecy for past messages. Not part of the Olvid wire protocol. Elements [1] and [3] mirror the newest provision so a pre-provisions decoder can still read it.

func (*ObliviousChannel) EncryptMessage

func (c *ObliviousChannel) EncryptMessage(encodedPayload []byte, rnd prng.PRNG) (header, ciphertext []byte, err error)

EncryptMessage encrypts an encoded payload on the oblivious channel (spec §23.1, oblivious channel): the message key is wrapped by a fresh ratcheted channel key and the header carries keyId || wrapped-key.

func (*ObliviousChannel) FullRatchetInProgress

func (c *ObliviousChannel) FullRatchetInProgress() bool

FullRatchetInProgress reports whether a send-seed full ratchet is under way.

func (*ObliviousChannel) MaybeTriggerFullRatchet

func (c *ObliviousChannel) MaybeTriggerFullRatchet(nowMs int64) bool

MaybeTriggerFullRatchet is called by the application send path after a message has been encrypted (reference gates the trigger on !protocolMessage — protocol senders never call this). It reports whether a send-seed full ratchet should be started now, and if so records that a full-ratchet run is in progress so it is not re-triggered on every subsequent send. The validity clock starts at the first send.

func (*ObliviousChannel) RatchetReceiveSeed

func (c *ObliviousChannel) RatchetReceiveSeed(newSeed, remoteDeviceUID []byte, nowMs int64) error

RatchetReceiveSeed re-seeds the receive direction after a full ratchet initiated by the peer (spec §33). It APPENDS a new receive provision rather than replacing the current one, so a message still in flight under the old seed decrypts across the boundary; older provisions are pruned by age and count (reference createNewProvision + ProvisionedKeyMaterial expiry).

func (*ObliviousChannel) RatchetSendSeed

func (c *ObliviousChannel) RatchetSendSeed(newSeed, selfDeviceUID []byte, nowMs int64) error

RatchetSendSeed re-seeds the send direction after a full ratchet (spec §33): a fresh channel seed is diversified with the sender's own device UID. It also resets the trigger bookkeeping (reference updateSendSeed): the message counter baseline and validity clock move to now, and the in-progress flag clears.

type ObvURLIdentity

type ObvURLIdentity struct {
	Identity    *CryptoIdentity
	DisplayName string
}

ObvURLIdentity is the (identity, display name) pair an invitation link carries.

func ParseInvitationLink(link string) (*ObvURLIdentity, error)

ParseInvitationLink parses an Olvid invitation/QR link into its identity + display name. It accepts the sharing (/#) and mutual-scan (/1#) forms and base64url with or without padding (and, leniently, standard base64 with +/ that some sources may carry).

func (u *ObvURLIdentity) InvitationLink() string

InvitationLink returns the sharing invitation link for this identity + display name.

type OutgoingMessage

type OutgoingMessage struct {
	ViaOblivious bool
	Header       []byte
	Ciphertext   []byte
}

OutgoingMessage is a channel-encrypted protocol message addressed to the party's contact device, ready to transport (e.g. upload to the server). It is the exported form used to drive the protocol over a network.

type OwnedCryptoIdentity

type OwnedCryptoIdentity struct {
	ServerURL []byte

	AuthPublicKey  *PublicKeyOverEC
	AuthPrivateKey *PrivateKeyOverEC
	KEMPublicKey   *PublicKeyOverEC
	KEMPrivateKey  *PrivateKeyOverEC
	SecretMACKey   *MacKey
}

OwnedCryptoIdentity (spec Section 18) is a CryptoIdentity whose owner also holds the private keys: the authentication and KEM key pairs plus a secret MAC key.

func DecodeOwnedCryptoIdentity

func DecodeOwnedCryptoIdentity(b []byte) (*OwnedCryptoIdentity, error)

DecodeOwnedCryptoIdentity is the inverse of Encode.

func GenerateOwnedCryptoIdentity

func GenerateOwnedCryptoIdentity(serverURL []byte, rnd prng.PRNG) (*OwnedCryptoIdentity, error)

GenerateOwnedCryptoIdentity creates a fresh owned identity (spec §18, generateOwnedCryptoIdentity): the authentication key pair is over MDC, the KEM key pair over Curve25519, and the secret key is an HMAC-SHA-256 key.

func ReconstructOwnedIdentity

func ReconstructOwnedIdentity(identityBytes, authPrivEnc, kemPrivEnc, macKeyEnc []byte) (*OwnedCryptoIdentity, error)

ReconstructOwnedIdentity rebuilds an owned identity from the parts a backup stores separately (spec §36.1 private_identity + owned_identity): the public identity bytes and the Olvid-encoded server-authentication private key, encryption private key, and MAC key (as produced by PrivateKeyOverEC.Encode and the symmetric-key encoding). Used by restore.

func (*OwnedCryptoIdentity) Encode

func (o *OwnedCryptoIdentity) Encode() []byte

Encode serializes the owned identity (including its private keys) as an encoded list. This is a convenience for local persistence — it is NOT part of the Olvid wire protocol and must be stored securely.

func (*OwnedCryptoIdentity) GetCryptoIdentity

func (o *OwnedCryptoIdentity) GetCryptoIdentity() *CryptoIdentity

GetCryptoIdentity returns the public CryptoIdentity for this owned identity (spec §18, getCryptoIdentity).

func (o *OwnedCryptoIdentity) InvitationLink(displayName string) string

InvitationLink builds this owned identity's sharing invitation link with the given display name, to hand to a contact so they can add you.

type OwnedIdentityBackup

type OwnedIdentityBackup struct {
	OwnedIdentity     []byte                  `json:"owned_identity"`
	PrivateIdentity   PrivateIdentityBackup   `json:"private_identity"`
	PublishedDetails  IdentityDetailsBackup   `json:"published_details"`
	LatestDetails     IdentityDetailsBackup   `json:"latest_details"`
	APIKey            string                  `json:"api_key,omitempty"`
	ContactIdentities []ContactIdentityBackup `json:"contact_identities"`
	OwnedGroups       []ContactGroupBackup    `json:"owned_groups"`     // groups v1 (legacy)
	GroupsV2          []GroupV2Backup         `json:"groups_v2"`        // groups v2 (current)
	Active            *bool                   `json:"active,omitempty"` // owned identity active flag
}

func OwnedIdentityBackupFromIdentity

func OwnedIdentityBackupFromIdentity(o *OwnedCryptoIdentity, published, latest IdentityDetailsBackup, apiKey string) OwnedIdentityBackup

OwnedIdentityBackupFromIdentity builds the owned-identity backup node from an owned identity: its public identity bytes, the three private keys (Olvid-encoded), and the supplied details. Contact and owned-group arrays start empty; the caller may append.

type PendingGroupMemberBackup

type PendingGroupMemberBackup struct {
	ContactIdentity   []byte `json:"contact_identity"`
	SerializedDetails string `json:"serialized_details"`
	Declined          bool   `json:"declined"`
}

type PreKey

type PreKey struct {
	DeviceUID     []byte
	KeyID         []byte // 32-byte random identifier
	EncryptionKey *PublicKeyOverEC
	Expiration    int64 // ms since epoch
	Capabilities  []string
}

PreKey is a device pre-key (spec §24).

func ParseSignedPreKey

func ParseSignedPreKey(signedPreKey []byte, ownerAuth *PublicKeyOverEC, serverTimestamp int64) (*PreKey, error)

ParseSignedPreKey verifies a signed pre-key against the owner's authentication public key and parses it (spec §24 / PreKeyBlobOnServer). When serverTimestamp > 0, a pre-key whose expiration is not strictly after it is rejected.

func (*PreKey) Sign

func (pk *PreKey) Sign(owned *OwnedCryptoIdentity, rnd prng.PRNG) ([]byte, error)

Sign returns the encoded signed pre-key: encodeList(payload, signature), where signature is over payload with the owner's authentication key.

type PrivateIdentityBackup

type PrivateIdentityBackup struct {
	ServerAuthenticationPrivateKey []byte `json:"server_authentication_private_key"`
	EncryptionPrivateKey           []byte `json:"encryption_private_key"`
	MacKey                         []byte `json:"mac_key"`
}

type PrivateKeyOverEC

type PrivateKeyOverEC struct {
	*types.PrivateKey
	Curve  *ec.Curve
	Scalar *big.Int
}

PrivateKeyOverEC is the concrete representation of a private key over a curve.

func DecodePrivateKeyOverEC

func DecodePrivateKeyOverEC(b []byte) (*PrivateKeyOverEC, error)

DecodePrivateKeyOverEC is the inverse of PrivateKeyOverEC.Encode.

func (*PrivateKeyOverEC) Encode

func (sk *PrivateKeyOverEC) Encode() []byte

Encode returns the standard key encoding (0x92 for private keys).

type ProtocolMessage

type ProtocolMessage struct {
	ProtocolID  uint32
	InstanceUID [32]byte
	MessageID   uint32
	Inputs      [][]byte // each element is an already-encoded value
}

ProtocolMessage is the structure of a protocol message (spec §22.1): an encoded list of [protocolId, 32-byte protocol-instance uid, protocolMessageId, encoded list of inputs].

func BuildCapabilitiesMessage added in v0.3.0

func BuildCapabilitiesMessage(rawCaps []string, isResponse, toSelf bool, rnd prng.PRNG) (*ProtocolMessage, error)

BuildCapabilitiesMessage builds the channel message that announces rawCaps to a peer: to a contact (toSelf=false, id 3) or to one of our own devices (toSelf=true, id 4). isResponse must be true when replying to a peer's announcement, so the exchange doesn't loop. The instance UID is random — the recipient processes each message statelessly and never correlates by instance.

func BuildContactDeletionNotification added in v0.3.0

func BuildContactDeletionNotification(rnd prng.PRNG) (*ProtocolMessage, error)

BuildContactDeletionNotification builds the "I removed you as a contact" message (id 1), sent to the contact over their channel. Empty payload — the recipient identifies us from the channel.

func BuildContactDowngradeNotification added in v0.3.0

func BuildContactDowngradeNotification(rnd prng.PRNG) (*ProtocolMessage, error)

BuildContactDowngradeNotification builds the "I downgraded you from one-to-one" message (id 4).

func BuildGroupInvitationBroadcast

func BuildGroupInvitationBroadcast(gid GroupIdentifier, version int64, keys *BlobKeys) (*ProtocolMessage, error)

BuildGroupInvitationBroadcast builds the broadcast variant (id 5), sent over an asymmetric channel to a member we hold no oblivious channel with: inputs = [gid, version, blobKeys]. It lets a freshly-added member receive the invitation without a channel first.

func BuildGroupInvitationMessage

func BuildGroupInvitationMessage(gid GroupIdentifier, version int64, keys *BlobKeys, notifiedDeviceUIDs [][]byte) (*ProtocolMessage, error)

BuildGroupInvitationMessage builds the InvitationOrMembersUpdate protocol message (reference InvitationOrMembersUpdateMessage): inputs = [gid, version, blobKeys, notifiedDeviceUids].

func BuildGroupInvitationPropagated

func BuildGroupInvitationPropagated(gid GroupIdentifier, version int64, keys *BlobKeys, inviter *CryptoIdentity) (*ProtocolMessage, error)

BuildGroupInvitationPropagated builds the own-device propagation variant (id 6): inputs = [gid, version, blobKeys] plus the inviter identity when known.

func BuildKickMessage

func BuildKickMessage(gid GroupIdentifier, encryptedChain, signature []byte) (*ProtocolMessage, error)

BuildKickMessage builds a Kick protocol message (reference KickMessage): inputs = [gid, encryptedAdministratorsChain, signature].

func BuildOwnedIdentityDeletedMessage added in v0.3.0

func BuildOwnedIdentityDeletedMessage(deletedIdentity, signature []byte, rnd prng.PRNG) (*ProtocolMessage, error)

BuildOwnedIdentityDeletedMessage builds the ContactOwnedIdentityWasDeleted message (id 1) a deleter sends to a contact: the deleter's own identity and the recipient-bound signature.

func BuildPerformContactDeviceDiscovery added in v0.3.0

func BuildPerformContactDeviceDiscovery(rnd prng.PRNG) (*ProtocolMessage, error)

BuildPerformContactDeviceDiscovery builds the "please re-discover my devices" nudge (id 6), sent to a contact after we change our own device set (e.g. deactivate a device).

func BuildPingMessage

func BuildPingMessage(gid GroupIdentifier, invitationNonce, signature []byte, isResponse bool) (*ProtocolMessage, error)

BuildPingMessage builds a Ping protocol message (reference PingMessage): inputs = [gid, invitationNonce, signature, isResponse].

func BuildPropagateContactDeletion added in v0.3.0

func BuildPropagateContactDeletion(contactIdentity []byte, rnd prng.PRNG) (*ProtocolMessage, error)

BuildPropagateContactDeletion builds the message telling our OWN other devices to delete a contact (id 2), carrying the contact identity.

func BuildPropagateContactDowngrade added in v0.3.0

func BuildPropagateContactDowngrade(contactIdentity []byte, rnd prng.PRNG) (*ProtocolMessage, error)

BuildPropagateContactDowngrade builds the message telling our OWN other devices to downgrade a contact from one-to-one (id 5), carrying the contact identity.

func BuildSingleItemSyncMessage

func BuildSingleItemSyncMessage(atom *SyncAtom) (*ProtocolMessage, error)

BuildSingleItemSyncMessage wraps a sync atom as the SingleItemSyncMessage broadcast to the identity's other owned devices.

func BuildSnapshotSyncMessage

func BuildSnapshotSyncMessage(snapshot *Snapshot) *ProtocolMessage

BuildSnapshotSyncMessage wraps a full profile snapshot for exchange with an own device during reconciliation (ref the SynchronizationProtocol snapshot exchange).

func DecodeProtocolEnvelope

func DecodeProtocolEnvelope(b []byte) (*ProtocolMessage, error)

DecodeProtocolEnvelope parses a channel plaintext produced by EncodeEnvelope, returning the protocol message. It rejects non-protocol message types.

func NewIntroductionAckMessage

func NewIntroductionAckMessage(instanceUID [32]byte) *ProtocolMessage

NewIntroductionAckMessage (message 6) confirms trust was established on the sender's side.

func NewMediatorInvitationMessage

func NewMediatorInvitationMessage(instanceUID [32]byte, contactIdentity []byte, serializedDetails string) *ProtocolMessage

NewMediatorInvitationMessage (message 1) is sent by the mediator to one invitee, naming the other contact and their published details.

func NewNotifyAcceptedMessage

func NewNotifyAcceptedMessage(instanceUID [32]byte, deviceUIDs [][]byte, signature []byte) *ProtocolMessage

NewNotifyAcceptedMessage (message 4) is sent by an accepting invitee to the other party: it carries the sender's device UIDs and the signature over [mediator, other, self].

func NewPropagateOwnDetailsMessage

func NewPropagateOwnDetailsMessage(instanceUID [32]byte, jsonDetailsWithVersion string) *ProtocolMessage

NewPropagateOwnDetailsMessage builds a PROPAGATE_OWN_DETAILS message (message 3) for our own other devices.

func NewSendDetailsMessage

func NewSendDetailsMessage(instanceUID [32]byte, jsonDetailsWithVersion string) *ProtocolMessage

NewSendDetailsMessage builds a SEND_DETAILS protocol message (ProtocolID 6, message 2) carrying the serialized details+version JSON, to be posted over an oblivious channel to a contact. instanceUID identifies the publication run — a fresh random UID per publication.

func (*ProtocolMessage) Encode

func (m *ProtocolMessage) Encode() []byte

Encode returns the 4-element encoded list of the protocol message.

func (*ProtocolMessage) EncodeEnvelope

func (m *ProtocolMessage) EncodeEnvelope() []byte

EncodeEnvelope wraps the protocol message in the message-type envelope used as the (padded) channel plaintext (spec §22): encodeList(messageType, elements).

type PublicKeyOverEC

type PublicKeyOverEC struct {
	*types.PublicKey
	Curve *ec.Curve
	Point *ec.Point // Point.Y always set; Point.X may be nil
}

PublicKeyOverEC is the concrete representation of a public key over a curve.

func DecodeGroupAdminPublicKey

func DecodeGroupAdminPublicKey(b []byte) (*PublicKeyOverEC, error)

DecodeGroupAdminPublicKey is the inverse of EncodeGroupAdminPublicKey.

func (*PublicKeyOverEC) Encode

func (pk *PublicKeyOverEC) Encode() []byte

Encode returns the standard key encoding (0x91 for public keys).

func (*PublicKeyOverEC) GetCompactKey

func (pk *PublicKeyOverEC) GetCompactKey() []byte

GetCompactKey returns algoImplemByteId ∥ bytesFromBigUInt(pk.y) (spec §13).

type SASParty

type SASParty struct {

	// Results, available once WAITING_FOR_USER_SAS is reached:
	SASToDisplay []byte // the 4 digits this user shows the peer

	Trusted bool // mutual trust confirmed (peer's confirmation received)
	// contains filtered or unexported fields
}

SASParty is one user running the Trust Establishment SAS protocol.

func NewSASParty

func NewSASParty(owned *OwnedCryptoIdentity, contact *CryptoIdentity, instanceUID [32]byte, isAlice bool, ownDeviceUIDs [][]byte, ownDetails string, rnd prng.PRNG) *SASParty

NewSASParty creates a party. Alice is the initiator (she commits first). ownDeviceUIDs and ownDetails are placed in the outgoing messages so the peer learns this party's devices and display name (required for interop and for creating the channel afterwards).

func (*SASParty) AwaitingSAS

func (p *SASParty) AwaitingSAS() bool

AwaitingSAS reports whether the message exchange is complete and the party is waiting for the out-of-band SAS comparison (call SASToDisplay / CheckSAS).

func (*SASParty) Begin

func (p *SASParty) Begin() ([]OutgoingMessage, error)

Begin starts the protocol from the initiator side (sending the commitment).

func (*SASParty) BuildPropagateCommitment added in v0.3.7

func (p *SASParty) BuildPropagateCommitment() *ProtocolMessage

BuildPropagateCommitment builds PropagateCommitmentToBobDevices (id 4), broadcast by the responder after receiving the commitment. Valid after processing it. Inputs: [contactId, contactSerializedDetails, contactDeviceUids, commitment].

func (*SASParty) BuildPropagateConfirmation added in v0.3.7

func (p *SASParty) BuildPropagateConfirmation(accepted bool) *ProtocolMessage

BuildPropagateConfirmation builds PropagateConfirmationToBobDevices (id 6). Inputs: [accepted].

func (*SASParty) BuildPropagateEnteredSAS added in v0.3.7

func (p *SASParty) BuildPropagateEnteredSAS() *ProtocolMessage

BuildPropagateEnteredSAS builds PropagateEnteredSasToOtherDevices (id 12), carrying the digits the user entered (the peer's half = our expectedSAS). Valid after CheckSAS. Inputs: [sasEnteredByUser].

func (*SASParty) BuildPropagateInvitation added in v0.3.7

func (p *SASParty) BuildPropagateInvitation(contactDisplayName string) *ProtocolMessage

BuildPropagateInvitation builds PropagateInvitationToAliceDevices (id 2), broadcast by the initiator after sending the commitment. Valid after Start(). Inputs: [contactId, contactDisplayName, decommitment, seedAlice].

func (*SASParty) Cancelled added in v0.2.5

func (p *SASParty) Cancelled() bool

Cancelled reports whether the exchange was cancelled by the protocol (a failed commitment open or a replayed commitment), so a caller can drop it.

func (*SASParty) CheckSAS

func (p *SASParty) CheckSAS(enteredFromContact []byte) ([]OutgoingMessage, bool, error)

CheckSAS stands in for the out-of-band comparison + user entry: the user enters the digits the peer displayed. On a match this party sends its mutual-trust confirmation (msg 13) and, once the peer's confirmation has also arrived, trust is established. Returns the outgoing confirmation to transport (nil if the SAS did not match) and whether it matched.

func (*SASParty) InstanceUID added in v0.2.5

func (p *SASParty) InstanceUID() [32]byte

InstanceUID returns the protocol-instance UID of this exchange (for dispatcher routing).

func (*SASParty) MutualTrustConfirmed

func (p *SASParty) MutualTrustConfirmed() bool

MutualTrustConfirmed reports whether mutual trust has been established (both sides confirmed). The contact may now be created and a channel established.

func (*SASParty) PeerDetails

func (p *SASParty) PeerDetails() string

PeerDetails returns the peer's serialized display-name details from the exchange.

func (*SASParty) PeerDeviceUIDs

func (p *SASParty) PeerDeviceUIDs() [][]byte

PeerDeviceUIDs returns the peer's device UIDs learned during the exchange (for §26).

func (*SASParty) Receive

func (p *SASParty) Receive(header, ciphertext []byte) ([]OutgoingMessage, error)

Receive processes one incoming channel-encrypted (header, ciphertext) pair (SAS runs over the asymmetric channel). Messages not for this run (wrong protocol id or instance) error.

func (*SASParty) ReceiveParsed added in v0.2.5

func (p *SASParty) ReceiveParsed(m *ProtocolMessage) ([]OutgoingMessage, error)

ReceiveParsed processes an already-decoded protocol message (from a caller's unified receive dispatch), bypassing decryption. It advances the exchange and returns the reply(s) to transport. A message for a different protocol/instance errors, so the caller can route by instance UID and run several exchanges concurrently.

func (*SASParty) Start

func (p *SASParty) Start() ([]ccpOutgoing, error)

Start runs the SendCommitment step (spec §25): commit to a random seed under our own identity and send [identity, serializedDetails, deviceUids, commitment] (reference layout).

func (*SASParty) StateName

func (p *SASParty) StateName() string

StateName returns a human-readable name for the party's current protocol state (diagnostics).

type SerializedIdentityDetails

type SerializedIdentityDetails struct {
	FirstName string `json:"first_name,omitempty"`
	LastName  string `json:"last_name,omitempty"`
	Company   string `json:"company,omitempty"`
	Position  string `json:"position,omitempty"`
}

SerializedIdentityDetails mirrors Olvid's JsonIdentityDetails (spec §17): the human-readable details of an identity, serialized as JSON and carried in trust-establishment (SAS) and group messages. The JSON property names match the reference (@JsonProperty), and null/empty fields are omitted (the reference serializes with Jackson's NON_NULL inclusion). This value is transmitted and parsed by the peer — it is NOT committed or signed during trust establishment — so it must be valid JSON the reference can parse, but need not be byte-exact.

func ParseIdentityDetailsWithVersion

func ParseIdentityDetailsWithVersion(s string) (SerializedIdentityDetails, int, error)

ParseIdentityDetailsWithVersion parses that JSON back into details and version.

type ServerBlob

type ServerBlob struct {
	Chain                  *AdministratorsChain
	Members                []*GroupMember
	Version                int64
	SerializedGroupDetails string
	SerializedGroupType    string // optional ("" means absent)
}

ServerBlob is the group structure encrypted and stored on the server (spec §34, GroupV2.ServerBlob).

func DecodeServerBlob

func DecodeServerBlob(b []byte) (*ServerBlob, error)

DecodeServerBlob parses an encoded server blob (spec §34, ServerBlob.of).

func (*ServerBlob) ConsolidateLeaveLogs

func (b *ServerBlob) ConsolidateLeaveLogs(gid GroupIdentifier, logItems [][]byte) []*CryptoIdentity

ConsolidateLeaveLogs removes members whose leave was proven by a log item and returns the identities that left (spec §34, ServerBlob.consolidateWithLogEntries).

func (*ServerBlob) EncodePlain

func (b *ServerBlob) EncodePlain() []byte

EncodePlain returns the plaintext (unencrypted) blob encoding, the inverse of DecodeServerBlob. Used for local persistence; the wire form is EncryptServerBlob.

type SettingsNode

type SettingsNode struct {
	AutoJoinGroups          *string
	SendReadReceipt         *bool
	UnarchiveOnNotification *bool
	Domain                  []string // fields this snapshot covers; defaults to all on encode if empty
}

func (*SettingsNode) ContentsEqual

func (n *SettingsNode) ContentsEqual(o SnapshotNode) bool

func (*SettingsNode) Diff

func (n *SettingsNode) Diff(o SnapshotNode) ([]SyncDiff, error)

func (*SettingsNode) Encode

func (n *SettingsNode) Encode() []byte

Encode serializes the node as encodeList( encodeList(domain...), encodeList(entry...) ) where each entry is encodeList(fieldName, value). Only in-domain, set fields are emitted, in settingsFields order for a deterministic layout.

func (*SettingsNode) Tag

func (n *SettingsNode) Tag() string

type Snapshot

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

Snapshot is a set of domain nodes keyed by tag (ref ObvSyncSnapshot).

func DecodeSnapshot

func DecodeSnapshot(b []byte, decoders SnapshotDecoders) (*Snapshot, error)

DecodeSnapshot decodes a whole snapshot from Encode output.

func DecodeSnapshotDict

func DecodeSnapshotDict(d types.Dict, decoders SnapshotDecoders) (*Snapshot, error)

DecodeSnapshotDict rebuilds a Snapshot from EncodeDict output, decoding each tag that has a registered decoder. Unknown tags are ignored (forward-compatible with a peer that carries node types this device does not know).

func NewSnapshot

func NewSnapshot(nodes ...SnapshotNode) *Snapshot

NewSnapshot builds a snapshot from nodes (last write wins on tag collision).

func ParseSnapshotSyncMessage

func ParseSnapshotSyncMessage(m *ProtocolMessage, decoders SnapshotDecoders) (*Snapshot, error)

ParseSnapshotSyncMessage recovers a received snapshot, decoding each node for which a decoder is registered (see DecodeSnapshotDict).

func (*Snapshot) Add

func (s *Snapshot) Add(n SnapshotNode)

Add inserts or replaces a node.

func (*Snapshot) ContentsEqual

func (s *Snapshot) ContentsEqual(other *Snapshot) bool

ContentsEqual reports whether two snapshots hold the same nodes with equal contents (structural; ref areContentsTheSame). Snapshots with different tag sets are unequal.

func (*Snapshot) Diff

func (s *Snapshot) Diff(other *Snapshot) ([]SyncDiff, error)

Diff lists per-node divergences of s against other (ref computeDiff). A node present on only one side is reported as a whole-node presence diff.

func (*Snapshot) Encode

func (s *Snapshot) Encode() []byte

Encode serializes the whole snapshot dict to bytes (the value backup encrypts and a full-sync message carries).

func (*Snapshot) EncodeDict

func (s *Snapshot) EncodeDict() types.Dict

EncodeDict packs the snapshot as encodeDict{ tag: Encoded.of(node.Encode()) } — the single representation shared by full-sync exchange and backup (ref toEncodedDictionary). Each value is the node's bytes wrapped as a byte-array encoding.

func (*Snapshot) Get

func (s *Snapshot) Get(tag string) SnapshotNode

Get returns the node for tag, or nil.

func (*Snapshot) Tags

func (s *Snapshot) Tags() []string

Tags returns the node tags in sorted order.

type SnapshotDecoders

type SnapshotDecoders map[string]func([]byte) (SnapshotNode, error)

SnapshotDecoders maps a node tag to a decoder for that node's byte serialization.

type SnapshotNode

type SnapshotNode interface {
	Tag() string                                 // stable dictionary key, e.g. "settings"
	Encode() []byte                              // TLV serialization of this domain's state
	ContentsEqual(other SnapshotNode) bool       // structural, order-independent equality
	Diff(other SnapshotNode) ([]SyncDiff, error) // per-field divergences for reconciliation
}

SnapshotNode is one domain's contribution to a snapshot (ref ObvSyncSnapshotNode).

func DecodeSettingsNode

func DecodeSettingsNode(b []byte) (SnapshotNode, error)

DecodeSettingsNode is the SnapshotDecoders entry for SnapshotTagSettings.

type SymEnc

type SymEnc interface {
	Encrypt(iv, pt []byte) (ct []byte, err error)
	Decrypt(ct []byte) (pt []byte, err error)
	CtLen(ptlen uint32) (ctlen uint32)
	PtLen(ctlen uint32) (ptlen uint32, err error)
}

IV should be unpredictable. n can be predictable. this is an interface, it should not display the usage of SymEncKey

type SyncAtom

type SyncAtom struct {
	Type             int
	ContactIdentity  []byte  // contact-scoped atoms (the contact's identity bytes)
	GroupOwnerAndUID []byte  // group-v1 atoms: owner identity || 32-byte UID
	GroupV2ID        []byte  // group-v2 atoms (group-v2 identifier bytes)
	StringValue      *string // nickname/note/details/auto-join/last-rating-timestamp
	IntValue         *int64  // custom hue / v2-details version / rating
	BoolValue        *bool   // send-read-receipt / boolean settings
}

SyncAtom is a personal-state delta shared between an owned identity's devices. Fields are sparse: only those relevant to Type are set. GroupOwnerAndUID holds the group-v1 owner identity followed by the 32-byte group UID (split on the wire, joined here).

func ParseSingleItemSyncMessage

func ParseSingleItemSyncMessage(m *ProtocolMessage) (*SyncAtom, error)

ParseSingleItemSyncMessage recovers the sync atom from a received SingleItemSyncMessage.

func ParseSyncAtom

func ParseSyncAtom(b []byte) (*SyncAtom, error)

ParseSyncAtom decodes an atom produced by Encode. It rejects atom types whose sub-encodings are not yet implemented, and malformed lengths.

func (*SyncAtom) Encode

func (a *SyncAtom) Encode() ([]byte, error)

Encode serializes the atom to encodeList(type, field...). Optional scalars are omitted when nil (e.g. clearing a nickname yields just [type, identity]); required fields that are missing are an error.

func (*SyncAtom) IsAppSyncItem

func (a *SyncAtom) IsAppSyncItem() bool

IsAppSyncItem reports whether the app layer applies this atom (true) or the engine's identity manager does (false). Trust-details atoms (12–14) are identity-level; all others are app-level personal state the engine only relays.

type SyncDiff

type SyncDiff struct {
	NodeTag string
	Field   string
	Local   string
	Other   string
}

SyncDiff describes one field on which two snapshots of the same node diverge (ref ObvSyncDiff). Values are rendered to strings for reporting.

type TransferContact

type TransferContact struct {
	Identity          []byte
	OneToOne          bool
	Revoked           bool
	ForcefullyTrusted bool
	TrustLevel        string
	PublishedDetails  string
	TrustedDetails    string
}

TransferContact is one contact from the snapshot (enough to seed the contact; details/devices are re-fetched by ResyncAfterRestore).

type TransferGroupV2

type TransferGroupV2 struct {
	Identifier      []byte // encoded GroupIdentifier
	MainSeed        []byte
	VersionSeed     []byte
	EncodedAdminKey []byte
	InvitationNonce []byte
}

TransferGroupV2 is one groups-v2 group from the snapshot (identifier + blob keys + own nonce; the authoritative blob is re-fetched by ResyncAfterRestore).

type TransferSnapshot

type TransferSnapshot struct {
	OwnedIdentity         []byte // the owned identity's public bytes (server URL + public keys)
	AuthPrivEnc           []byte // Olvid-encoded server-authentication private key
	KEMPrivEnc            []byte // Olvid-encoded encryption private key
	MacKeyEnc             []byte // Olvid-encoded MAC key
	BackupSeed            []byte
	OwnedPublishedDetails string // the profile's own published details (JsonIdentityDetails), for the display name
	Contacts              []TransferContact
	Groups                []TransferGroupV2
}

TransferSnapshot is the decoded, restore-ready content of a device-transfer snapshot.

func ParseTransferSnapshot

func ParseTransferSnapshot(dictBlock []byte) (*TransferSnapshot, error)

ParseTransferSnapshot decodes the snapshot dictionary block returned by DeviceTransferParty.ReceiveSnapshot into restore-ready content. It reads the outer Olvid DICTIONARY, extracts the "identity" section (a byte block wrapping JSON), and JSON-decodes it.

func (*TransferSnapshot) OwnedIdentityCrypto

func (ts *TransferSnapshot) OwnedIdentityCrypto() (*OwnedCryptoIdentity, error)

OwnedIdentityCrypto reconstructs the full owned identity (public identity + private keys) from the snapshot, ready to persist as this device's identity.

Directories

Path Synopsis
Package ec implements the Edwards curves used by Olvid (spec Section 12): Curve25519 and MDC.
Package ec implements the Edwards curves used by Olvid (spec Section 12): Curve25519 and MDC.

Jump to

Keyboard shortcuts

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