signal

package module
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Feb 23, 2026 License: AGPL-3.0 Imports: 16 Imported by: 0

README

signal-go

Go Reference

Go library for Signal messenger with CGO bindings for the official libsignal.

Feature Status
Device linking (secondary device via QR) ✅
Device registration (primary via SMS/voice) ✅
Sending & receiving 1:1 messages ✅
Group messaging (sender keys, sealed sender v2) ✅
Sealed sender ✅
Phone number lookup (CDSI) ✅
Contact & group sync ✅
Profile management ✅
Attachments
Typing indicators & read receipts
Message editing & deletion
Voice/video calls
Stories

Example

package main

import (
	"context"
	"fmt"
	"log"

	signal "github.com/gwillem/signal-go"
)

func main() {
	ctx := context.Background()
	client := signal.NewClient()

	// 1. Link as secondary device (scan QR code with your phone)
	err := client.Link(ctx, func(uri string) {
		fmt.Println("Scan this with Signal on your phone:")
		fmt.Println(uri)
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Linked to", client.Number())

	// 2. Send a message (by UUID or phone number)
	err = client.Send(ctx, "+31612345678", "Hello from signal-go!")
	if err != nil {
		log.Fatal(err)
	}

	// 3. Receive messages
	for msg, err := range client.Receive(ctx) {
		if err != nil {
			log.Println("Error:", err)
			continue
		}
		fmt.Printf("%s: %s\n", msg.Sender, msg.Body)
	}
}

Quick start

make deps-download              # downloads pre-compiled libsignal binaries (~200MB)
go run ./cmd/sgnl link          # link as secondary device (scan QR with phone)
go run ./cmd/sgnl receive       # start receiving messages

See docs/building.md for building libsignal from source and cross-compilation.

Notes

Run a receive loop for group messaging. Group messages use sender keys distributed via 1:1 sessions. The library tracks which recipients have received the sender key and skips re-sending on subsequent messages. If a recipient's session becomes stale (e.g. they re-installed), the server sends a retry receipt that triggers re-distribution. Without a receive loop (client.Receive), these retry receipts are never processed and the recipient won't be able to decrypt group messages.

License

AGPL-3.0 (required by libsignal static linking)

Documentation

Overview

Package signal provides a high-level client for the Signal messenger protocol.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AccountSettings

type AccountSettings struct {
	// DiscoverableByPhoneNumber controls whether your number can be found via Contact Discovery.
	DiscoverableByPhoneNumber *bool
	// UnrestrictedUnidentifiedAccess allows anyone to send you sealed sender messages.
	UnrestrictedUnidentifiedAccess *bool
}

AccountSettings contains configurable account settings.

type Client

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

Client is the main entry point for interacting with Signal.

func NewClient

func NewClient(opts ...Option) *Client

NewClient creates a new Signal client.

func Open

func Open(number string, opts ...Option) (*Client, error)

Open opens an existing account by phone number (e.g. "+31647272794"). It finds the database in the default data directory, opens it, and loads credentials.

func (*Client) ACI

func (c *Client) ACI() string

ACI returns the Account Identity UUID.

func (*Client) Close

func (c *Client) Close() error

Close closes the client's database connection and frees CDSI resources.

func (*Client) DeviceID

func (c *Client) DeviceID() int

DeviceID returns the device ID assigned during registration.

func (*Client) Devices

func (c *Client) Devices(ctx context.Context) ([]DeviceInfo, error)

Devices returns the list of registered devices for this account.

func (*Client) FetchGroupDetails

func (c *Client) FetchGroupDetails(ctx context.Context) (int, error)

FetchGroupDetails fetches details (name, members) for all groups that don't have names yet. This uses the Groups V2 API which requires zkgroup auth credentials. Returns the number of groups updated.

func (*Client) GetGroup

func (c *Client) GetGroup(groupID string) (*Group, error)

GetGroup returns group details by group ID (hex-encoded GroupIdentifier). Returns nil if the group is not found.

func (*Client) GetIdentityKey

func (c *Client) GetIdentityKey(theirUUID string) ([]byte, error)

GetIdentityKey returns the stored identity key for a remote party.

func (*Client) GetServerProfile

func (c *Client) GetServerProfile(ctx context.Context) (*ServerProfile, error)

GetServerProfile fetches and decrypts the user's profile from the server.

func (*Client) Groups

func (c *Client) Groups() ([]*Group, error)

Groups returns all groups this device knows about. Groups are discovered incrementally from received group messages.

func (*Client) IdentityKey

func (c *Client) IdentityKey() ([]byte, error)

IdentityKey returns our public identity key bytes.

func (c *Client) Link(ctx context.Context, onQR func(uri string)) error

Link connects as a secondary device. It blocks until the primary device scans the QR code and completes provisioning, then registers the device with the Signal server. The onQR callback is called with the device link URI for display as a QR code.

func (*Client) Load

func (c *Client) Load() error

Load opens an existing database and loads credentials without re-linking. If no explicit DB path is set, it discovers the most recent account database in the default data directory.

func (*Client) LookupACI

func (c *Client) LookupACI(number string) string

LookupACI returns the ACI UUID for the given E.164 phone number from the local contact store. Returns empty string if not found.

func (*Client) LookupNumber

func (c *Client) LookupNumber(aci string) string

LookupNumber returns the phone number for the given ACI UUID from the local contact store. Returns empty string if not found.

func (*Client) Number

func (c *Client) Number() string

Number returns the phone number associated with the linked account.

func (*Client) ProfileInfo

func (c *Client) ProfileInfo() (*ProfileInfo, error)

ProfileInfo returns the current account's profile information.

func (*Client) Receive

func (c *Client) Receive(ctx context.Context) iter.Seq2[Message, error]

Receive returns an iterator that yields incoming text messages. It connects to the authenticated WebSocket and decrypts messages. The iterator stops when the context is cancelled or the caller breaks.

func (*Client) RefreshPreKeys

func (c *Client) RefreshPreKeys(ctx context.Context) error

RefreshPreKeys re-uploads local pre-keys to the server. Use this if pre-keys on the server are out of sync with local storage.

func (*Client) Register

func (c *Client) Register(
	ctx context.Context,
	number string,
	transport string,
	getCode func() (string, error),
	getCaptcha func() (string, error),
) error

Register registers a new Signal account as a primary device. The getCode callback is called to prompt the user for the SMS/voice verification code. The getCaptcha callback is called if a CAPTCHA challenge is required.

func (*Client) Send

func (c *Client) Send(ctx context.Context, recipient string, text string) error

Send sends a text message to the given recipient. Recipient can be an ACI UUID (e.g., "550e8400-e29b-41d4-a716-446655440000"), an E.164 phone number (e.g., "+31612345678"), or a group ID (64 hex chars). For phone numbers, the local contact store is checked first; if not found, CDSI (Contact Discovery Service) is used to resolve the number. Automatically attempts sealed sender first with fallback to unsealed.

func (*Client) SendGroup

func (c *Client) SendGroup(ctx context.Context, groupID string, text string) error

SendGroup sends a text message to a group. The groupID should be the hex-encoded GroupIdentifier (obtained from Groups()). Uses sender key encryption for efficient group messaging.

func (*Client) SetProfile

func (c *Client) SetProfile(ctx context.Context, name string, numberSharing *bool) error

SetProfile updates profile settings on the Signal server. If name is empty and numberSharing is nil, this is a no-op. If the account doesn't have a profile key, one is generated and saved.

func (*Client) SetProfileName

func (c *Client) SetProfileName(ctx context.Context, name string) error

SetProfileName sets the profile name on the Signal server. If the account doesn't have a profile key, one is generated and saved.

func (*Client) SyncContacts

func (c *Client) SyncContacts(ctx context.Context) error

SyncContacts requests a contact sync from the primary device. The primary device will respond with a SyncMessage.Contacts that is automatically handled by the receive loop, populating the local contact store.

func (*Client) SyncGroups

func (c *Client) SyncGroups(ctx context.Context) (int, error)

SyncGroups fetches group master keys from the Storage Service and stores them locally. This requires the account's master key to be available (set during device linking). Returns the number of groups synced.

func (*Client) UpdateAccountSettings

func (c *Client) UpdateAccountSettings(ctx context.Context, settings *AccountSettings) error

UpdateAccountSettings updates account attributes and/or profile settings on the server. Only non-nil fields in settings are updated.

func (*Client) UpdateAttributes

func (c *Client) UpdateAttributes(ctx context.Context) error

UpdateAttributes updates account attributes on the Signal server. This can fix message delivery issues by ensuring the unidentifiedAccessKey is set.

type DeviceInfo

type DeviceInfo = signalservice.DeviceInfo

DeviceInfo is the public type for device information.

type Group

type Group = store.Group

Group represents a Signal group stored locally.

type Message

type Message = signalservice.Message

Message represents a received Signal message.

type Option

type Option func(*Client)

Option configures a Client.

func WithAPIURL

func WithAPIURL(url string) Option

WithAPIURL overrides the default REST API URL.

func WithDBPath

func WithDBPath(path string) Option

WithDBPath overrides the database path for persistent storage. If not set, defaults to $XDG_DATA_HOME/signal-go/<aci>.db after linking.

func WithDebugDir

func WithDebugDir(path string) Option

WithDebugDir sets a directory for dumping raw envelope bytes before decryption. When set, every received envelope is written as a .bin file for offline inspection.

func WithLogger

func WithLogger(l *log.Logger) Option

WithLogger sets the logger for verbose output. If not set, logging is disabled.

func WithProvisioningURL

func WithProvisioningURL(url string) Option

WithProvisioningURL overrides the default provisioning WebSocket URL.

func WithTLSConfig

func WithTLSConfig(tc *tls.Config) Option

WithTLSConfig overrides the TLS configuration used for connections. If nil (the default), Signal's pinned CA certificate is used.

type ProfileInfo

type ProfileInfo struct {
	Number     string
	ACI        string
	PNI        string
	DeviceID   int
	ProfileKey []byte
}

ProfileInfo contains basic profile information for display.

type ServerProfile

type ServerProfile struct {
	Name       string
	About      string
	AboutEmoji string
	Avatar     string // CDN path, empty if no avatar
}

ServerProfile contains decrypted profile data from the server.

Directories

Path Synopsis
cmd
sgnl command
Command sgnl is a CLI for Signal messenger.
Command sgnl is a CLI for Signal messenger.
internal
proto
Package proto contains generated protobuf types for Signal's provisioning and WebSocket protocols.
Package proto contains generated protobuf types for Signal's provisioning and WebSocket protocols.
provisioncrypto
Package provisioncrypto implements the Signal provisioning envelope crypto: HKDF key derivation, HMAC-SHA256, AES-256-CBC, and PKCS#7 padding.
Package provisioncrypto implements the Signal provisioning envelope crypto: HKDF key derivation, HMAC-SHA256, AES-256-CBC, and PKCS#7 padding.
signalservice
Package signalservice orchestrates Signal protocol operations: device provisioning, message sending, and message receiving.
Package signalservice orchestrates Signal protocol operations: device provisioning, message sending, and message receiving.
signalws
Package signalws provides protobuf-framed WebSocket communication for the Signal provisioning protocol.
Package signalws provides protobuf-framed WebSocket communication for the Signal provisioning protocol.

Jump to

Keyboard shortcuts

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