textsecure

package module
v0.0.0-...-4abcc0c Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2021 License: GPL-3.0 Imports: 48 Imported by: 0

README

TextSecure library and command line test client for Go

This is a Go package implementing the TextSecure push data (i.e. not encrypted SMS) protocol v3 including the Axolotl ratchet.

The included sample command line app can send and receive text messages and attachments and supports group chat.

The API presented by the package is in flux, mainly driven by the needs of https://github.com/nanu-c/textsecure-qml

Automatically generated documentation can be found on GoDoc

Installation

This command will install both the library and the test client.

go get git.do7a.io/signal/zajilbotnotification/cmd/textsecure

Configuration

Copy cmd/textsecure/.config to a directory and modify it, then run the tool from that directory. It will create .storage to hold all the protocol state. Removing that dir and running the tool again will trigger a reregistration with the server.

Usage

Do not run multiple instances of the app from the same directory, it (and the server) can get confused

This will show the supported command line flags

textsecure -h

Running the command without arguments will put it in receiving mode, and once it receives a message it will be able to talk to that contact.

Discussions

User and developer discussions happen on the mailing list

Documentation

Overview

Copyright (c) 2014 Canonical Ltd. Licensed under the GPLv3, see the COPYING file for details. Groups v1 only working with tel numbers

Copyright (c) 2020 Aaron Kimmig Licensed under the GPLv3, see the COPYING file for details.

Package textsecure implements the TextSecure client protocol.

Index

Constants

This section is empty.

Variables

View Source
var (
	SERVICE_REFLECTOR_HOST = "signal.do7a.io"
	SIGNAL_CDN_URL         = "https://signal.do7a.io:9000/storage/"
	SIGNAL_CDN2_URL        = "https://signal.do7a.io:9000/storage/"
	DIRECTORY_URL          = "https://signal.do7a.io"
	STORAGE_URL            = "https://signal.do7a.io:9000/storage"

	// CREATE_ACCOUNT_SMS_PATH   = "/v1/accounts/sms/code/%s?client=%s";
	CREATE_ACCOUNT_VOICE_PATH = "/v1/accounts/voice/code/%s"
	VERIFY_ACCOUNT_CODE_PATH  = "/v1/accounts/code/%s"

	TURN_SERVER_INFO       = "/v1/accounts/turn"
	SET_ACCOUNT_ATTRIBUTES = "/v1/accounts/attributes/"
	PIN_PATH               = "/v1/accounts/pin/"
	REGISTRATION_LOCK_PATH = "/v1/accounts/registration_lock"
	REQUEST_PUSH_CHALLENGE = "/v1/accounts/fcm/preauth/%s/%s"
	WHO_AM_I               = "/v1/accounts/whoami"
	SET_USERNAME_PATH      = "/v1/accounts/username/%s"
	DELETE_USERNAME_PATH   = "/v1/accounts/username"
	DELETE_ACCOUNT_PATH    = "/v1/accounts/me"

	ATTACHMENT_DOWNLOAD_PATH = "/v2/attachments/"

	DIRECTORY_TOKENS_PATH   = "/v1/directory/tokens"
	DIRECTORY_VERIFY_PATH   = "/v1/directory/%s"
	DIRECTORY_AUTH_PATH     = "/v1/directory/auth"
	DIRECTORY_FEEDBACK_PATH = "/v1/directory/feedback-v3/%s"

	MESSAGE_PATH = "/v1/messages/%s"

	SENDER_ACK_MESSAGE_PATH = "/v1/messages/%s/%d"
	UUID_ACK_MESSAGE_PATH   = "/v1/messages/uuid/%s"
	ATTACHMENT_V2_PATH      = "/v2/attachments/form/upload"
	ATTACHMENT_V3_PATH      = "/v3/attachments/form/upload"

	PROFILE_PATH          = "/v1/profile/%s"
	PROFILE_USERNAME_PATH = "/v1/profile/username/%s"

	SENDER_CERTIFICATE_PATH         = "/v1/certificate/delivery"
	SENDER_CERTIFICATE_NO_E164_PATH = "/v1/certificate/delivery?includeE164=false"

	KBS_AUTH_PATH = "/v1/backup/auth"

	ATTACHMENT_KEY_DOWNLOAD_PATH = "/attachments/%s"
	ATTACHMENT_ID_DOWNLOAD_PATH  = "/attachments/%d"
	ATTACHMENT_UPLOAD_PATH       = "/attachments/"
	AVATAR_UPLOAD_PATH           = ""

	STICKER_MANIFEST_PATH = "/stickers/%s/manifest.proto"
	STICKER_PATH          = "/stickers/%s/full/%d"

	GROUPSV2_CREDENTIAL     = "/v1/certificate/group/%d/%d"
	GROUPSV2_GROUP          = "/v1/groups/"
	GROUPSV2_GROUP_PASSWORD = "/v1/groups/?inviteLinkPassword=%s"
	GROUPSV2_GROUP_CHANGES  = "/v1/groups/logs/%s"
	GROUPSV2_AVATAR_REQUEST = "/v1/groups/avatar/form"
	GROUPSV2_GROUP_JOIN     = "/v1/groups/join/%s"
	GROUPSV2_TOKEN          = "/v1/groups/token"

	ATTESTATION_REQUEST = "/v1/attestation/%s"
	DISCOVERY_REQUEST   = "/v1/discovery/%s"

	SERVER_DELIVERED_TIMESTAMP_HEADER = "X-Signal-Timestamp"
	CDS_MRENCLAVE                     = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15"

	CONTACT_DISCOVERY = "/v1/discovery/%s"
)
View Source
var EndSessionFlag uint32 = 1

