Documentation ¶
Index ¶
- Constants
- func GenerateRandomID() string
- func ValidateInvite(invite string) (*groups.GroupInvite, error)
- type Authorization
- type Error
- type Group
- func (g *Group) AddMessage(message *groups.DecryptedGroupMessage, sig []byte) (*Message, bool)
- func (g *Group) AddSentMessage(message *groups.DecryptedGroupMessage, sig []byte) Message
- func (g *Group) CheckGroup() bool
- func (g *Group) Compromised()
- func (g *Group) DecryptMessage(ciphertext []byte) (bool, *groups.DecryptedGroupMessage)
- func (g *Group) EncryptMessage(message *groups.DecryptedGroupMessage) ([]byte, error)
- func (g *Group) ErrorSentMessage(sig []byte, error string) bool
- func (g *Group) GetAttribute(name string) (value string, exists bool)
- func (g *Group) GetTimeline() (timeline []Message)
- func (g *Group) Invite() (string, error)
- func (g *Group) SetAttribute(name string, value string)
- type Key
- type KeyBundle
- type KeyType
- type LocallyIndexedMessage
- type Message
- type Profile
- func (p *Profile) AcceptInvite(groupID string) (err error)
- func (p *Profile) AckSentMessageToPeer(onion string, eventID string) int
- func (p *Profile) AddContact(onion string, profile *PublicProfile)
- func (p *Profile) AddGroup(group *Group)
- func (p *Profile) AddGroupSentMessageError(groupID string, signature []byte, error string)
- func (p *Profile) AddMessageToContactTimeline(onion string, messageTxt string, sent time.Time) (message *Message)
- func (p *Profile) AddSentMessageToContactTimeline(onion string, messageTxt string, sent time.Time, eventID string) *Message
- func (p *Profile) AttemptDecryption(ciphertext []byte, signature []byte) (bool, string, *Message, bool)
- func (p *Profile) ContactsAuthorizations(authorizationFilter ...Authorization) map[string]Authorization
- func (p *Profile) DeleteContact(onion string)
- func (p *Profile) DeleteGroup(groupID string)
- func (p *Profile) EncryptMessageToGroup(message string, groupID string) ([]byte, []byte, error)
- func (p *Profile) ErrorSentMessageToPeer(onion string, eventID string, error string) int
- func (p *Profile) GetContact(onion string) (*PublicProfile, bool)
- func (p *Profile) GetContactAuthorization(onion string) Authorization
- func (p *Profile) GetContacts() []string
- func (p *Profile) GetCopy(timeline bool) *Profile
- func (p *Profile) GetGroup(groupID string) (g *Group)
- func (p *Profile) GetGroups() []string
- func (p *Profile) ProcessInvite(invite string) (string, error)
- func (p *Profile) RejectInvite(groupID string)
- func (p *Profile) SetContactAuthorization(onion string, auth Authorization) (err error)
- func (p *Profile) SignMessage(message string) []byte
- func (p *Profile) StartGroup(server string) (groupID string, invite string, err error)
- func (p *Profile) UpdateMessageFlags(handle string, mIdx int, flags uint64)
- func (p *Profile) VerifyGroupMessage(onion string, groupID string, ciphertext []byte, signature []byte) bool
- type PublicProfile
- type Timeline
- func (t *Timeline) GetCopy() *Timeline
- func (t *Timeline) GetMessages() []Message
- func (t *Timeline) GetMessagesByHash(contentHash string) ([]LocallyIndexedMessage, error)
- func (t *Timeline) Insert(mi *Message) bool
- func (t *Timeline) Len() int
- func (t *Timeline) Less(i, j int) bool
- func (t *Timeline) SetMessages(messages []Message)
- func (t *Timeline) Sort()
- func (t *Timeline) Swap(i, j int)
Constants ¶
const ( InvalidEd25519PublicKey = Error("InvalidEd25519PublicKey") InconsistentKeyBundleError = Error("InconsistentKeyBundleError") )
Error definitions
const ( // BundleType - the attribute under which the signed server bundle is stored... BundleType = KeyType("server_key_bundle") // KeyTypeServerOnion - a cwtch address KeyTypeServerOnion = KeyType("bulletin_board_onion") // bulletin board // KeyTypeTokenOnion - a cwtch peer with a PoW based token protocol KeyTypeTokenOnion = KeyType("token_service_onion") //KeyTypePrivacyPass - a privacy pass based token server KeyTypePrivacyPass = KeyType("privacy_pass_public_key") )
const CurrentGroupVersion = 3
CurrentGroupVersion is used to set the version of newly created groups and make sure group structs stored are correct and up to date
const GroupInvitePrefix = "torv3"
GroupInvitePrefix identifies a particular string as being a serialized group invite.
const MaxGroupMessageLength = 1800
MaxGroupMessageLength is the maximum length of a message posted to a server group. TODO: Should this be per server?
const MessageBaseSize float64 = 463
MessageBaseSize 2021.06 byte size of an *empty* message json serialized
Variables ¶
This section is empty.
Functions ¶
func GenerateRandomID ¶ added in v0.3.7
func GenerateRandomID() string
GenerateRandomID generates a random 16 byte hex id code
func ValidateInvite ¶ added in v0.8.0
func ValidateInvite(invite string) (*groups.GroupInvite, error)
ValidateInvite takes in a serialized invite and returns the invite structure if it is cryptographically valid and an error if it is not
Types ¶
type Authorization ¶ added in v0.3.14
type Authorization string
Authorization is a type determining client assigned authorization to a peer
const ( // AuthUnknown is an initial state for a new unseen peer AuthUnknown Authorization = "unknown" // AuthApproved means the client has approved the peer, it can send messages to us, perform GetVals, etc AuthApproved Authorization = "approved" // AuthBlocked means the client has blocked the peer, it's messages and connections should be rejected AuthBlocked Authorization = "blocked" )
type Error ¶ added in v0.4.1
type Error string
Error models some common errors that need to be handled by applications that use Cwtch
type Group ¶
type Group struct { // GroupID is now derived from the GroupKey and the GroupServer GroupID string GroupKey [32]byte GroupServer string Timeline Timeline `json:"-"` Accepted bool IsCompromised bool Attributes map[string]string LocalID string State string `json:"-"` UnacknowledgedMessages []Message Version int // contains filtered or unexported fields }
Group defines and encapsulates Cwtch's conception of group chat. Which are sessions tied to a server under a given group key. Each group has a set of Messages.
func (*Group) AddMessage ¶
AddMessage takes a DecryptedGroupMessage and adds it to the Groups Timeline
func (*Group) AddSentMessage ¶
func (g *Group) AddSentMessage(message *groups.DecryptedGroupMessage, sig []byte) Message
AddSentMessage takes a DecryptedGroupMessage and adds it to the Groups Timeline
func (*Group) CheckGroup ¶ added in v0.8.0
CheckGroup returns true only if the ID of the group is cryptographically valid.
func (*Group) Compromised ¶
func (g *Group) Compromised()
Compromised should be called if we detect a groupkey leak
func (*Group) DecryptMessage ¶
func (g *Group) DecryptMessage(ciphertext []byte) (bool, *groups.DecryptedGroupMessage)
DecryptMessage takes a ciphertext and returns true and the decrypted message if the cipher text can be successfully decrypted,else false.
func (*Group) EncryptMessage ¶
func (g *Group) EncryptMessage(message *groups.DecryptedGroupMessage) ([]byte, error)
EncryptMessage takes a message and encrypts the message under the group key.
func (*Group) ErrorSentMessage ¶ added in v0.3.2
ErrorSentMessage removes a sent message from the unacknowledged list and sets its error flag if found, otherwise returns false
func (*Group) GetAttribute ¶
GetAttribute returns the value of a value set with SetAttribute. If no such value has been set exists is set to false.
func (*Group) GetTimeline ¶
GetTimeline provides a safe copy of the timeline
func (*Group) SetAttribute ¶
SetAttribute allows applications to store arbitrary configuration info at the group level.
type Key ¶ added in v0.4.0
type Key string
Key provides a wrapper for a generic public key identifier (could be an onion address, a zcash address etc.)
type KeyBundle ¶ added in v0.4.0
KeyBundle manages a collection of related keys for various different services.
func DeserializeAndVerify ¶ added in v0.4.1
DeserializeAndVerify takes in a json formatted bundle and only returns a valid key bundle if it has been signed by the server.
func NewKeyBundle ¶ added in v0.4.1
func NewKeyBundle() *KeyBundle
NewKeyBundle creates a new KeyBundle initialized with no keys.
func (*KeyBundle) AttributeBundle ¶ added in v0.4.0
AttributeBundle returns a map that can be used as part of a peer attribute bundle
func (*KeyBundle) HasKeyType ¶ added in v0.4.0
HasKeyType returns true if the bundle has a public key of a given type.
func (*KeyBundle) Sign ¶ added in v0.4.1
func (kb *KeyBundle) Sign(identity primitives.Identity)
Sign allows a server to authenticate a key bundle by signing it (this uses the tapir identity interface)
type KeyType ¶ added in v0.4.0
type KeyType string
KeyType provides a wrapper for a generic public key type identifier (could be an onion address, a zcash address etc.)
type LocallyIndexedMessage ¶ added in v0.9.1
LocallyIndexedMessage is a type wrapper around a Message and a TimeLine Index that is local to this instance of the timeline.
type Message ¶
type Message struct { Timestamp time.Time Received time.Time PeerID string Message string Signature []byte PreviousMessageSig []byte ReceivedByServer bool // messages sent to a server Acknowledged bool // peer to peer Error string `json:",omitempty"` // Application specific flags, useful for storing small amounts of metadata Flags uint64 }
Message is a local representation of a given message sent over a group chat channel.
type Profile ¶
type Profile struct { PublicProfile Contacts map[string]*PublicProfile Ed25519PrivateKey ed25519.PrivateKey Groups map[string]*Group }
Profile encapsulates all the attributes necessary to be a Cwtch Peer.
func GenerateNewProfile ¶
GenerateNewProfile creates a new profile, with new encryption and signing keys, and a profile name.
func (*Profile) AcceptInvite ¶
AcceptInvite accepts a group invite
func (*Profile) AckSentMessageToPeer ¶ added in v0.3.2
AckSentMessageToPeer sets mesage to a peer as acknowledged
func (*Profile) AddContact ¶
func (p *Profile) AddContact(onion string, profile *PublicProfile)
AddContact allows direct manipulation of cwtch contacts
func (*Profile) AddGroupSentMessageError ¶ added in v0.3.2
AddGroupSentMessageError searches matching groups for the message by sig and marks it as an error
func (*Profile) AddMessageToContactTimeline ¶ added in v0.3.2
func (p *Profile) AddMessageToContactTimeline(onion string, messageTxt string, sent time.Time) (message *Message)
AddMessageToContactTimeline allows the saving of a message sent via a direct connection chat to the profile.
func (*Profile) AddSentMessageToContactTimeline ¶ added in v0.3.2
func (p *Profile) AddSentMessageToContactTimeline(onion string, messageTxt string, sent time.Time, eventID string) *Message
AddSentMessageToContactTimeline allows the saving of a message sent via a direct connection chat to the profile.
func (*Profile) AttemptDecryption ¶
func (p *Profile) AttemptDecryption(ciphertext []byte, signature []byte) (bool, string, *Message, bool)
AttemptDecryption takes a ciphertext and signature and attempts to decrypt it under known groups. If successful, adds the message to the group's timeline
func (*Profile) ContactsAuthorizations ¶ added in v0.3.14
func (p *Profile) ContactsAuthorizations(authorizationFilter ...Authorization) map[string]Authorization
ContactsAuthorizations calculates a list of Peers who are at the supplied auth levels
func (*Profile) DeleteContact ¶
DeleteContact deletes a peer contact
func (*Profile) DeleteGroup ¶
DeleteGroup deletes a group
func (*Profile) EncryptMessageToGroup ¶
EncryptMessageToGroup when given a message and a group, encrypts and signs the message under the group and profile
func (*Profile) ErrorSentMessageToPeer ¶ added in v0.3.2
ErrorSentMessageToPeer sets a sent message's error message and removes it from the unacknowledged list
func (*Profile) GetContact ¶
func (p *Profile) GetContact(onion string) (*PublicProfile, bool)
GetContact returns a contact if the profile has it
func (*Profile) GetContactAuthorization ¶ added in v0.3.14
func (p *Profile) GetContactAuthorization(onion string) Authorization
GetContactAuthorization returns the contact's authorization level
func (*Profile) GetContacts ¶
GetContacts returns an unordered list of contact onions associated with this profile.
func (*Profile) GetCopy ¶
GetCopy returns a full deep copy of the Profile struct and its members (timeline inclusion control by arg)
func (*Profile) GetGroup ¶ added in v0.3.3
GetGroup a pointer to a Group by the group Id, returns nil if no group found.
func (*Profile) GetGroups ¶
GetGroups returns an unordered list of group IDs associated with this profile.
func (*Profile) ProcessInvite ¶
ProcessInvite validates a group invite and adds a new group invite to the profile if it is valid. returns the new group ID on success, error on fail.
func (*Profile) RejectInvite ¶
RejectInvite rejects and removes a group invite
func (*Profile) SetContactAuthorization ¶ added in v0.3.14
func (p *Profile) SetContactAuthorization(onion string, auth Authorization) (err error)
SetContactAuthorization sets the authoirization level of a peer
func (*Profile) SignMessage ¶
SignMessage takes a given message and returns an Ed21159 signature
func (*Profile) StartGroup ¶
StartGroup when given a server, creates a new Group under this profile and returns the group id an a precomputed invite which can be sent on the wire.
func (*Profile) UpdateMessageFlags ¶ added in v0.8.6
UpdateMessageFlags updates the flags stored with a message
func (*Profile) VerifyGroupMessage ¶
func (p *Profile) VerifyGroupMessage(onion string, groupID string, ciphertext []byte, signature []byte) bool
VerifyGroupMessage confirms the authenticity of a message given an sender onion, ciphertext and signature. The goal of this function is 2-fold:
- We confirm that the sender referenced in the group text is the actual sender of the message (or at least knows the senders private key)
- Secondly, we confirm that the sender sent the message to a particular group id on a specific server (it doesn't matter if we actually received this message from the server or from a hybrid protocol, all that matters is that the sender and receivers agree that this message was intended for the group
The 2nd point is important as it prevents an attack documented in the original Cwtch paper (and later at https://docs.openprivacy.ca/cwtch-security-handbook/groups.html) in which a malicious profile sets up 2 groups on two different servers with the same key and then forwards messages between them to convince the parties in each group that they are actually in one big group (with the intent to later censor and/or selectively send messages to each group).
type PublicProfile ¶
type PublicProfile struct { Name string Ed25519PublicKey ed25519.PublicKey Authorization Authorization DeprecatedBlocked bool `json:"Blocked"` Onion string Attributes map[string]string Timeline Timeline `json:"-"` LocalID string // used by storage engine State string `json:"-"` UnacknowledgedMessages map[string]int // contains filtered or unexported fields }
PublicProfile is a local copy of a CwtchIdentity
func (*PublicProfile) GetAttribute ¶
func (p *PublicProfile) GetAttribute(name string) (value string, exists bool)
GetAttribute returns the value of a value set with SetCustomAttribute. If no such value has been set exists is set to false.
func (*PublicProfile) IsServer ¶ added in v0.4.0
func (p *PublicProfile) IsServer() (isServer bool)
IsServer returns true if the profile is associated with a server.
func (*PublicProfile) SetAttribute ¶
func (p *PublicProfile) SetAttribute(name string, value string)
SetAttribute allows applications to store arbitrary configuration info at the profile level.
type Timeline ¶
type Timeline struct { Messages []Message SignedGroupID []byte // contains filtered or unexported fields }
Timeline encapsulates a collection of ordered Messages, and a mechanism to access them in a threadsafe manner.
func (*Timeline) GetMessages ¶
GetMessages returns a copy of the entire timeline
func (*Timeline) GetMessagesByHash ¶ added in v0.9.1
func (t *Timeline) GetMessagesByHash(contentHash string) ([]LocallyIndexedMessage, error)
GetMessagesByHash attempts to find messages that match the given content hash in the timeline. If successful it returns a list of messages as well as their local index , on failure it returns an error. We return a list of messages because content hashes are not guaranteed to be unique from a given Peer. This allows us to do things like: ensure that reply-to and quotes reference the last seen message from the message they are quoted in or detect duplicate messages from a peer.
func (*Timeline) Less ¶
Less checks 2 Messages (i and j) in the timeline and returns true if i occurred before j, else false
func (*Timeline) SetMessages ¶
SetMessages sets the Messages of this timeline. Only to be used in loading/initialization