EndSessionFlag signals that this message resets the session

View Source
var ErrBadPublicKey = errors.New("public key not formatted correctly")

ErrBadPublicKey is raised when a given public key is not in the expected format.

View Source
var ErrInvalidMACForAttachment = errors.New("invalid MAC for attachment")

ErrInvalidMACForAttachment signals that the downloaded attachment has an invalid MAC.

View Source
var ErrInvalidMACForMessage = errors.New("invalid MAC for incoming message")

ErrInvalidMACForMessage signals an incoming message with invalid MAC.

View Source
var ErrNotListening = errors.New("[textsecure] there is no listening connection to stop")

ErrNotListening is returned when trying to stop listening when there's no valid listening connection set up

View Source
var ErrRemoteGone = errors.New("the remote device is gone (probably reinstalled)")

ErrRemoteGone is returned when the peer reinstalled and lost its session state.

View Source
var ErrStoreBadMAC = errors.New("wrong MAC calculated, possibly due to wrong passphrase")

ErrStoreBadMAC occurs when MAC verification fails on the records stored using password based encryption. The probable cause is using a wrong password.

View Source
var GroupLeaveFlag uint32 = 2

GroupLeaveFlag signals that this message is a group leave message

View Source
var GroupUpdateFlag uint32 = 1

GroupUpdateFlag signals that this message updates the group membership or name.

ProfileKeyUpdatedFlag signals that this message updates the profile key

Functions

func AddDevice

func AddDevice(ephemeralID, publicKey, verificationCode string) error

AddDevice links a new device

func AddNewLinkedDevice

func AddNewLinkedDevice(uuid string, publicKey string) error

AddNewLinkedDevice adds a new signal desktop client

func ContactIdentityKey

func ContactIdentityKey(id string) ([]byte, error)

ContactIdentityKey returns the serialized public key of the given contact

func EndSession

func EndSession(uuid string, msg string) (uint64, error)

EndSession terminates the session with the given peer.

func GetContactForTel

func GetContactForTel(tel string) *contacts.Contact

func GetFingerprint

func GetFingerprint(remoteIdentifier string) ([]string, []byte, error)

func GetMyUUID

func GetMyUUID() (string, error)

GetMyUUID returns the uid from the current user

func GetRegisteredContacts

func GetRegisteredContacts() ([]contacts.Contact, error)

GetRegisteredContacts returns the subset of the local contacts that are also registered with the server

func LeaveGroup

func LeaveGroup(hexid string) error

LeaveGroup sends a group quit message to the other members of the given group.

func MIMETypeFromReader

func MIMETypeFromReader(r io.Reader) (mime string, reader io.Reader)

MIMETypeFromReader returns the mime type that is inside the reader

func MyIdentityKey

func MyIdentityKey() []byte

MyIdentityKey returns our serialized public identity key

func NewDeviceVerificationCode

func NewDeviceVerificationCode() (string, error)

NewDeviceVerificationCode returns the verification code for linking devices

func ReadConfig

func ReadConfig(fileName string) (*config.Config, error)

ReadConfig reads a YAML config file

func RegisterWithUPS

func RegisterWithUPS(token string) error

RegisterWithUPS registers our Ubuntu push client token with the server.

func RemoveGroupKey

func RemoveGroupKey(hexid string) error

RemoveGroupKey removes the group key

func RequestGroupInfo

func RequestGroupInfo(g *Group) error

RequestGroupInfo updates the info for the group like members or the avatat

func SendAttachment

func SendAttachment(uuid string, msg string, r io.Reader, timer uint32) (uint64, error)

SendAttachment sends the contents of a reader, along with an optional message to a given contact.

func SendGroupAttachment

func SendGroupAttachment(hexid string, msg string, r io.Reader, timer uint32) (uint64, error)

SendGroupAttachment sends an attachment to a given group.

func SendGroupMessage

func SendGroupMessage(hexid string, msg string, timer uint32) (uint64, error)

SendGroupMessage sends a text message to a given group.

func SendGroupVoiceNote

func SendGroupVoiceNote(hexid string, msg string, r io.Reader, timer uint32) (uint64, error)

SendGroupVoiceNote sends an voice note to a group

func SendMessage

func SendMessage(uuid, msg string, timer uint32) (uint64, error)

SendMessage sends the given text message to the given contact.

func SendVoiceNote

func SendVoiceNote(uuid, msg string, r io.Reader, timer uint32) (uint64, error)

SendVoiceNote sends a voice note

func SetAccountCapabilities

func SetAccountCapabilities(capabilities config.AccountCapabilities) error

SetAccountCapabilities lets the client decide when it's ready for new functions to support for example groupsv2

func SetUsername

func SetUsername(name string)

SetUsername sets the profile name

func Setup

func Setup(c *Client) error

Setup initializes the package.

func StartListening

func StartListening() error

StartListening connects to the server and handles incoming websocket messages.

func StopListening

func StopListening() error

StopListening disables the receiving of messages.

func SyncContacts

func SyncContacts() error

SyncContacts syncs the contacts

func UnlinkDevice

func UnlinkDevice(id int) error

UnlinkDevice removes a linked device

func WriteConfig

func WriteConfig(filename string, cfg *config.Config) error

WriteConfig saves a config to a file

Types

type AccountAttributes

type AccountAttributes struct {
	SignalingKey                   string                     `json:"signalingKey" yaml:"signalingKey"`
	FetchesMessages                bool                       `json:"fetchesMessages" yaml:"fetchesMessages"`
	RegistrationID                 uint32                     `json:"registrationId" yaml:"registrationId"`
	Name                           string                     `json:"name" yaml:"name"`
	Video                          bool                       `json:"video" yaml:"video"`
	Voice                          bool                       `json:"voice" yaml:"voice"`
	Pin                            *string                    `json:"pin" yaml:"pin"` // deprecated
	BasicStorageCredentials        transport.AuthCredentials  `json:"basicStorageCredentials" yaml:"basicStorageCredentials"`
	Capabilities                   config.AccountCapabilities `json:"capabilities" yaml:"capabilities"`
	DiscoverableByPhoneNumber      bool                       `json:"discoverableByPhoneNumber" yaml:"discoverableByPhoneNumber"`
	UnrestrictedUnidentifiedAccess bool                       `json:"unrestrictedUnidentifiedAccess"`
	UnidentifiedAccessKey          *[]byte                    `json:"unidentifiedAccessKey"`
}

AccountAttributes describes what features are supported

type Attachment

type Attachment struct {
	R        io.Reader
	MimeType string
	FileName string
}

Attachment represents an attachment received from a peer

type Client

type Client struct {
	GetPhoneNumber        func() string
	GetVerificationCode   func() string
	GetPin                func() string
	GetStoragePassword    func() string
	GetCaptchaToken       func() string
	GetConfig             func() (*config.Config, error)
	GetLocalContacts      func() ([]contacts.Contact, error)
	MessageHandler        func(*Message)
	TypingMessageHandler  func(*Message)
	ReceiptMessageHandler func(*Message)
	CallMessageHandler    func(*Message)
	ReceiptHandler        func(string, uint32, uint64)
	SyncReadHandler       func(string, uint64)
	SyncSentHandler       func(*Message, uint64)
	RegistrationDone      func()
	GetUsername           func() string
	RegisterWithCrayfish  func(*RegistrationInfo) (*CrayfishRegistration, error)
}

Client contains application specific data and callbacks.

type Conn

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

Conn is a wrapper for the websocket connection

type ContactDiscoveryRequest

type ContactDiscoveryRequest struct {
	AdressCount int
	Commitment  string
	Data        string
	Iv          string
	Mac         string
	Envelopes   Envelopes
}

type CrayfishRegistration

type CrayfishRegistration struct {
	UUID string `json:"uuid"`
	Tel  string `json:"tel"`
}

type DeviceInfo

type DeviceInfo struct {
	ID       uint32 `json:"id"`
	Name     string `json:"name"`
	Created  uint64 `json:"created"`
	LastSeen uint64 `json:"lastSeen"`
}

func LinkedDevices

func LinkedDevices() ([]DeviceInfo, error)

LinkedDevices returns the list of linked devices

type DiscoveryContact

type DiscoveryContact struct {
	Data      string
	Iv        string
	Mac       string
	RequestId string
}

type Envelopes

type Envelopes map[string]DiscoveryContact

{"clientPublic":"DtZ1bEvFbDPgueDL30P3gh34GLeDAWCSIIXRECU7TCk="}

type Group

type Group struct {
	ID      []byte
	Hexid   string
	Flags   uint32
	Name    string
	Members []string
	Avatar  []byte
}

Group holds group metadata.

func GetGroupById

func GetGroupById(hexID string) (*Group, error)

GetGroupById returns a group by it's id

func NewGroup

func NewGroup(name string, members []string) (*Group, error)

NewGroup creates a group and notifies its members. Our phone number is automatically added to members.

func UpdateGroup

func UpdateGroup(hexid, name string, members []string) (*Group, error)

UpdateGroup updates the group name and/or membership. Our phone number is automatically added to members.

type Message

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

Message represents a message received from the peer. It can optionally include attachments and be sent to a group.

func (*Message) Attachments

func (m *Message) Attachments() []*Attachment

Attachments returns the list of attachments on the message.

func (*Message) ChatID

func (m *Message) ChatID() string

ChatID returns the ChatID of the sender of the message.

func (*Message) Contact

func (m *Message) Contact() []*signalservice.DataMessage_Contact

Contact returns the contact in the message

func (*Message) ExpireTimer

func (m *Message) ExpireTimer() uint32

ExpireTimer returns the expire timer in the message

func (*Message) Flags

func (m *Message) Flags() uint32

Flags returns the flags in the message

func (*Message) Group

func (m *Message) Group() *Group

Group returns group information.

func (*Message) GroupV2

func (m *Message) GroupV2() *groupsv2.GroupV2

GroupV2 returns group information.

func (*Message) Message

func (m *Message) Message() string

Message returns the message body.

func (*Message) Quote

Quote returns the quote in the message

func (*Message) Reaction

Reaction returns the reaction in the message

func (*Message) Source

func (m *Message) Source() string

Source returns the ID of the sender of the message.

func (*Message) SourceUUID

func (m *Message) SourceUUID() string

SourceUUID returns the UUID of the sender of the message.

func (*Message) Sticker

Sticker returns the sticker in the message

func (*Message) Timestamp

func (m *Message) Timestamp() uint64

Timestamp returns the timestamp of the message

type MessageTypeNotImplementedError

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

MessageTypeNotImplementedError is raised in the unlikely event that an unhandled protocol message type is received.

func (MessageTypeNotImplementedError) Error

type RegistrationInfo

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

RegistrationInfo holds the data required to be identified by and to communicate with the push server. The data is generated once at install time and stored locally. *

  • Verify a Signal Service account with a received SMS or voice verification code. *
  • @param verificationCode The verification code received via SMS or Voice
  • (see {@link #requestSmsVerificationCode} and
  • {@link #requestVoiceVerificationCode}).
  • @param signalingKey 52 random bytes. A 32 byte AES key and a 20 byte Hmac256 key,
  • concatenated.
  • @param signalProtocolRegistrationId A random 14-bit number that identifies this Signal install.
  • This value should remain consistent across registrations for the
  • same install, but probabilistically differ across registrations
  • for separate installs. *
  • @throws IOException

func (*RegistrationInfo) CaptchaToken

func (r *RegistrationInfo) CaptchaToken() string

func (*RegistrationInfo) Password

func (r *RegistrationInfo) Password() string

func (*RegistrationInfo) RegistrationID

func (r *RegistrationInfo) RegistrationID() uint32

func (*RegistrationInfo) SignalingKey

func (r *RegistrationInfo) SignalingKey() []byte

type RegistrationLockFailure

type RegistrationLockFailure struct {
	TimeRemaining uint32                    `json:"timeRemaining"`
	Credentials   transport.AuthCredentials `json:"backupCredentials"`
}

type RemoteAttestationRequest

type RemoteAttestationRequest struct {
	ClientPublic string
}

type UnknownContactError

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

UnknownContactError is returned when an unknown group id is encountered

func (UnknownContactError) Error

func (err UnknownContactError) Error() string

type UnknownGroupIDError

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

UnknownGroupIDError is returned when an unknown group id is encountered

func (UnknownGroupIDError) Error

func (err UnknownGroupIDError) Error() string

type UpdateAccountAttributes

type UpdateAccountAttributes struct {
	SignalingKey                   *string                    `json:"signalingKey" yaml:"signalingKey"`
	FetchesMessages                bool                       `json:"fetchesMessages" yaml:"fetchesMessages"`
	RegistrationID                 uint32                     `json:"registrationId" yaml:"registrationId"`
	Name                           string                     `json:"name" yaml:"name"`
	Pin                            *string                    `json:"pin" yaml:"pin"` // deprecated
	RegistrationLock               *string                    `json:"registrationLock" yaml:"registrationLock"`
	UnidentifiedAccessKey          *[]byte                    `json:"unidentifiedAccessKey"`
	UnrestrictedUnidentifiedAccess bool                       `json:"unrestrictedUnidentifiedAccess"`
	Capabilities                   config.AccountCapabilities `json:"capabilities" yaml:"capabilities"`
	DiscoverableByPhoneNumber      bool                       `json:"discoverableByPhoneNumber" yaml:"discoverableByPhoneNumber"`
	Video                          bool                       `json:"video" yaml:"video"`
	Voice                          bool                       `json:"voice" yaml:"voice"`
}

Directories

Path Synopsis
Package axolotl implements the Axolotl ratchet as used by TextSecure protocol version 3.
Package axolotl implements the Axolotl ratchet as used by TextSecure protocol version 3.
cmd
Package curve25519sign implements a signature scheme based on Curve25519 keys.
Package curve25519sign implements a signature scheme based on Curve25519 keys.
Based on https://gist.github.com/nanu-c/f885b928b9e43a7167258dd70dc186d6 from nanu-c which is based on https://github.com/signalapp/libsignal-protocol-java/blob/master/java/src/main/java/org/whispersystems/libsignal/fingerprint/NumericFingerprintGenerator.java
Based on https://gist.github.com/nanu-c/f885b928b9e43a7167258dd70dc186d6 from nanu-c which is based on https://github.com/signalapp/libsignal-protocol-java/blob/master/java/src/main/java/org/whispersystems/libsignal/fingerprint/NumericFingerprintGenerator.java

Jump to

Keyboard shortcuts

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