From d4b2659f96d1b5fbabc7fc8794ebf57b0a71a1d7 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 23 Apr 2026 20:39:33 +0300 Subject: [PATCH 01/34] signalmeow/sending: remove unnecessary warnings for receipt sync messages --- pkg/signalmeow/sending.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pkg/signalmeow/sending.go b/pkg/signalmeow/sending.go index 769798a..a485b54 100644 --- a/pkg/signalmeow/sending.go +++ b/pkg/signalmeow/sending.go @@ -384,15 +384,7 @@ func syncMessageFromSoloEditMessage(editMessage *signalpb.EditMessage, result Su } func syncMessageFromReadReceiptMessage(ctx context.Context, receiptMessage *signalpb.ReceiptMessage, messageSender libsignalgo.ServiceID) *signalpb.Content { - if *receiptMessage.Type != signalpb.ReceiptMessage_READ { - zerolog.Ctx(ctx).Warn(). - Any("receipt_message_type", receiptMessage.Type). - Msg("syncMessageFromReadReceiptMessage called with non-read receipt message") - return nil - } else if messageSender.Type != libsignalgo.ServiceIDTypeACI { - zerolog.Ctx(ctx).Warn(). - Stringer("message_sender", messageSender). - Msg("syncMessageFromReadReceiptMessage called with non-ACI message sender") + if *receiptMessage.Type != signalpb.ReceiptMessage_READ || messageSender.Type != libsignalgo.ServiceIDTypeACI { return nil } read := []*signalpb.SyncMessage_Read{} From 2b2a3b036f5d8095d9603e414055f770c1a2a0b9 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Mon, 27 Apr 2026 12:19:52 +0300 Subject: [PATCH 02/34] signalmeow/attachments: use go-util for pkcs7 padding --- go.mod | 2 +- go.sum | 4 ++-- pkg/signalmeow/attachments.go | 44 ++++++++++++++++++++--------------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index 1106eb6..8df1d19 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/rs/zerolog v1.35.0 github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 - go.mau.fi/util v0.9.8 + go.mau.fi/util v0.9.9-0.20260424160448-fd0d9737ad38 golang.org/x/crypto v0.50.0 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f golang.org/x/net v0.53.0 diff --git a/go.sum b/go.sum index 0f27daa..af95348 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -go.mau.fi/util v0.9.8 h1:+/jf8eM2dAT2wx9UidmaneH28r/CSCKCniCyby1qWz8= -go.mau.fi/util v0.9.8/go.mod h1:up/5mbzH2M1pSBNXqRxODn8dg/hEKbLJu92W4/SNAX0= +go.mau.fi/util v0.9.9-0.20260424160448-fd0d9737ad38 h1:D4OKITjyvlud39Q10oMnfhdeNkzEIVkXrEeCW6nvgLk= +go.mau.fi/util v0.9.9-0.20260424160448-fd0d9737ad38/go.mod h1:up/5mbzH2M1pSBNXqRxODn8dg/hEKbLJu92W4/SNAX0= go.mau.fi/zeroconfig v0.2.0 h1:e/OGEERqVRRKlgaro7E6bh8xXiKFSXB3eNNIud7FUjU= go.mau.fi/zeroconfig v0.2.0/go.mod h1:J0Vn0prHNOm493oZoQ84kq83ZaNCYZnq+noI1b1eN8w= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= diff --git a/pkg/signalmeow/attachments.go b/pkg/signalmeow/attachments.go index a48414e..c091827 100644 --- a/pkg/signalmeow/attachments.go +++ b/pkg/signalmeow/attachments.go @@ -35,6 +35,7 @@ import ( "github.com/rs/zerolog" "go.mau.fi/util/fallocate" + "go.mau.fi/util/pkcs7" "go.mau.fi/util/random" "google.golang.org/protobuf/proto" @@ -136,6 +137,15 @@ func DownloadAttachment( const MACLength = 32 const IVLength = 16 +func macAndAESDecrypt(body, key []byte) ([]byte, error) { + l := len(body) - MACLength + if !verifyMAC(key[MACLength:], body[:l], body[l:]) { + return nil, ErrInvalidMACForAttachment + } + + return aesDecrypt(key[:MACLength], body[:l]) +} + func decryptAttachment(body, key, digest []byte, plaintextDigest bool, size uint32) ([]byte, error) { if !plaintextDigest { hash := sha256.Sum256(body) @@ -143,12 +153,7 @@ func decryptAttachment(body, key, digest []byte, plaintextDigest bool, size uint return nil, ErrInvalidDigestForAttachment } } - l := len(body) - MACLength - if !verifyMAC(key[MACLength:], body[:l], body[l:]) { - return nil, ErrInvalidMACForAttachment - } - - decrypted, err := aesDecrypt(key[:MACLength], body[:l]) + decrypted, err := macAndAESDecrypt(body, key) if err != nil { return nil, err } @@ -240,6 +245,14 @@ func extend(data []byte, paddedLen int) []byte { } } +func macAndAESEncrypt(keys, plaintext []byte) ([]byte, error) { + encrypted, err := aesEncrypt(keys[:32], plaintext) + if err != nil { + return nil, err + } + return appendMAC(keys[32:], encrypted), nil +} + func (cli *Client) UploadAttachment(ctx context.Context, body []byte) (*signalpb.AttachmentPointer, error) { log := zerolog.Ctx(ctx).With().Str("func", "upload attachment").Logger() keys := random.Bytes(64) // combined AES and MAC keys @@ -255,11 +268,10 @@ func (cli *Client) UploadAttachment(ctx context.Context, body []byte) (*signalpb } body = extend(body, paddedLen) - encrypted, err := aesEncrypt(keys[:32], body) + encryptedWithMAC, err := macAndAESEncrypt(keys, body) if err != nil { return nil, err } - encryptedWithMAC := appendMAC(keys[32:], encrypted) // Get upload attributes from Signal server attributesPath := "/v4/attachments/form/upload" @@ -467,13 +479,10 @@ func aesDecrypt(key, ciphertext []byte) ([]byte, error) { } iv := ciphertext[:IVLength] + ciphertext = ciphertext[IVLength:] mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(ciphertext, ciphertext) - pad := ciphertext[len(ciphertext)-1] - if pad > aes.BlockSize { - return nil, fmt.Errorf("pad value (%d) larger than AES blocksize (%d)", pad, aes.BlockSize) - } - return ciphertext[aes.BlockSize : len(ciphertext)-int(pad)], nil + return pkcs7.Unpad(ciphertext) } func aesDecryptFile(key []byte, file *os.File, downloadedSize int64) (int64, error) { @@ -533,14 +542,11 @@ func aesEncrypt(key, plaintext []byte) ([]byte, error) { return nil, err } - pad := aes.BlockSize - len(plaintext)%aes.BlockSize - plaintext = append(plaintext, bytes.Repeat([]byte{byte(pad)}, pad)...) - - ciphertext := make([]byte, len(plaintext)) + plaintext = pkcs7.Pad(plaintext, aes.BlockSize) iv := random.Bytes(16) mode := cipher.NewCBCEncrypter(block, iv) - mode.CryptBlocks(ciphertext, plaintext) + mode.CryptBlocks(plaintext, plaintext) - return append(iv, ciphertext...), nil + return append(iv, plaintext...), nil } From 6beb2faa9fa2ee2dda264f813766bd6517db5d84 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 23 Apr 2026 20:39:21 +0300 Subject: [PATCH 03/34] msgconv/from-matrix: preserve sticker pack metadata when sending to signal --- go.mod | 2 +- go.sum | 4 +-- pkg/msgconv/from-matrix.go | 29 ++++++++++--------- pkg/msgconv/from-signal.go | 20 ++++++------- pkg/msgconv/imagepack.go | 57 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 28 deletions(-) create mode 100644 pkg/msgconv/imagepack.go diff --git a/go.mod b/go.mod index 8df1d19..a4718d6 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( golang.org/x/net v0.53.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.27.0 + maunium.net/go/mautrix v0.27.1-0.20260428110059-49a05bf06436 ) require ( diff --git a/go.sum b/go.sum index af95348..ddff313 100644 --- a/go.sum +++ b/go.sum @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.27.0 h1:yfEYwoIluVWkofUgbZl9gP4i5nQTF+QNsxtb+r5bKlM= -maunium.net/go/mautrix v0.27.0/go.mod h1:7QpEQiTy6p4LHkXXaZI+N46tGYy8HMhD0JjzZAFoFWs= +maunium.net/go/mautrix v0.27.1-0.20260428110059-49a05bf06436 h1:vga9ypiOLJmGguxq4D1aquDPFihOuD99EGPEwva12UI= +maunium.net/go/mautrix v0.27.1-0.20260428110059-49a05bf06436/go.mod h1:4fZ0M0xB5ZtueQI65RilX28J/3794BeK+LaCg4U61Jk= diff --git a/pkg/msgconv/from-matrix.go b/pkg/msgconv/from-matrix.go index 89b0181..a334afd 100644 --- a/pkg/msgconv/from-matrix.go +++ b/pkg/msgconv/from-matrix.go @@ -110,21 +110,24 @@ func (mc *MessageConverter) ToSignal( return nil, fmt.Errorf("failed to convert sticker: %w", err) } att.Flags = proto.Uint32(uint32(signalpb.AttachmentPointer_BORDERLESS)) - var emoji *string - // TODO check for single grapheme cluster? - if len([]rune(content.Body)) == 1 { - emoji = proto.String(variationselector.Remove(content.Body)) - } - dm.Sticker = &signalpb.DataMessage_Sticker{ - // Signal iOS validates that pack id/key are of the correct length. - // Android is fine with any non-nil values (like a zero-length byte string). - PackId: make([]byte, 16), - PackKey: make([]byte, 32), - StickerId: proto.Uint32(0), - Data: att, - Emoji: emoji, + dm.Sticker = ParseStickerMeta(content.Info.BridgedSticker) + if dm.Sticker == nil { + var emoji *string + // TODO check for single grapheme cluster? + if len([]rune(content.Body)) == 1 { + emoji = proto.String(variationselector.Remove(content.Body)) + } + dm.Sticker = &signalpb.DataMessage_Sticker{ + // Signal iOS validates that pack id/key are of the correct length. + // Android is fine with any non-nil values (like a zero-length byte string). + PackId: make([]byte, 16), + PackKey: make([]byte, 32), + StickerId: proto.Uint32(0), + Emoji: emoji, + } } + dm.Sticker.Data = att case event.MsgLocation: lat, lon, err := parseGeoURI(content.GeoURI) if err != nil { diff --git a/pkg/msgconv/from-signal.go b/pkg/msgconv/from-signal.go index 96b4f10..defbe44 100644 --- a/pkg/msgconv/from-signal.go +++ b/pkg/msgconv/from-signal.go @@ -468,20 +468,16 @@ func (mc *MessageConverter) convertStickerToMatrix(ctx context.Context, sticker converted.Content.Info.Height = 200 } converted.Content.Body = sticker.GetEmoji() + if len(sticker.GetPackId()) == PackIDLength && len(sticker.GetPackKey()) == PackKeyLength && !bytes.Equal(sticker.GetPackId(), zeroPackID) { + converted.Content.Info.BridgedSticker = &event.BridgedSticker{ + Network: StickerSourceID, + ID: strconv.FormatUint(uint64(sticker.GetStickerId()), 10), + Emoji: sticker.GetEmoji(), + PackURL: fmt.Sprintf(PackURLFormat, sticker.GetPackId(), sticker.GetPackKey()), + } + } converted.Type = event.EventSticker converted.Content.MsgType = "" - if converted.Extra == nil { - converted.Extra = map[string]any{} - } - // TODO fetch full pack metadata like the old bridge did? - converted.Extra["fi.mau.signal.sticker"] = map[string]any{ - "id": sticker.GetStickerId(), - "emoji": sticker.GetEmoji(), - "pack": map[string]any{ - "id": sticker.GetPackId(), - "key": sticker.GetPackKey(), - }, - } return converted } diff --git a/pkg/msgconv/imagepack.go b/pkg/msgconv/imagepack.go new file mode 100644 index 0000000..910b5bc --- /dev/null +++ b/pkg/msgconv/imagepack.go @@ -0,0 +1,57 @@ +// mautrix-signal - A Matrix-Signal puppeting bridge. +// Copyright (C) 2026 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package msgconv + +import ( + "fmt" + "strconv" + + "google.golang.org/protobuf/proto" + "maunium.net/go/mautrix/event" + + signalpb "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf" +) + +const StickerSourceID = "signal" +const PackURLFormat = "https://signal.art/addstickers/#pack_id=%x&pack_key=%x" + +const PackIDLength = 16 +const PackKeyLength = 32 +const PackURLLength = len(PackURLFormat) - len("%x")*2 + PackIDLength*2 + PackKeyLength*2 + +var zeroPackID = make([]byte, PackIDLength) + +func ParseStickerMeta(info *event.BridgedSticker) *signalpb.DataMessage_Sticker { + if info.Network != StickerSourceID || len(info.PackURL) != PackURLLength { + return nil + } + stickerID, err := strconv.ParseUint(info.ID, 10, 32) + if err != nil { + return nil + } + var packID, packKey []byte + _, err = fmt.Sscanf(info.PackURL, PackURLFormat, &packID, &packKey) + if err != nil || len(packID) != PackIDLength || len(packKey) != PackKeyLength { + return nil + } + return &signalpb.DataMessage_Sticker{ + PackId: packID, + PackKey: packKey, + StickerId: proto.Uint32(uint32(stickerID)), + Emoji: &info.Emoji, + } +} From c2afb9f1135e125f6baa3252b4faf8a4ea960eba Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Mon, 27 Apr 2026 12:22:20 +0300 Subject: [PATCH 04/34] signalmeow/web: sent ContentLength field in request --- pkg/signalmeow/web/web.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/signalmeow/web/web.go b/pkg/signalmeow/web/web.go index d0fcd01..e617b40 100644 --- a/pkg/signalmeow/web/web.go +++ b/pkg/signalmeow/web/web.go @@ -129,6 +129,7 @@ func SendHTTPRequest(ctx context.Context, host, method, path string, opt *HTTPRe } else { req.Header.Set("Content-Type", string(ContentTypeJSON)) } + req.ContentLength = int64(len(opt.Body)) req.Header.Set("Content-Length", fmt.Sprintf("%d", len(opt.Body))) req.Header.Set("User-Agent", UserAgent) req.Header.Set("X-Signal-Agent", SignalAgent) From 9e9dc8b548b35a8a964358d835ae12b161d020fc Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Mon, 27 Apr 2026 12:30:54 +0300 Subject: [PATCH 05/34] signalmeow/sticker: add methods for creating and fetching sticker packs --- go.mod | 2 +- pkg/signalmeow/sticker.go | 251 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 pkg/signalmeow/sticker.go diff --git a/go.mod b/go.mod index a4718d6..030ad61 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( golang.org/x/crypto v0.50.0 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f golang.org/x/net v0.53.0 + golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 maunium.net/go/mautrix v0.27.1-0.20260428110059-49a05bf06436 @@ -43,7 +44,6 @@ require ( github.com/yuin/goldmark v1.8.2 // indirect go.mau.fi/zeroconfig v0.2.0 // indirect golang.org/x/mod v0.35.0 // indirect - golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.43.0 // indirect golang.org/x/text v0.36.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/pkg/signalmeow/sticker.go b/pkg/signalmeow/sticker.go new file mode 100644 index 0000000..2759d18 --- /dev/null +++ b/pkg/signalmeow/sticker.go @@ -0,0 +1,251 @@ +// mautrix-signal - A Matrix-signal puppeting bridge. +// Copyright (C) 2026 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package signalmeow + +import ( + "bytes" + "context" + "crypto/hkdf" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "io" + "mime/multipart" + "net/http" + "net/textproto" + "sync" + + "go.mau.fi/util/exerrors" + "go.mau.fi/util/random" + "golang.org/x/sync/semaphore" + "google.golang.org/protobuf/proto" + + signalpb "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf" + "go.mau.fi/mautrix-signal/pkg/signalmeow/web" +) + +func DownloadStickerPackManifest(ctx context.Context, packID, packKey []byte) (*signalpb.Pack, error) { + if len(packID) != 16 { + return nil, fmt.Errorf("invalid pack ID length: %d", len(packID)) + } + resp, err := downloadStickerData(ctx, fmt.Sprintf("/stickers/%x/manifest.proto", packID), packKey) + if err != nil { + return nil, err + } + var pack signalpb.Pack + err = proto.Unmarshal(resp, &pack) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal decrypted manifest: %w", err) + } + return &pack, nil +} + +func DownloadStickerPackItem(ctx context.Context, packID, packKey []byte, stickerID uint32) ([]byte, error) { + if len(packID) != 16 { + return nil, fmt.Errorf("invalid pack ID length: %d", len(packID)) + } + return downloadStickerData(ctx, fmt.Sprintf("/stickers/%x/full/%d", packID, stickerID), packKey) +} + +func downloadStickerData(ctx context.Context, path string, packKey []byte) ([]byte, error) { + if len(packKey) != 32 { + return nil, fmt.Errorf("invalid pack key length: %d", len(packKey)) + } + var body, decrypted []byte + resp, err := web.SendHTTPRequest(ctx, web.CDN1Hostname, http.MethodGet, path, nil) + defer web.CloseBody(resp) + if err != nil { + return nil, fmt.Errorf("failed to make request: %w", err) + } else if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode) + } else if body, err = io.ReadAll(resp.Body); err != nil { + return nil, fmt.Errorf("failed to read response: %w", err) + } else if decrypted, err = decryptSticker(packKey, body); err != nil { + return nil, fmt.Errorf("failed to decrypt response: %w", err) + } else { + return decrypted, nil + } +} + +type stickerUploadAttributes struct { + ACL string `json:"acl"` + Algorithm string `json:"algorithm"` + Credential string `json:"credential"` + Date string `json:"date"` + ID int `json:"id"` + Key string `json:"key"` + Policy string `json:"policy"` + Signature string `json:"signature"` +} + +func (sua *stickerUploadAttributes) makeFormBody(encryptedData []byte) (*web.HTTPReqOpt, error) { + var buf bytes.Buffer + writer := multipart.NewWriter(&buf) + var closed bool + // This isn't necessary in practice, just do it to avoid linter warnings + defer func() { + if !closed { + _ = writer.Close() + } + }() + fields := map[string]string{ + "key": sua.Key, + "acl": sua.ACL, + "policy": sua.Policy, + "x-amz-algorithm": sua.Algorithm, + "x-amz-credential": sua.Credential, + "x-amz-date": sua.Date, + "Content-Type": "application/octet-stream", + } + for key, value := range fields { + err := writer.WriteField(key, value) + if err != nil { + return nil, fmt.Errorf("failed to write multipart field %s: %w", key, err) + } + } + filePart, err := writer.CreatePart(textproto.MIMEHeader{ + "Content-Type": []string{"application/octet-stream"}, + "Content-Disposition": []string{`form-data; name="file"`}, + }) + if err != nil { + return nil, fmt.Errorf("failed to create multipart file part: %w", err) + } + _, err = filePart.Write(encryptedData) + if err != nil { + return nil, fmt.Errorf("failed to write file data to multipart body: %w", err) + } + err = writer.Close() + if err != nil { + return nil, fmt.Errorf("failed to close multipart writer: %w", err) + } + closed = true + return &web.HTTPReqOpt{ + Body: buf.Bytes(), + ContentType: web.ContentType(writer.FormDataContentType()), + }, nil +} + +func (sua *stickerUploadAttributes) upload(ctx context.Context, packKey, fileData []byte) error { + encryptedData, err := macAndAESEncrypt(fileData, deriveStickerPackKey(packKey)) + if err != nil { + return fmt.Errorf("failed to encrypt sticker data: %w", err) + } + req, err := sua.makeFormBody(encryptedData) + if err != nil { + return fmt.Errorf("failed to prepare request: %w", err) + } + resp, err := web.SendHTTPRequest(ctx, web.CDN1Hostname, http.MethodPost, "/", req) + if err != nil { + return err + } + _ = resp.Body.Close() + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return fmt.Errorf("unexpected status code %d", resp.StatusCode) + } + return nil +} + +func (sua *stickerUploadAttributes) uploadAsync( + ctx context.Context, + packKey []byte, + getFileData func(context.Context) ([]byte, error), + sema *semaphore.Weighted, + done func(), + onError func(error), +) { + defer done() + err := sema.Acquire(ctx, 1) + if err != nil { + return + } + defer sema.Release(1) + fileData, err := getFileData(ctx) + if err == nil { + err = sua.upload(ctx, packKey, fileData) + } + if err != nil { + onError(err) + } +} + +type stickerPackUploadAttributes struct { + PackID string `json:"packId"` + Manifest *stickerUploadAttributes `json:"manifest"` + Stickers []*stickerUploadAttributes `json:"stickers"` +} + +var StickerUploadParallelism = 4 + +func (cli *Client) UploadStickerPack(ctx context.Context, pack *signalpb.Pack, stickerData []func(context.Context) ([]byte, error)) (packID, packKey []byte, err error) { + for i, sticker := range pack.Stickers { + if sticker.GetId() >= uint32(len(stickerData)) { + return nil, nil, fmt.Errorf("sticker ID %d at index %d is out of bounds, only %d sticker blobs provided", sticker.GetId(), i, len(stickerData)) + } + } + marshaledPack, err := proto.Marshal(pack) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal pack: %w", err) + } + packKey = random.Bytes(32) + resp, err := cli.AuthedWS.SendRequest(ctx, http.MethodGet, fmt.Sprintf("/v1/sticker/pack/form/%d", len(stickerData)), nil, nil) + if err != nil { + return nil, nil, fmt.Errorf("failed to get upload form: %w", err) + } + var packAttributes stickerPackUploadAttributes + err = web.DecodeWSResponseBody(ctx, &packAttributes, resp) + if err != nil { + return nil, nil, fmt.Errorf("failed to decode pack attributes: %w", err) + } + if len(packAttributes.Stickers) != len(stickerData) { + return nil, nil, fmt.Errorf("expected %d sticker upload attribute sets, got %d", len(stickerData), len(packAttributes.Stickers)) + } + packID, err = hex.DecodeString(packAttributes.PackID) + if err != nil { + return nil, nil, fmt.Errorf("invalid pack ID in response: %w", err) + } + err = packAttributes.Manifest.upload(ctx, packKey, marshaledPack) + if err != nil { + return nil, nil, fmt.Errorf("failed to upload manifest: %w", err) + } + var wg sync.WaitGroup + wg.Add(len(packAttributes.Stickers)) + sema := semaphore.NewWeighted(int64(StickerUploadParallelism)) + var errorList []error + var errorLock sync.Mutex + for i, attrs := range packAttributes.Stickers { + go attrs.uploadAsync(ctx, packKey, stickerData[i], sema, wg.Done, func(err error) { + errorLock.Lock() + errorList = append(errorList, fmt.Errorf("failed to upload sticker #%d: %w", i+1, err)) + errorLock.Unlock() + }) + } + wg.Wait() + err = ctx.Err() + if err == nil { + err = errors.Join(errorList...) + } + return +} + +func decryptSticker(packKey, ciphertext []byte) ([]byte, error) { + return macAndAESDecrypt(ciphertext, deriveStickerPackKey(packKey)) +} + +func deriveStickerPackKey(key []byte) []byte { + return exerrors.Must(hkdf.Key(sha256.New, key, make([]byte, 32), "Sticker Pack", 2*32)) +} From a27b6745b2eeb7720ad74a1c890a1b58e969848c Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 29 Apr 2026 09:10:31 +0300 Subject: [PATCH 06/34] dependencies: update mautrix-go --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 030ad61..0a53f3b 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.27.1-0.20260428110059-49a05bf06436 + maunium.net/go/mautrix v0.27.1-0.20260429060852-d7aad0e862c7 ) require ( diff --git a/go.sum b/go.sum index ddff313..f291411 100644 --- a/go.sum +++ b/go.sum @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.27.1-0.20260428110059-49a05bf06436 h1:vga9ypiOLJmGguxq4D1aquDPFihOuD99EGPEwva12UI= -maunium.net/go/mautrix v0.27.1-0.20260428110059-49a05bf06436/go.mod h1:4fZ0M0xB5ZtueQI65RilX28J/3794BeK+LaCg4U61Jk= +maunium.net/go/mautrix v0.27.1-0.20260429060852-d7aad0e862c7 h1:ZL/dTgBuj7ZzH543brFUvxZo2lJGsCMBvnfKIvjdHC4= +maunium.net/go/mautrix v0.27.1-0.20260429060852-d7aad0e862c7/go.mod h1:4fZ0M0xB5ZtueQI65RilX28J/3794BeK+LaCg4U61Jk= From 14559977fc5d1d796a39170c7c1b39b4ab3303c5 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 30 Apr 2026 12:05:00 +0300 Subject: [PATCH 07/34] directmedia: fix response metadata for avatars --- go.mod | 2 +- go.sum | 4 ++-- pkg/connector/directmedia.go | 40 ++++++++++++++---------------------- 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 0a53f3b..9ef0f7b 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.27.1-0.20260429060852-d7aad0e862c7 + maunium.net/go/mautrix v0.27.1-0.20260430090139-beddfdeef6c9 ) require ( diff --git a/go.sum b/go.sum index f291411..1ae8e5f 100644 --- a/go.sum +++ b/go.sum @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.27.1-0.20260429060852-d7aad0e862c7 h1:ZL/dTgBuj7ZzH543brFUvxZo2lJGsCMBvnfKIvjdHC4= -maunium.net/go/mautrix v0.27.1-0.20260429060852-d7aad0e862c7/go.mod h1:4fZ0M0xB5ZtueQI65RilX28J/3794BeK+LaCg4U61Jk= +maunium.net/go/mautrix v0.27.1-0.20260430090139-beddfdeef6c9 h1:ffaVxcARQCkNq4Vw+AaXMUH4HcU5StEWOrfphM/jEfw= +maunium.net/go/mautrix v0.27.1-0.20260430090139-beddfdeef6c9/go.mod h1:4fZ0M0xB5ZtueQI65RilX28J/3794BeK+LaCg4U61Jk= diff --git a/pkg/connector/directmedia.go b/pkg/connector/directmedia.go index 0877d66..4f010f6 100644 --- a/pkg/connector/directmedia.go +++ b/pkg/connector/directmedia.go @@ -4,7 +4,6 @@ import ( "context" "encoding/base64" "fmt" - "io" "os" "maunium.net/go/mautrix/bridgev2" @@ -30,6 +29,7 @@ func (s *SignalConnector) Download(ctx context.Context, mediaID networkid.MediaI return nil, fmt.Errorf("failed to parse direct media id: %w", err) } + var rawDataResp []byte switch info := info.(type) { case *signalid.DirectMediaAttachment: log.Info(). @@ -76,18 +76,11 @@ func (s *SignalConnector) Download(ctx context.Context, mediaID networkid.MediaI return nil, fmt.Errorf("failed to to get group master key: %w", err) } - return &mediaproxy.GetMediaResponseCallback{ - Callback: func(w io.Writer) (int64, error) { - data, err := client.Client.DownloadGroupAvatar(ctx, info.GroupAvatarPath, groupMasterKey) - if err != nil { - log.Err(err).Msg("Direct download failed") - return 0, err - } - - _, err = w.Write(data) - return int64(len(data)), err - }, - }, nil + rawDataResp, err = client.Client.DownloadGroupAvatar(ctx, info.GroupAvatarPath, groupMasterKey) + if err != nil { + log.Err(err).Msg("Direct download failed") + return nil, err + } case *signalid.DirectMediaProfileAvatar: log.Info(). Stringer("user_id", info.UserID). @@ -111,19 +104,16 @@ func (s *SignalConnector) Download(ctx context.Context, mediaID networkid.MediaI return nil, fmt.Errorf("profile key not found") } - return &mediaproxy.GetMediaResponseCallback{ - Callback: func(w io.Writer) (int64, error) { - data, err := client.Client.DownloadUserAvatar(ctx, info.ProfileAvatarPath, *profileKey) - if err != nil { - log.Err(err).Msg("Direct download failed") - return 0, err - } - - _, err = w.Write(data) - return int64(len(data)), err - }, - }, nil + rawDataResp, err = client.Client.DownloadUserAvatar(ctx, info.ProfileAvatarPath, *profileKey) + if err != nil { + log.Err(err).Msg("Direct download failed") + return nil, err + } default: return nil, fmt.Errorf("no downloader for direct media type: %T", info) } + if rawDataResp == nil { + return nil, fmt.Errorf("unexpected fallthrough with no data") + } + return mediaproxy.GetMediaResponseRawData(rawDataResp), nil } From 1f1b645213c02b7142338ae7d6aaf2e803410f70 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 30 Apr 2026 12:26:24 +0300 Subject: [PATCH 08/34] client: add support for importing Signal sticker packs --- go.mod | 2 +- go.sum | 4 +- pkg/connector/client.go | 5 ++ pkg/connector/directmedia.go | 11 +++ pkg/msgconv/imagepack.go | 147 ++++++++++++++++++++++++++++++++++- pkg/signalid/media.go | 35 +++++++++ 6 files changed, 198 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 9ef0f7b..f409215 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/rs/zerolog v1.35.0 github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 - go.mau.fi/util v0.9.9-0.20260424160448-fd0d9737ad38 + go.mau.fi/util v0.9.9-0.20260430092340-8772e7714ea5 golang.org/x/crypto v0.50.0 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f golang.org/x/net v0.53.0 diff --git a/go.sum b/go.sum index 1ae8e5f..abe70ca 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -go.mau.fi/util v0.9.9-0.20260424160448-fd0d9737ad38 h1:D4OKITjyvlud39Q10oMnfhdeNkzEIVkXrEeCW6nvgLk= -go.mau.fi/util v0.9.9-0.20260424160448-fd0d9737ad38/go.mod h1:up/5mbzH2M1pSBNXqRxODn8dg/hEKbLJu92W4/SNAX0= +go.mau.fi/util v0.9.9-0.20260430092340-8772e7714ea5 h1:cNm4gkt7j907g1Q4XvyNKW8tTM8BaU91Kbfa5GGyiCs= +go.mau.fi/util v0.9.9-0.20260430092340-8772e7714ea5/go.mod h1:up/5mbzH2M1pSBNXqRxODn8dg/hEKbLJu92W4/SNAX0= go.mau.fi/zeroconfig v0.2.0 h1:e/OGEERqVRRKlgaro7E6bh8xXiKFSXB3eNNIud7FUjU= go.mau.fi/zeroconfig v0.2.0/go.mod h1:J0Vn0prHNOm493oZoQ84kq83ZaNCYZnq+noI1b1eN8w= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 17ee216..1f69191 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -46,6 +46,7 @@ type SignalClient struct { var ( _ bridgev2.NetworkAPI = (*SignalClient)(nil) _ bridgev2.BackgroundSyncingNetworkAPI = (*SignalClient)(nil) + _ bridgev2.StickerImportingNetworkAPI = (*SignalClient)(nil) ) var pushCfg = &bridgev2.PushConfig{ @@ -76,6 +77,10 @@ func (s *SignalClient) RegisterPushNotifications(ctx context.Context, pushType b } } +func (s *SignalClient) DownloadImagePack(ctx context.Context, url string) (*bridgev2.ImportedImagePack, error) { + return s.Main.MsgConv.DownloadImagePack(ctx, url) +} + func (s *SignalClient) LogoutRemote(ctx context.Context) { if s.Client == nil { return diff --git a/pkg/connector/directmedia.go b/pkg/connector/directmedia.go index 4f010f6..05e2a07 100644 --- a/pkg/connector/directmedia.go +++ b/pkg/connector/directmedia.go @@ -109,6 +109,17 @@ func (s *SignalConnector) Download(ctx context.Context, mediaID networkid.MediaI log.Err(err).Msg("Direct download failed") return nil, err } + case *signalid.DirectMediaSticker: + log.Info(). + Hex("pack_id", info.PackID). + Uint32("sticker_id", info.StickerID). + Msg("Direct downloading sticker") + + rawDataResp, err = signalmeow.DownloadStickerPackItem(ctx, info.PackID, info.PackKey, info.StickerID) + if err != nil { + log.Err(err).Msg("Direct download failed") + return nil, err + } default: return nil, fmt.Errorf("no downloader for direct media type: %T", info) } diff --git a/pkg/msgconv/imagepack.go b/pkg/msgconv/imagepack.go index 910b5bc..8d538bf 100644 --- a/pkg/msgconv/imagepack.go +++ b/pkg/msgconv/imagepack.go @@ -17,12 +17,23 @@ package msgconv import ( + "bytes" + "context" + "encoding/hex" "fmt" + "net/url" "strconv" + "strings" + "go.mau.fi/util/emojishortcodes" "google.golang.org/protobuf/proto" + "maunium.net/go/mautrix/bridgev2" + "maunium.net/go/mautrix/bridgev2/database" "maunium.net/go/mautrix/event" + "maunium.net/go/mautrix/id" + "go.mau.fi/mautrix-signal/pkg/signalid" + "go.mau.fi/mautrix-signal/pkg/signalmeow" signalpb "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf" ) @@ -43,9 +54,8 @@ func ParseStickerMeta(info *event.BridgedSticker) *signalpb.DataMessage_Sticker if err != nil { return nil } - var packID, packKey []byte - _, err = fmt.Sscanf(info.PackURL, PackURLFormat, &packID, &packKey) - if err != nil || len(packID) != PackIDLength || len(packKey) != PackKeyLength { + packID, packKey, err := parsePackURL(info.PackURL) + if err != nil || len(packID) != PackIDLength || len(packKey) != PackKeyLength || bytes.Equal(packID, zeroPackID) { return nil } return &signalpb.DataMessage_Sticker{ @@ -55,3 +65,134 @@ func ParseStickerMeta(info *event.BridgedSticker) *signalpb.DataMessage_Sticker Emoji: &info.Emoji, } } + +func parsePackURL(rawURL string) (packID, packKey []byte, err error) { + parsed, err := url.Parse(rawURL) + if err != nil { + return nil, nil, fmt.Errorf("invalid URL: %w", err) + } else if parsed.Host != "signal.art" || !strings.HasPrefix(parsed.Path, "/addstickers") { + return nil, nil, fmt.Errorf("invalid host or path in URL") + } + q, err := url.ParseQuery(parsed.Fragment) + if err != nil { + return nil, nil, fmt.Errorf("invalid URL fragment: %w", err) + } + packID, err = hex.DecodeString(q.Get("pack_id")) + if err != nil { + return nil, nil, fmt.Errorf("invalid pack ID in URL: %w", err) + } + packKey, err = hex.DecodeString(q.Get("pack_key")) + if err != nil { + return nil, nil, fmt.Errorf("invalid pack key in URL: %w", err) + } + return +} + +func (mc *MessageConverter) DownloadImagePack(ctx context.Context, url string) (*bridgev2.ImportedImagePack, error) { + packID, packKey, err := parsePackURL(url) + if err != nil { + return nil, err + } + manifest, err := signalmeow.DownloadStickerPackManifest(ctx, packID, packKey) + if err != nil { + return nil, fmt.Errorf("failed to download sticker pack manifest: %w", err) + } + topLevelExtra := map[string]any{ + "fi.mau.signal.stickerpack": map[string]any{ + "pack_id": hex.EncodeToString(packID), + "pack_key": hex.EncodeToString(packKey), + }, + } + content := &event.ImagePackEventContent{ + Images: make(map[string]*event.ImagePackImage, len(manifest.Stickers)), + Metadata: event.ImagePackMetadata{ + DisplayName: manifest.GetTitle(), + AvatarURL: "", + Usage: []event.ImagePackUsage{event.ImagePackUsageSticker}, + Attribution: manifest.GetAuthor(), + BridgedPack: &event.BridgedStickerPack{ + Network: StickerSourceID, + URL: fmt.Sprintf(PackURLFormat, packID, packKey), + }, + }, + } + imagesByID := make(map[uint32]id.ContentURIString, len(manifest.Stickers)) + uploadImage := func(sticker *signalpb.Pack_Sticker) (id.ContentURIString, error) { + stickerID := sticker.GetId() + existing, ok := imagesByID[stickerID] + if ok { + return existing, nil + } + var mxc id.ContentURIString + if mc.DirectMedia { + mediaID, err := signalid.DirectMediaSticker{ + PackID: packID, + PackKey: packKey, + StickerID: stickerID, + }.AsMediaID() + if err != nil { + return "", fmt.Errorf("failed to create media ID for sticker %d: %w", stickerID, err) + } + mxc, err = mc.Bridge.Matrix.GenerateContentURI(ctx, mediaID) + if err != nil { + return "", fmt.Errorf("failed to generate content URI for sticker %d: %w", stickerID, err) + } + } else { + dbKey := database.Key(fmt.Sprintf("stickercache:%x:%d", packID, stickerID)) + if cached := mc.Bridge.DB.KV.Get(ctx, dbKey); cached != "" { + mxc = id.ContentURIString(cached) + imagesByID[stickerID] = mxc + return mxc, nil + } + data, err := signalmeow.DownloadStickerPackItem(ctx, packID, packKey, stickerID) + if err != nil { + return "", fmt.Errorf("failed to download sticker %d: %w", stickerID, err) + } + mxc, _, err = mc.Bridge.Bot.UploadMedia(ctx, "", data, "", sticker.GetContentType()) + if err != nil { + return "", fmt.Errorf("failed to upload sticker %d: %w", stickerID, err) + } + mc.Bridge.DB.KV.Set(ctx, dbKey, string(mxc)) + } + imagesByID[stickerID] = mxc + return mxc, nil + } + for _, sticker := range manifest.Stickers { + mxc, err := uploadImage(sticker) + if err != nil { + return nil, err + } + shortcode := emojishortcodes.Get(sticker.GetEmoji()) + realShortcode := shortcode + i := 2 + for _, alreadyExists := content.Images[realShortcode]; alreadyExists; i++ { + realShortcode = fmt.Sprintf("%s_%d", shortcode, i) + } + content.Images[realShortcode] = &event.ImagePackImage{ + URL: mxc, + Body: sticker.GetEmoji(), + Info: &event.FileInfo{ + MimeType: sticker.GetContentType(), + Width: 200, + Height: 200, + BridgedSticker: &event.BridgedSticker{ + Network: StickerSourceID, + ID: strconv.FormatUint(uint64(sticker.GetId()), 10), + Emoji: sticker.GetEmoji(), + PackURL: content.Metadata.BridgedPack.URL, + }, + }, + } + } + if manifest.Cover != nil { + content.Metadata.AvatarURL, err = uploadImage(manifest.Cover) + if err != nil { + return nil, fmt.Errorf("failed to upload sticker pack cover: %w", err) + } + } + return &bridgev2.ImportedImagePack{ + Content: content, + Extra: topLevelExtra, + Shortcode: hex.EncodeToString(packID), + }, nil +} diff --git a/pkg/signalid/media.go b/pkg/signalid/media.go index 8c91b6a..a530c22 100644 --- a/pkg/signalid/media.go +++ b/pkg/signalid/media.go @@ -34,6 +34,7 @@ const ( directMediaTypeGroupAvatar directMediaType = 1 directMediaTypeProfileAvatar directMediaType = 2 directMediaTypePlaintextDigestAttachment directMediaType = 3 + directMediaTypeSticker directMediaType = 4 ) type DirectMediaInfo interface { @@ -44,6 +45,7 @@ var ( _ DirectMediaInfo = (*DirectMediaAttachment)(nil) _ DirectMediaInfo = (*DirectMediaGroupAvatar)(nil) _ DirectMediaInfo = (*DirectMediaProfileAvatar)(nil) + _ DirectMediaInfo = (*DirectMediaSticker)(nil) ) type DirectMediaAttachment struct { @@ -127,6 +129,30 @@ func (m DirectMediaProfileAvatar) AsMediaID() (mediaID networkid.MediaID, err er return networkid.MediaID(buf.Bytes()), nil } +type DirectMediaSticker struct { + PackID []byte + PackKey []byte + StickerID uint32 +} + +const packIDLen = 16 +const packKeyLen = 32 +const directMediaStickerLen = 1 + packIDLen + packKeyLen + 4 + +func (m DirectMediaSticker) AsMediaID() (mediaID networkid.MediaID, err error) { + if len(m.PackID) != packIDLen { + return nil, fmt.Errorf("invalid pack ID length: %d", len(m.PackID)) + } else if len(m.PackKey) != packKeyLen { + return nil, fmt.Errorf("invalid pack key length: %d", len(m.PackKey)) + } + mediaID = make(networkid.MediaID, directMediaStickerLen) + mediaID[0] = byte(directMediaTypeSticker) + copy(mediaID[1:], m.PackID) + copy(mediaID[1+packIDLen:], m.PackKey) + binary.BigEndian.PutUint32(mediaID[1+packIDLen+packKeyLen:], m.StickerID) + return mediaID, nil +} + func ParseDirectMediaInfo(mediaID networkid.MediaID) (_ DirectMediaInfo, err error) { mediaIDLen := len(mediaID) if mediaIDLen == 0 { @@ -200,6 +226,15 @@ func ParseDirectMediaInfo(mediaID networkid.MediaID) (_ DirectMediaInfo, err err info.ProfileAvatarPath = string(profileAvatarPath) } return &info, nil + case directMediaTypeSticker: + var info DirectMediaSticker + if len(mediaID) != directMediaStickerLen { + return info, fmt.Errorf("invalid media ID length for sticker: %d", len(mediaID)) + } + info.PackID = mediaID[1 : 1+packIDLen] + info.PackKey = mediaID[1+packIDLen : 1+packIDLen+packKeyLen] + info.StickerID = binary.BigEndian.Uint32(mediaID[1+packIDLen+packKeyLen:]) + return &info, nil } return nil, fmt.Errorf("invalid direct media type %d", mediaType) From 9ebd8d4dd09fbbbf3b39deaf673e01d9c611fe2d Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 30 Apr 2026 13:23:08 +0300 Subject: [PATCH 09/34] .github: add another item to bug report template --- .github/ISSUE_TEMPLATE/bug.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index c10630f..06ba9e8 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -11,7 +11,8 @@ type: Bug ### Checklist - + * [ ] This is an actual bug, not just a setup issue (see the [troubleshooting docs](https://docs.mau.fi/bridges/general/troubleshooting.html) or ask in the Matrix room for setup help). * [ ] I am certain that sufficient information is included. Ask in the Matrix room first if not. +* [ ] The bug is still present on the main branch. From 694858478c710b08a7a61e18a57b402d5d35eafc Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 30 Apr 2026 15:15:08 +0300 Subject: [PATCH 10/34] client: add stub ListImagePacks method --- go.mod | 2 +- go.sum | 4 ++-- pkg/connector/capabilities.go | 1 + pkg/connector/client.go | 5 +++++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f409215..a936973 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.27.1-0.20260430090139-beddfdeef6c9 + maunium.net/go/mautrix v0.27.1-0.20260430124810-125ac2c48014 ) require ( diff --git a/go.sum b/go.sum index abe70ca..f817e1d 100644 --- a/go.sum +++ b/go.sum @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.27.1-0.20260430090139-beddfdeef6c9 h1:ffaVxcARQCkNq4Vw+AaXMUH4HcU5StEWOrfphM/jEfw= -maunium.net/go/mautrix v0.27.1-0.20260430090139-beddfdeef6c9/go.mod h1:4fZ0M0xB5ZtueQI65RilX28J/3794BeK+LaCg4U61Jk= +maunium.net/go/mautrix v0.27.1-0.20260430124810-125ac2c48014 h1:KwXGBWwUHYJKVTYWgbZEFcaM6uYLMvfjzHJg/TLwvKc= +maunium.net/go/mautrix v0.27.1-0.20260430124810-125ac2c48014/go.mod h1:4fZ0M0xB5ZtueQI65RilX28J/3794BeK+LaCg4U61Jk= diff --git a/pkg/connector/capabilities.go b/pkg/connector/capabilities.go index e791324..d23285c 100644 --- a/pkg/connector/capabilities.go +++ b/pkg/connector/capabilities.go @@ -211,6 +211,7 @@ var signalGeneralCaps = &bridgev2.NetworkGeneralCapabilities{ AggressiveUpdateInfo: true, ImplicitReadReceipts: true, Provisioning: bridgev2.ProvisioningCapabilities{ + ImagePackImport: true, ResolveIdentifier: bridgev2.ResolveIdentifierCapabilities{ CreateDM: true, LookupPhone: true, diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 1f69191..4fcf188 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -27,6 +27,7 @@ import ( "maunium.net/go/mautrix/bridgev2" "maunium.net/go/mautrix/bridgev2/networkid" "maunium.net/go/mautrix/bridgev2/status" + "maunium.net/go/mautrix/event" "go.mau.fi/mautrix-signal/pkg/signalid" "go.mau.fi/mautrix-signal/pkg/signalmeow" @@ -81,6 +82,10 @@ func (s *SignalClient) DownloadImagePack(ctx context.Context, url string) (*brid return s.Main.MsgConv.DownloadImagePack(ctx, url) } +func (s *SignalClient) ListImagePacks(ctx context.Context) ([]*event.ImagePackMetadata, error) { + return []*event.ImagePackMetadata{}, nil +} + func (s *SignalClient) LogoutRemote(ctx context.Context) { if s.Client == nil { return From 0214ecc6005359dcb41bacd56cd07de5bc4521a3 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Mon, 4 May 2026 17:32:04 +0300 Subject: [PATCH 11/34] msgconv/imagepack: fix stickers with no bridged metadata --- pkg/msgconv/imagepack.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/msgconv/imagepack.go b/pkg/msgconv/imagepack.go index 8d538bf..e8f91cb 100644 --- a/pkg/msgconv/imagepack.go +++ b/pkg/msgconv/imagepack.go @@ -47,7 +47,7 @@ const PackURLLength = len(PackURLFormat) - len("%x")*2 + PackIDLength*2 + PackKe var zeroPackID = make([]byte, PackIDLength) func ParseStickerMeta(info *event.BridgedSticker) *signalpb.DataMessage_Sticker { - if info.Network != StickerSourceID || len(info.PackURL) != PackURLLength { + if info == nil || info.Network != StickerSourceID || len(info.PackURL) != PackURLLength { return nil } stickerID, err := strconv.ParseUint(info.ID, 10, 32) From 0813d3909524ec4db44284cc180a75685557c847 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 6 May 2026 13:23:56 +0300 Subject: [PATCH 12/34] .github: add version command to bug report template --- .github/ISSUE_TEMPLATE/bug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 06ba9e8..cba1054 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -15,4 +15,4 @@ type: Bug * [ ] This is an actual bug, not just a setup issue (see the [troubleshooting docs](https://docs.mau.fi/bridges/general/troubleshooting.html) or ask in the Matrix room for setup help). * [ ] I am certain that sufficient information is included. Ask in the Matrix room first if not. -* [ ] The bug is still present on the main branch. +* [ ] The bug is still present on the main branch. The `!signal version` command output is: `` From 90487a25e048d9677e059291d44d8f80a6a5a391 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 6 May 2026 13:47:09 +0300 Subject: [PATCH 13/34] imagepack: return 404 on incorrectly formatted link --- pkg/msgconv/imagepack.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/msgconv/imagepack.go b/pkg/msgconv/imagepack.go index e8f91cb..a2529af 100644 --- a/pkg/msgconv/imagepack.go +++ b/pkg/msgconv/imagepack.go @@ -27,6 +27,7 @@ import ( "go.mau.fi/util/emojishortcodes" "google.golang.org/protobuf/proto" + "maunium.net/go/mautrix" "maunium.net/go/mautrix/bridgev2" "maunium.net/go/mautrix/bridgev2/database" "maunium.net/go/mautrix/event" @@ -91,7 +92,7 @@ func parsePackURL(rawURL string) (packID, packKey []byte, err error) { func (mc *MessageConverter) DownloadImagePack(ctx context.Context, url string) (*bridgev2.ImportedImagePack, error) { packID, packKey, err := parsePackURL(url) if err != nil { - return nil, err + return nil, bridgev2.WrapRespErr(err, mautrix.MNotFound) } manifest, err := signalmeow.DownloadStickerPackManifest(ctx, packID, packKey) if err != nil { From 06bdbfc2cab281e91af2dc97f2cdc15512d00b7e Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 8 May 2026 16:55:42 +0300 Subject: [PATCH 14/34] libsignal: update to v0.93.2 --- pkg/libsignalgo/identitykeystore.go | 12 +- pkg/libsignalgo/kyberprekeystore.go | 8 +- pkg/libsignalgo/libsignal | 2 +- pkg/libsignalgo/libsignal-ffi.h | 191 ++++++++++++++------------- pkg/libsignalgo/message.go | 3 +- pkg/libsignalgo/prekeybundle.go | 3 +- pkg/libsignalgo/prekeystore.go | 8 +- pkg/libsignalgo/senderkeystore.go | 6 +- pkg/libsignalgo/session_test.go | 19 +-- pkg/libsignalgo/sessionstore.go | 6 +- pkg/libsignalgo/signedprekeystore.go | 6 +- pkg/libsignalgo/version.go | 2 +- pkg/signalmeow/keys.go | 5 + pkg/signalmeow/receiving_decrypt.go | 5 + 14 files changed, 147 insertions(+), 129 deletions(-) diff --git a/pkg/libsignalgo/identitykeystore.go b/pkg/libsignalgo/identitykeystore.go index 43941da..ba26f06 100644 --- a/pkg/libsignalgo/identitykeystore.go +++ b/pkg/libsignalgo/identitykeystore.go @@ -159,11 +159,11 @@ func signal_destroy_identity_key_store_callback(storeCtx unsafe.Pointer) { func (ctx *CallbackContext) wrapIdentityKeyStore(store IdentityKeyStore) C.SignalConstPointerFfiIdentityKeyStoreStruct { return C.SignalConstPointerFfiIdentityKeyStoreStruct{&C.SignalIdentityKeyStore{ ctx: wrapStore(ctx, store), - get_local_identity_key_pair: C.SignalFfiBridgeIdentityKeyStoreGetLocalIdentityKeyPair(C.signal_get_identity_key_pair_callback), - get_local_registration_id: C.SignalFfiBridgeIdentityKeyStoreGetLocalRegistrationId(C.signal_get_local_registration_id_callback), - get_identity_key: C.SignalFfiBridgeIdentityKeyStoreGetIdentityKey(C.signal_get_identity_key_callback), - save_identity_key: C.SignalFfiBridgeIdentityKeyStoreSaveIdentityKey(C.signal_save_identity_key_callback), - is_trusted_identity: C.SignalFfiBridgeIdentityKeyStoreIsTrustedIdentity(C.signal_is_trusted_identity_callback), - destroy: C.SignalFfiBridgeIdentityKeyStoreDestroy(C.signal_destroy_identity_key_store_callback), + get_local_identity_key_pair: C.SignalFfiIdentityKeyStoreGetLocalIdentityKeyPair(C.signal_get_identity_key_pair_callback), + get_local_registration_id: C.SignalFfiIdentityKeyStoreGetLocalRegistrationId(C.signal_get_local_registration_id_callback), + get_identity_key: C.SignalFfiIdentityKeyStoreGetIdentityKey(C.signal_get_identity_key_callback), + save_identity_key: C.SignalFfiIdentityKeyStoreSaveIdentityKey(C.signal_save_identity_key_callback), + is_trusted_identity: C.SignalFfiIdentityKeyStoreIsTrustedIdentity(C.signal_is_trusted_identity_callback), + destroy: C.SignalFfiIdentityKeyStoreDestroy(C.signal_destroy_identity_key_store_callback), }} } diff --git a/pkg/libsignalgo/kyberprekeystore.go b/pkg/libsignalgo/kyberprekeystore.go index ebb5a9f..9deea17 100644 --- a/pkg/libsignalgo/kyberprekeystore.go +++ b/pkg/libsignalgo/kyberprekeystore.go @@ -77,9 +77,9 @@ func signal_destroy_kyber_pre_key_store_callback(storeCtx unsafe.Pointer) { func (ctx *CallbackContext) wrapKyberPreKeyStore(store KyberPreKeyStore) C.SignalConstPointerFfiKyberPreKeyStoreStruct { return C.SignalConstPointerFfiKyberPreKeyStoreStruct{&C.SignalKyberPreKeyStore{ ctx: wrapStore(ctx, store), - load_kyber_pre_key: C.SignalFfiBridgeKyberPreKeyStoreLoadKyberPreKey(C.signal_load_kyber_pre_key_callback), - store_kyber_pre_key: C.SignalFfiBridgeKyberPreKeyStoreStoreKyberPreKey(C.signal_store_kyber_pre_key_callback), - mark_kyber_pre_key_used: C.SignalFfiBridgeKyberPreKeyStoreMarkKyberPreKeyUsed(C.signal_mark_kyber_pre_key_used_callback), - destroy: C.SignalFfiBridgeKyberPreKeyStoreDestroy(C.signal_destroy_kyber_pre_key_store_callback), + load_kyber_pre_key: C.SignalFfiKyberPreKeyStoreLoadKyberPreKey(C.signal_load_kyber_pre_key_callback), + store_kyber_pre_key: C.SignalFfiKyberPreKeyStoreStoreKyberPreKey(C.signal_store_kyber_pre_key_callback), + mark_kyber_pre_key_used: C.SignalFfiKyberPreKeyStoreMarkKyberPreKeyUsed(C.signal_mark_kyber_pre_key_used_callback), + destroy: C.SignalFfiKyberPreKeyStoreDestroy(C.signal_destroy_kyber_pre_key_store_callback), }} } diff --git a/pkg/libsignalgo/libsignal b/pkg/libsignalgo/libsignal index b58bd7d..bbc1688 160000 --- a/pkg/libsignalgo/libsignal +++ b/pkg/libsignalgo/libsignal @@ -1 +1 @@ -Subproject commit b58bd7d5dfa0a391486df4210fd83bab96b9b479 +Subproject commit bbc16886cae2feab1cd1fe271ccc651e8860ce96 diff --git a/pkg/libsignalgo/libsignal-ffi.h b/pkg/libsignalgo/libsignal-ffi.h index fe3bf52..b75462a 100644 --- a/pkg/libsignalgo/libsignal-ffi.h +++ b/pkg/libsignalgo/libsignal-ffi.h @@ -629,13 +629,6 @@ typedef struct { const SignalHttpRequest *raw; } SignalConstPointerHttpRequest; -/** - * A wrapper type for raw UUIDs, because C treats arrays specially in argument position. - */ -typedef struct { - uint8_t bytes[16]; -} SignalUuid; - /** * The fixed-width binary representation of a ServiceId. * @@ -643,6 +636,27 @@ typedef struct { */ typedef uint8_t SignalServiceIdFixedWidthBinaryBytes[17]; +typedef struct { + const uint32_t *base; + size_t length; +} SignalBorrowedSliceOfu32; + +typedef struct { + const SignalCiphertextMessage *raw; +} SignalConstPointerCiphertextMessage; + +typedef struct { + const SignalConstPointerCiphertextMessage *base; + size_t length; +} SignalBorrowedSliceOfConstPointerCiphertextMessage; + +/** + * A wrapper type for raw UUIDs, because C treats arrays specially in argument position. + */ +typedef struct { + uint8_t bytes[16]; +} SignalUuid; + typedef struct { SignalPrivateKey *raw; } SignalMutPointerPrivateKey; @@ -754,10 +768,6 @@ typedef struct { const SignalPlaintextContent *raw; } SignalConstPointerPlaintextContent; -typedef struct { - const SignalCiphertextMessage *raw; -} SignalConstPointerCiphertextMessage; - typedef struct { SignalConnectionInfo *raw; } SignalMutPointerConnectionInfo; @@ -782,20 +792,18 @@ typedef struct { SignalSessionRecord *raw; } SignalMutPointerSessionRecord; -typedef int (*SignalFfiBridgeSessionStoreLoadSession)(void *ctx, SignalMutPointerSessionRecord *out, SignalMutPointerProtocolAddress address); +typedef int (*SignalFfiSessionStoreLoadSession)(void *ctx, SignalMutPointerSessionRecord *out, SignalMutPointerProtocolAddress address); -typedef int (*SignalFfiBridgeSessionStoreStoreSession)(void *ctx, SignalMutPointerProtocolAddress address, SignalMutPointerSessionRecord record); +typedef int (*SignalFfiSessionStoreStoreSession)(void *ctx, SignalMutPointerProtocolAddress address, SignalMutPointerSessionRecord record); -typedef void (*SignalFfiBridgeSessionStoreDestroy)(void *ctx); +typedef void (*SignalFfiSessionStoreDestroy)(void *ctx); typedef struct { void *ctx; - SignalFfiBridgeSessionStoreLoadSession load_session; - SignalFfiBridgeSessionStoreStoreSession store_session; - SignalFfiBridgeSessionStoreDestroy destroy; -} SignalFfiBridgeSessionStoreStruct; - -typedef SignalFfiBridgeSessionStoreStruct SignalSessionStore; + SignalFfiSessionStoreLoadSession load_session; + SignalFfiSessionStoreStoreSession store_session; + SignalFfiSessionStoreDestroy destroy; +} SignalSessionStore; typedef struct { const SignalSessionStore *raw; @@ -810,29 +818,27 @@ typedef struct { SignalMutPointerPublicKey second; } SignalPairOfMutPointerPrivateKeyMutPointerPublicKey; -typedef int (*SignalFfiBridgeIdentityKeyStoreGetLocalIdentityKeyPair)(void *ctx, SignalPairOfMutPointerPrivateKeyMutPointerPublicKey *out); +typedef int (*SignalFfiIdentityKeyStoreGetLocalIdentityKeyPair)(void *ctx, SignalPairOfMutPointerPrivateKeyMutPointerPublicKey *out); -typedef int (*SignalFfiBridgeIdentityKeyStoreGetLocalRegistrationId)(void *ctx, uint32_t *out); +typedef int (*SignalFfiIdentityKeyStoreGetLocalRegistrationId)(void *ctx, uint32_t *out); -typedef int (*SignalFfiBridgeIdentityKeyStoreGetIdentityKey)(void *ctx, SignalMutPointerPublicKey *out, SignalMutPointerProtocolAddress address); +typedef int (*SignalFfiIdentityKeyStoreGetIdentityKey)(void *ctx, SignalMutPointerPublicKey *out, SignalMutPointerProtocolAddress address); -typedef int (*SignalFfiBridgeIdentityKeyStoreSaveIdentityKey)(void *ctx, uint8_t *out, SignalMutPointerProtocolAddress address, SignalMutPointerPublicKey public_key); +typedef int (*SignalFfiIdentityKeyStoreSaveIdentityKey)(void *ctx, uint8_t *out, SignalMutPointerProtocolAddress address, SignalMutPointerPublicKey public_key); -typedef int (*SignalFfiBridgeIdentityKeyStoreIsTrustedIdentity)(void *ctx, bool *out, SignalMutPointerProtocolAddress address, SignalMutPointerPublicKey public_key, uint32_t direction); +typedef int (*SignalFfiIdentityKeyStoreIsTrustedIdentity)(void *ctx, bool *out, SignalMutPointerProtocolAddress address, SignalMutPointerPublicKey public_key, uint32_t direction); -typedef void (*SignalFfiBridgeIdentityKeyStoreDestroy)(void *ctx); +typedef void (*SignalFfiIdentityKeyStoreDestroy)(void *ctx); typedef struct { void *ctx; - SignalFfiBridgeIdentityKeyStoreGetLocalIdentityKeyPair get_local_identity_key_pair; - SignalFfiBridgeIdentityKeyStoreGetLocalRegistrationId get_local_registration_id; - SignalFfiBridgeIdentityKeyStoreGetIdentityKey get_identity_key; - SignalFfiBridgeIdentityKeyStoreSaveIdentityKey save_identity_key; - SignalFfiBridgeIdentityKeyStoreIsTrustedIdentity is_trusted_identity; - SignalFfiBridgeIdentityKeyStoreDestroy destroy; -} SignalFfiBridgeIdentityKeyStoreStruct; - -typedef SignalFfiBridgeIdentityKeyStoreStruct SignalIdentityKeyStore; + SignalFfiIdentityKeyStoreGetLocalIdentityKeyPair get_local_identity_key_pair; + SignalFfiIdentityKeyStoreGetLocalRegistrationId get_local_registration_id; + SignalFfiIdentityKeyStoreGetIdentityKey get_identity_key; + SignalFfiIdentityKeyStoreSaveIdentityKey save_identity_key; + SignalFfiIdentityKeyStoreIsTrustedIdentity is_trusted_identity; + SignalFfiIdentityKeyStoreDestroy destroy; +} SignalIdentityKeyStore; typedef struct { const SignalIdentityKeyStore *raw; @@ -846,23 +852,21 @@ typedef struct { SignalPreKeyRecord *raw; } SignalMutPointerPreKeyRecord; -typedef int (*SignalFfiBridgePreKeyStoreLoadPreKey)(void *ctx, SignalMutPointerPreKeyRecord *out, uint32_t id); +typedef int (*SignalFfiPreKeyStoreLoadPreKey)(void *ctx, SignalMutPointerPreKeyRecord *out, uint32_t id); -typedef int (*SignalFfiBridgePreKeyStoreStorePreKey)(void *ctx, uint32_t id, SignalMutPointerPreKeyRecord record); +typedef int (*SignalFfiPreKeyStoreStorePreKey)(void *ctx, uint32_t id, SignalMutPointerPreKeyRecord record); -typedef int (*SignalFfiBridgePreKeyStoreRemovePreKey)(void *ctx, uint32_t id); +typedef int (*SignalFfiPreKeyStoreRemovePreKey)(void *ctx, uint32_t id); -typedef void (*SignalFfiBridgePreKeyStoreDestroy)(void *ctx); +typedef void (*SignalFfiPreKeyStoreDestroy)(void *ctx); typedef struct { void *ctx; - SignalFfiBridgePreKeyStoreLoadPreKey load_pre_key; - SignalFfiBridgePreKeyStoreStorePreKey store_pre_key; - SignalFfiBridgePreKeyStoreRemovePreKey remove_pre_key; - SignalFfiBridgePreKeyStoreDestroy destroy; -} SignalFfiBridgePreKeyStoreStruct; - -typedef SignalFfiBridgePreKeyStoreStruct SignalPreKeyStore; + SignalFfiPreKeyStoreLoadPreKey load_pre_key; + SignalFfiPreKeyStoreStorePreKey store_pre_key; + SignalFfiPreKeyStoreRemovePreKey remove_pre_key; + SignalFfiPreKeyStoreDestroy destroy; +} SignalPreKeyStore; typedef struct { const SignalPreKeyStore *raw; @@ -872,20 +876,18 @@ typedef struct { SignalSignedPreKeyRecord *raw; } SignalMutPointerSignedPreKeyRecord; -typedef int (*SignalFfiBridgeSignedPreKeyStoreLoadSignedPreKey)(void *ctx, SignalMutPointerSignedPreKeyRecord *out, uint32_t id); +typedef int (*SignalFfiSignedPreKeyStoreLoadSignedPreKey)(void *ctx, SignalMutPointerSignedPreKeyRecord *out, uint32_t id); -typedef int (*SignalFfiBridgeSignedPreKeyStoreStoreSignedPreKey)(void *ctx, uint32_t id, SignalMutPointerSignedPreKeyRecord record); +typedef int (*SignalFfiSignedPreKeyStoreStoreSignedPreKey)(void *ctx, uint32_t id, SignalMutPointerSignedPreKeyRecord record); -typedef void (*SignalFfiBridgeSignedPreKeyStoreDestroy)(void *ctx); +typedef void (*SignalFfiSignedPreKeyStoreDestroy)(void *ctx); typedef struct { void *ctx; - SignalFfiBridgeSignedPreKeyStoreLoadSignedPreKey load_signed_pre_key; - SignalFfiBridgeSignedPreKeyStoreStoreSignedPreKey store_signed_pre_key; - SignalFfiBridgeSignedPreKeyStoreDestroy destroy; -} SignalFfiBridgeSignedPreKeyStoreStruct; - -typedef SignalFfiBridgeSignedPreKeyStoreStruct SignalSignedPreKeyStore; + SignalFfiSignedPreKeyStoreLoadSignedPreKey load_signed_pre_key; + SignalFfiSignedPreKeyStoreStoreSignedPreKey store_signed_pre_key; + SignalFfiSignedPreKeyStoreDestroy destroy; +} SignalSignedPreKeyStore; typedef struct { const SignalSignedPreKeyStore *raw; @@ -895,23 +897,21 @@ typedef struct { SignalKyberPreKeyRecord *raw; } SignalMutPointerKyberPreKeyRecord; -typedef int (*SignalFfiBridgeKyberPreKeyStoreLoadKyberPreKey)(void *ctx, SignalMutPointerKyberPreKeyRecord *out, uint32_t id); +typedef int (*SignalFfiKyberPreKeyStoreLoadKyberPreKey)(void *ctx, SignalMutPointerKyberPreKeyRecord *out, uint32_t id); -typedef int (*SignalFfiBridgeKyberPreKeyStoreStoreKyberPreKey)(void *ctx, uint32_t id, SignalMutPointerKyberPreKeyRecord record); +typedef int (*SignalFfiKyberPreKeyStoreStoreKyberPreKey)(void *ctx, uint32_t id, SignalMutPointerKyberPreKeyRecord record); -typedef int (*SignalFfiBridgeKyberPreKeyStoreMarkKyberPreKeyUsed)(void *ctx, uint32_t id, uint32_t ec_prekey_id, SignalMutPointerPublicKey base_key); +typedef int (*SignalFfiKyberPreKeyStoreMarkKyberPreKeyUsed)(void *ctx, uint32_t id, uint32_t ec_prekey_id, SignalMutPointerPublicKey base_key); -typedef void (*SignalFfiBridgeKyberPreKeyStoreDestroy)(void *ctx); +typedef void (*SignalFfiKyberPreKeyStoreDestroy)(void *ctx); typedef struct { void *ctx; - SignalFfiBridgeKyberPreKeyStoreLoadKyberPreKey load_kyber_pre_key; - SignalFfiBridgeKyberPreKeyStoreStoreKyberPreKey store_kyber_pre_key; - SignalFfiBridgeKyberPreKeyStoreMarkKyberPreKeyUsed mark_kyber_pre_key_used; - SignalFfiBridgeKyberPreKeyStoreDestroy destroy; -} SignalFfiBridgeKyberPreKeyStoreStruct; - -typedef SignalFfiBridgeKyberPreKeyStoreStruct SignalKyberPreKeyStore; + SignalFfiKyberPreKeyStoreLoadKyberPreKey load_kyber_pre_key; + SignalFfiKyberPreKeyStoreStoreKyberPreKey store_kyber_pre_key; + SignalFfiKyberPreKeyStoreMarkKyberPreKeyUsed mark_kyber_pre_key_used; + SignalFfiKyberPreKeyStoreDestroy destroy; +} SignalKyberPreKeyStore; typedef struct { const SignalKyberPreKeyStore *raw; @@ -1047,20 +1047,18 @@ typedef struct { SignalSenderKeyRecord *raw; } SignalMutPointerSenderKeyRecord; -typedef int (*SignalFfiBridgeSenderKeyStoreLoadSenderKey)(void *ctx, SignalMutPointerSenderKeyRecord *out, SignalMutPointerProtocolAddress sender, SignalUuid distribution_id); +typedef int (*SignalFfiSenderKeyStoreLoadSenderKey)(void *ctx, SignalMutPointerSenderKeyRecord *out, SignalMutPointerProtocolAddress sender, SignalUuid distribution_id); -typedef int (*SignalFfiBridgeSenderKeyStoreStoreSenderKey)(void *ctx, SignalMutPointerProtocolAddress sender, SignalUuid distribution_id, SignalMutPointerSenderKeyRecord record); +typedef int (*SignalFfiSenderKeyStoreStoreSenderKey)(void *ctx, SignalMutPointerProtocolAddress sender, SignalUuid distribution_id, SignalMutPointerSenderKeyRecord record); -typedef void (*SignalFfiBridgeSenderKeyStoreDestroy)(void *ctx); +typedef void (*SignalFfiSenderKeyStoreDestroy)(void *ctx); typedef struct { void *ctx; - SignalFfiBridgeSenderKeyStoreLoadSenderKey load_sender_key; - SignalFfiBridgeSenderKeyStoreStoreSenderKey store_sender_key; - SignalFfiBridgeSenderKeyStoreDestroy destroy; -} SignalFfiBridgeSenderKeyStoreStruct; - -typedef SignalFfiBridgeSenderKeyStoreStruct SignalSenderKeyStore; + SignalFfiSenderKeyStoreLoadSenderKey load_sender_key; + SignalFfiSenderKeyStoreStoreSenderKey store_sender_key; + SignalFfiSenderKeyStoreDestroy destroy; +} SignalSenderKeyStore; typedef struct { const SignalSenderKeyStore *raw; @@ -1117,6 +1115,11 @@ typedef struct { SignalFfiLoggerDestroy destroy; } SignalFfiLoggerStruct; +typedef struct { + SignalOwnedBuffer first; + SignalOwnedBuffer second; +} SignalPairOfOwnedBufferOfc_ucharOwnedBufferOfc_uchar; + /** * A C callback used to report the results of Rust futures. * @@ -1127,10 +1130,10 @@ typedef struct { * completed once. */ typedef struct { - void (*complete)(SignalFfiError *error, const SignalOwnedBuffer *result, const void *context); + void (*complete)(SignalFfiError *error, const SignalPairOfOwnedBufferOfc_ucharOwnedBufferOfc_uchar *result, const void *context); const void *context; SignalCancellationId cancellation_id; -} SignalCPromiseOwnedBufferOfc_uchar; +} SignalCPromisePairOfOwnedBufferOfc_ucharOwnedBufferOfc_uchar; typedef struct { const SignalUnauthenticatedChatConnection *raw; @@ -1200,20 +1203,18 @@ typedef struct { const SignalMessageBackupValidationOutcome *raw; } SignalConstPointerMessageBackupValidationOutcome; -typedef int (*SignalFfiBridgeInputStreamRead)(void *ctx, size_t *out, SignalBorrowedMutableBuffer buf); +typedef int (*SignalFfiInputStreamRead)(void *ctx, size_t *out, SignalBorrowedMutableBuffer buf); -typedef int (*SignalFfiBridgeInputStreamSkip)(void *ctx, uint64_t amount); +typedef int (*SignalFfiInputStreamSkip)(void *ctx, uint64_t amount); -typedef void (*SignalFfiBridgeInputStreamDestroy)(void *ctx); +typedef void (*SignalFfiInputStreamDestroy)(void *ctx); typedef struct { void *ctx; - SignalFfiBridgeInputStreamRead read; - SignalFfiBridgeInputStreamSkip skip; - SignalFfiBridgeInputStreamDestroy destroy; -} SignalFfiBridgeInputStreamStruct; - -typedef SignalFfiBridgeInputStreamStruct SignalInputStream; + SignalFfiInputStreamRead read; + SignalFfiInputStreamSkip skip; + SignalFfiInputStreamDestroy destroy; +} SignalInputStream; typedef struct { const SignalInputStream *raw; @@ -1647,9 +1648,7 @@ typedef struct { SignalValidatingMac *raw; } SignalMutPointerValidatingMac; -typedef SignalFfiBridgeInputStreamStruct SignalFfiBridgeSyncInputStreamStruct; - -typedef SignalFfiBridgeSyncInputStreamStruct SignalSyncInputStream; +typedef SignalInputStream SignalSyncInputStream; typedef struct { const SignalSyncInputStream *raw; @@ -1737,6 +1736,10 @@ SignalFfiError *signal_authenticated_chat_connection_preconnect(SignalCPromisebo SignalFfiError *signal_authenticated_chat_connection_send(SignalCPromiseFfiChatResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, SignalConstPointerHttpRequest http_request, uint32_t timeout_millis); +SignalFfiError *signal_authenticated_chat_connection_send_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *destination, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfConstPointerCiphertextMessage contents, bool online_only, bool is_urgent); + +SignalFfiError *signal_authenticated_chat_connection_send_sync_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfConstPointerCiphertextMessage contents, bool is_urgent); + SignalFfiError *signal_backup_auth_credential_check_valid_contents(SignalBorrowedBuffer params_bytes); SignalFfiError *signal_backup_auth_credential_get_backup_id(uint8_t (*out)[16], SignalBorrowedBuffer credential_bytes); @@ -1897,7 +1900,7 @@ SignalFfiError *signal_create_call_link_credential_request_issue_deterministic(S SignalFfiError *signal_create_call_link_credential_response_check_valid_contents(SignalBorrowedBuffer response_bytes); -SignalFfiError *signal_decrypt_message(SignalOwnedBuffer *out, SignalConstPointerSignalMessage message, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store); +SignalFfiError *signal_decrypt_message(SignalOwnedBuffer *out, SignalConstPointerSignalMessage message, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerProtocolAddress local_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store); SignalFfiError *signal_decrypt_pre_key_message(SignalOwnedBuffer *out, SignalConstPointerPreKeySignalMessage message, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerProtocolAddress local_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, SignalConstPointerFfiPreKeyStoreStruct prekey_store, SignalConstPointerFfiSignedPreKeyStoreStruct signed_prekey_store, SignalConstPointerFfiKyberPreKeyStoreStruct kyber_prekey_store); @@ -2118,9 +2121,7 @@ bool signal_init_logger(SignalLogLevel max_level, SignalFfiLoggerStruct logger); SignalFfiError *signal_key_transparency_aci_search_key(SignalOwnedBuffer *out, const SignalServiceIdFixedWidthBinaryBytes *aci); -SignalFfiError *signal_key_transparency_check(SignalCPromiseOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, uint8_t environment, SignalConstPointerUnauthenticatedChatConnection chat_connection, const SignalServiceIdFixedWidthBinaryBytes *aci, SignalConstPointerPublicKey aci_identity_key, const char *e164, SignalOptionalBorrowedSliceOfc_uchar unidentified_access_key, SignalOptionalBorrowedSliceOfc_uchar username_hash, SignalOptionalBorrowedSliceOfc_uchar account_data, SignalBorrowedBuffer last_distinguished_tree_head, bool is_self_check, bool is_e164_discoverable); - -SignalFfiError *signal_key_transparency_distinguished(SignalCPromiseOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, uint8_t environment, SignalConstPointerUnauthenticatedChatConnection chat_connection, SignalOptionalBorrowedSliceOfc_uchar last_distinguished_tree_head); +SignalFfiError *signal_key_transparency_check(SignalCPromisePairOfOwnedBufferOfc_ucharOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, uint8_t environment, SignalConstPointerUnauthenticatedChatConnection chat_connection, const SignalServiceIdFixedWidthBinaryBytes *aci, SignalConstPointerPublicKey aci_identity_key, const char *e164, SignalOptionalBorrowedSliceOfc_uchar unidentified_access_key, SignalOptionalBorrowedSliceOfc_uchar username_hash, SignalOptionalBorrowedSliceOfc_uchar account_data, SignalOptionalBorrowedSliceOfc_uchar last_distinguished_tree_head, bool is_self_check, bool is_e164_discoverable); SignalFfiError *signal_key_transparency_e164_search_key(SignalOwnedBuffer *out, const char *e164); @@ -2354,7 +2355,7 @@ SignalFfiError *signal_privatekey_serialize(SignalOwnedBuffer *out, SignalConstP SignalFfiError *signal_privatekey_sign(SignalOwnedBuffer *out, SignalConstPointerPrivateKey key, SignalBorrowedBuffer message); -SignalFfiError *signal_process_prekey_bundle(SignalConstPointerPreKeyBundle bundle, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, uint64_t now); +SignalFfiError *signal_process_prekey_bundle(SignalConstPointerPreKeyBundle bundle, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerProtocolAddress local_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, uint64_t now); SignalFfiError *signal_process_sender_key_distribution_message(SignalConstPointerProtocolAddress sender, SignalConstPointerSenderKeyDistributionMessage sender_key_distribution_message, SignalConstPointerFfiSenderKeyStoreStruct store); @@ -2782,6 +2783,8 @@ SignalFfiError *signal_unauthenticated_chat_connection_look_up_username_link(Sig SignalFfiError *signal_unauthenticated_chat_connection_send(SignalCPromiseFfiChatResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalConstPointerHttpRequest http_request, uint32_t timeout_millis); +SignalFfiError *signal_unauthenticated_chat_connection_send_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *destination, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfBuffers contents, uint8_t auth_kind, SignalOptionalBorrowedSliceOfc_uchar auth_buffer, bool online_only, bool is_urgent); + SignalFfiError *signal_unauthenticated_chat_connection_send_multi_recipient_message(SignalCPromiseOwnedBufferOfServiceIdFixedWidthBinaryBytes *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer payload, uint64_t timestamp, SignalBorrowedBuffer auth, bool online_only, bool is_urgent); SignalFfiError *signal_unidentified_sender_message_content_deserialize(SignalMutPointerUnidentifiedSenderMessageContent *out, SignalBorrowedBuffer data); diff --git a/pkg/libsignalgo/message.go b/pkg/libsignalgo/message.go index 1b581c0..6cba873 100644 --- a/pkg/libsignalgo/message.go +++ b/pkg/libsignalgo/message.go @@ -49,7 +49,7 @@ func Encrypt(ctx context.Context, plaintext []byte, forAddress, localAddress *Ad return wrapCiphertextMessage(ciphertextMessage.raw), nil } -func Decrypt(ctx context.Context, message *Message, fromAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore) ([]byte, error) { +func Decrypt(ctx context.Context, message *Message, fromAddress, localAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore) ([]byte, error) { callbackCtx := NewCallbackContext(ctx) defer callbackCtx.Unref() var decrypted C.SignalOwnedBuffer = C.SignalOwnedBuffer{} @@ -57,6 +57,7 @@ func Decrypt(ctx context.Context, message *Message, fromAddress *Address, sessio &decrypted, message.constPtr(), fromAddress.constPtr(), + localAddress.constPtr(), callbackCtx.wrapSessionStore(sessionStore), callbackCtx.wrapIdentityKeyStore(identityStore), ) diff --git a/pkg/libsignalgo/prekeybundle.go b/pkg/libsignalgo/prekeybundle.go index 4cd5547..8a6fcaa 100644 --- a/pkg/libsignalgo/prekeybundle.go +++ b/pkg/libsignalgo/prekeybundle.go @@ -27,13 +27,14 @@ import ( "time" ) -func ProcessPreKeyBundle(ctx context.Context, bundle *PreKeyBundle, forAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore) error { +func ProcessPreKeyBundle(ctx context.Context, bundle *PreKeyBundle, forAddress, localAddress *Address, sessionStore SessionStore, identityStore IdentityKeyStore) error { callbackCtx := NewCallbackContext(ctx) defer callbackCtx.Unref() var now C.uint64_t = C.uint64_t(time.Now().Unix()) signalFfiError := C.signal_process_prekey_bundle( bundle.constPtr(), forAddress.constPtr(), + localAddress.constPtr(), callbackCtx.wrapSessionStore(sessionStore), callbackCtx.wrapIdentityKeyStore(identityStore), now, diff --git a/pkg/libsignalgo/prekeystore.go b/pkg/libsignalgo/prekeystore.go index ed8ea21..8c3c36f 100644 --- a/pkg/libsignalgo/prekeystore.go +++ b/pkg/libsignalgo/prekeystore.go @@ -76,9 +76,9 @@ func signal_destroy_pre_key_store_callback(storeCtx unsafe.Pointer) { func (ctx *CallbackContext) wrapPreKeyStore(store PreKeyStore) C.SignalConstPointerFfiPreKeyStoreStruct { return C.SignalConstPointerFfiPreKeyStoreStruct{&C.SignalPreKeyStore{ ctx: wrapStore(ctx, store), - load_pre_key: C.SignalFfiBridgePreKeyStoreLoadPreKey(C.signal_load_pre_key_callback), - store_pre_key: C.SignalFfiBridgePreKeyStoreStorePreKey(C.signal_store_pre_key_callback), - remove_pre_key: C.SignalFfiBridgePreKeyStoreRemovePreKey(C.signal_remove_pre_key_callback), - destroy: C.SignalFfiBridgePreKeyStoreDestroy(C.signal_destroy_pre_key_store_callback), + load_pre_key: C.SignalFfiPreKeyStoreLoadPreKey(C.signal_load_pre_key_callback), + store_pre_key: C.SignalFfiPreKeyStoreStorePreKey(C.signal_store_pre_key_callback), + remove_pre_key: C.SignalFfiPreKeyStoreRemovePreKey(C.signal_remove_pre_key_callback), + destroy: C.SignalFfiPreKeyStoreDestroy(C.signal_destroy_pre_key_store_callback), }} } diff --git a/pkg/libsignalgo/senderkeystore.go b/pkg/libsignalgo/senderkeystore.go index a07a287..1649216 100644 --- a/pkg/libsignalgo/senderkeystore.go +++ b/pkg/libsignalgo/senderkeystore.go @@ -70,8 +70,8 @@ func signal_destroy_sender_key_store_callback(storeCtx unsafe.Pointer) { func (ctx *CallbackContext) wrapSenderKeyStore(store SenderKeyStore) C.SignalConstPointerFfiSenderKeyStoreStruct { return C.SignalConstPointerFfiSenderKeyStoreStruct{&C.SignalSenderKeyStore{ ctx: wrapStore(ctx, store), - load_sender_key: C.SignalFfiBridgeSenderKeyStoreLoadSenderKey(C.signal_load_sender_key_callback), - store_sender_key: C.SignalFfiBridgeSenderKeyStoreStoreSenderKey(C.signal_store_sender_key_callback), - destroy: C.SignalFfiBridgeSenderKeyStoreDestroy(C.signal_destroy_sender_key_store_callback), + load_sender_key: C.SignalFfiSenderKeyStoreLoadSenderKey(C.signal_load_sender_key_callback), + store_sender_key: C.SignalFfiSenderKeyStoreStoreSenderKey(C.signal_store_sender_key_callback), + destroy: C.SignalFfiSenderKeyStoreDestroy(C.signal_destroy_sender_key_store_callback), }} } diff --git a/pkg/libsignalgo/session_test.go b/pkg/libsignalgo/session_test.go index 4bde894..dd05718 100644 --- a/pkg/libsignalgo/session_test.go +++ b/pkg/libsignalgo/session_test.go @@ -30,7 +30,7 @@ import ( "go.mau.fi/mautrix-signal/pkg/libsignalgo" ) -func initializeSessions(t *testing.T, aliceStore, bobStore *InMemorySignalProtocolStore, bobAddress *libsignalgo.Address) { +func initializeSessions(t *testing.T, aliceStore, bobStore *InMemorySignalProtocolStore, bobAddress, aliceAddress *libsignalgo.Address) { ctx := context.TODO() bobPreKey, err := libsignalgo.GeneratePrivateKey() @@ -86,7 +86,7 @@ func initializeSessions(t *testing.T, aliceStore, bobStore *InMemorySignalProtoc assert.NoError(t, err) // Alice processes the bundle - err = libsignalgo.ProcessPreKeyBundle(ctx, bobBundle, bobAddress, aliceStore, aliceStore) + err = libsignalgo.ProcessPreKeyBundle(ctx, bobBundle, bobAddress, aliceAddress, aliceStore, aliceStore) assert.NoError(t, err) record, err := aliceStore.LoadSession(ctx, bobAddress) @@ -132,7 +132,7 @@ func TestSessionCipher(t *testing.T) { aliceStore := NewInMemorySignalProtocolStore() bobStore := NewInMemorySignalProtocolStore() - initializeSessions(t, aliceStore, bobStore, bobAddress) + initializeSessions(t, aliceStore, bobStore, bobAddress, aliceAddress) alicePlaintext := []byte{8, 6, 7, 5, 3, 0, 9} @@ -163,7 +163,7 @@ func TestSessionCipher(t *testing.T) { assert.NoError(t, err) aliceCiphertext2, err := libsignalgo.DeserializeMessage(bobCiphertext2Serialized) assert.NoError(t, err) - alicePlaintext2, err := libsignalgo.Decrypt(ctx, aliceCiphertext2, bobAddress, aliceStore, aliceStore) + alicePlaintext2, err := libsignalgo.Decrypt(ctx, aliceCiphertext2, bobAddress, aliceAddress, aliceStore, aliceStore) assert.NoError(t, err) assert.Equal(t, bobPlaintext2, alicePlaintext2) } @@ -183,7 +183,7 @@ func TestSessionCipherWithBadStore(t *testing.T) { aliceStore := NewInMemorySignalProtocolStore() bobStore := &BadInMemorySignalProtocolStore{NewInMemorySignalProtocolStore()} - initializeSessions(t, aliceStore, bobStore.InMemorySignalProtocolStore, bobAddress) + initializeSessions(t, aliceStore, bobStore.InMemorySignalProtocolStore, bobAddress, aliceAddress) alicePlaintext := []byte{8, 6, 7, 5, 3, 0, 9} @@ -216,7 +216,7 @@ func TestSealedSenderEncrypt_Repeated(t *testing.T) { aliceStore := NewInMemorySignalProtocolStore() bobStore := NewInMemorySignalProtocolStore() - initializeSessions(t, aliceStore, bobStore, bobAddress) + initializeSessions(t, aliceStore, bobStore, bobAddress, aliceAddress) trustRoot, err := libsignalgo.GenerateIdentityKeyPair() assert.NoError(t, err) @@ -252,15 +252,18 @@ func TestArchiveSession(t *testing.T) { ctx := context.TODO() setupLogging() + aliceACI := uuid.New() bobACI := uuid.New() + aliceAddress, err := libsignalgo.NewACIServiceID(aliceACI).Address(1) + assert.NoError(t, err) bobAddress, err := libsignalgo.NewACIServiceID(bobACI).Address(1) assert.NoError(t, err) aliceStore := NewInMemorySignalProtocolStore() bobStore := NewInMemorySignalProtocolStore() - initializeSessions(t, aliceStore, bobStore, bobAddress) + initializeSessions(t, aliceStore, bobStore, bobAddress, aliceAddress) session, err := aliceStore.LoadSession(ctx, bobAddress) assert.NoError(t, err) @@ -315,7 +318,7 @@ func TestSealedSenderGroupCipher(t *testing.T) { bobStore := NewInMemorySignalProtocolStore() - initializeSessions(t, aliceStore, bobStore, bobAddress) + initializeSessions(t, aliceStore, bobStore, bobAddress, aliceAddress) trustRoot, err := libsignalgo.GenerateIdentityKeyPair() assert.NoError(t, err) diff --git a/pkg/libsignalgo/sessionstore.go b/pkg/libsignalgo/sessionstore.go index 2515232..99000e5 100644 --- a/pkg/libsignalgo/sessionstore.go +++ b/pkg/libsignalgo/sessionstore.go @@ -67,8 +67,8 @@ func signal_destroy_session_store_callback(storeCtx unsafe.Pointer) { func (ctx *CallbackContext) wrapSessionStore(store SessionStore) C.SignalConstPointerFfiSessionStoreStruct { return C.SignalConstPointerFfiSessionStoreStruct{&C.SignalSessionStore{ ctx: wrapStore(ctx, store), - load_session: C.SignalFfiBridgeSessionStoreLoadSession(C.signal_load_session_callback), - store_session: C.SignalFfiBridgeSessionStoreStoreSession(C.signal_store_session_callback), - destroy: C.SignalFfiBridgeSessionStoreDestroy(C.signal_destroy_session_store_callback), + load_session: C.SignalFfiSessionStoreLoadSession(C.signal_load_session_callback), + store_session: C.SignalFfiSessionStoreStoreSession(C.signal_store_session_callback), + destroy: C.SignalFfiSessionStoreDestroy(C.signal_destroy_session_store_callback), }} } diff --git a/pkg/libsignalgo/signedprekeystore.go b/pkg/libsignalgo/signedprekeystore.go index cfb3015..b1306e2 100644 --- a/pkg/libsignalgo/signedprekeystore.go +++ b/pkg/libsignalgo/signedprekeystore.go @@ -67,8 +67,8 @@ func signal_destroy_signed_pre_key_store_callback(storeCtx unsafe.Pointer) { func (ctx *CallbackContext) wrapSignedPreKeyStore(store SignedPreKeyStore) C.SignalConstPointerFfiSignedPreKeyStoreStruct { return C.SignalConstPointerFfiSignedPreKeyStoreStruct{&C.SignalSignedPreKeyStore{ ctx: wrapStore(ctx, store), - load_signed_pre_key: C.SignalFfiBridgeSignedPreKeyStoreLoadSignedPreKey(C.signal_load_signed_pre_key_callback), - store_signed_pre_key: C.SignalFfiBridgeSignedPreKeyStoreStoreSignedPreKey(C.signal_store_signed_pre_key_callback), - destroy: C.SignalFfiBridgeSignedPreKeyStoreDestroy(C.signal_destroy_signed_pre_key_store_callback), + load_signed_pre_key: C.SignalFfiSignedPreKeyStoreLoadSignedPreKey(C.signal_load_signed_pre_key_callback), + store_signed_pre_key: C.SignalFfiSignedPreKeyStoreStoreSignedPreKey(C.signal_store_signed_pre_key_callback), + destroy: C.SignalFfiSignedPreKeyStoreDestroy(C.signal_destroy_signed_pre_key_store_callback), }} } diff --git a/pkg/libsignalgo/version.go b/pkg/libsignalgo/version.go index bd14084..1f7e94d 100644 --- a/pkg/libsignalgo/version.go +++ b/pkg/libsignalgo/version.go @@ -2,4 +2,4 @@ package libsignalgo -const Version = "v0.92.1" +const Version = "v0.93.2" diff --git a/pkg/signalmeow/keys.go b/pkg/signalmeow/keys.go index f1801e5..5439755 100644 --- a/pkg/signalmeow/keys.go +++ b/pkg/signalmeow/keys.go @@ -413,6 +413,10 @@ func (cli *Client) FetchAndProcessPreKey(ctx context.Context, theirServiceID lib if cli.Store.RecipientStore.IsUnregistered(ctx, theirServiceID) { return fmt.Errorf("%w (cached)", ErrUnregisteredUser) } + localAddress, err := cli.Store.ACIServiceID().Address(uint(cli.Store.DeviceID)) + if err != nil { + return fmt.Errorf("failed to get own address: %w", err) + } // Fetch prekey deviceIDPath := "/*" if specificDeviceID >= 0 { @@ -518,6 +522,7 @@ func (cli *Client) FetchAndProcessPreKey(ctx context.Context, theirServiceID lib ctx, preKeyBundle, address, + localAddress, cli.Store.ACISessionStore, cli.Store.ACIIdentityStore, ) diff --git a/pkg/signalmeow/receiving_decrypt.go b/pkg/signalmeow/receiving_decrypt.go index 6296f00..1d2c8cc 100644 --- a/pkg/signalmeow/receiving_decrypt.go +++ b/pkg/signalmeow/receiving_decrypt.go @@ -243,11 +243,16 @@ func (cli *Client) decryptCiphertextEnvelope( if identityStore == nil { return nil, fmt.Errorf("no identity store for destination service ID %s", destinationServiceID) } + destinationAddress, err := destinationServiceID.Address(uint(cli.Store.DeviceID)) + if err != nil { + return nil, fmt.Errorf("failed to get own address: %w", err) + } plaintext, ciphertextHash, err := cli.bufferedDecryptTxn(ctx, ciphertext, serverTimestamp, func(ctx context.Context) ([]byte, error) { return libsignalgo.Decrypt( ctx, message, senderAddress, + destinationAddress, sessionStore, identityStore, ) From 4f1ebf7aa2708374c0e71d3f76913e07485aad96 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 8 May 2026 16:56:40 +0300 Subject: [PATCH 15/34] dependencies: update mautrix-go --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index a936973..c9cf551 100644 --- a/go.mod +++ b/go.mod @@ -11,17 +11,17 @@ require ( github.com/emersion/go-vcard v0.0.0-20241024213814-c9703dde27ff github.com/google/uuid v1.6.0 github.com/mattn/go-pointer v0.0.1 - github.com/rs/zerolog v1.35.0 + github.com/rs/zerolog v1.35.1 github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 - go.mau.fi/util v0.9.9-0.20260430092340-8772e7714ea5 + go.mau.fi/util v0.9.9-0.20260508133822-4207002539ff golang.org/x/crypto v0.50.0 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f golang.org/x/net v0.53.0 golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.27.1-0.20260430124810-125ac2c48014 + maunium.net/go/mautrix v0.27.1-0.20260507230413-b25744aa7730 ) require ( @@ -32,7 +32,7 @@ require ( github.com/lib/pq v1.12.3 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-sqlite3 v1.14.42 // indirect + github.com/mattn/go-sqlite3 v1.14.44 // indirect github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect diff --git a/go.sum b/go.sum index f817e1d..69eb732 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= -github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo= -github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ= +github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8= +github.com/mattn/go-sqlite3 v1.14.44/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ= github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 h1:WDsQxOJDy0N1VRAjXLpi8sCEZRSGarLWQevDxpTBRrM= github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -42,8 +42,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= -github.com/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI= -github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= +github.com/rs/zerolog v1.35.1 h1:m7xQeoiLIiV0BCEY4Hs+j2NG4Gp2o2KPKmhnnLiazKI= +github.com/rs/zerolog v1.35.1/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= @@ -61,8 +61,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -go.mau.fi/util v0.9.9-0.20260430092340-8772e7714ea5 h1:cNm4gkt7j907g1Q4XvyNKW8tTM8BaU91Kbfa5GGyiCs= -go.mau.fi/util v0.9.9-0.20260430092340-8772e7714ea5/go.mod h1:up/5mbzH2M1pSBNXqRxODn8dg/hEKbLJu92W4/SNAX0= +go.mau.fi/util v0.9.9-0.20260508133822-4207002539ff h1:nH8zuwSw5uu2pal7p9x5BSAvavuiJqRFN558XvcTtKg= +go.mau.fi/util v0.9.9-0.20260508133822-4207002539ff/go.mod h1:jE9FfhbgEgAwxei6lomO9v8zdCIATcquONUu4vjRwSs= go.mau.fi/zeroconfig v0.2.0 h1:e/OGEERqVRRKlgaro7E6bh8xXiKFSXB3eNNIud7FUjU= go.mau.fi/zeroconfig v0.2.0/go.mod h1:J0Vn0prHNOm493oZoQ84kq83ZaNCYZnq+noI1b1eN8w= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.27.1-0.20260430124810-125ac2c48014 h1:KwXGBWwUHYJKVTYWgbZEFcaM6uYLMvfjzHJg/TLwvKc= -maunium.net/go/mautrix v0.27.1-0.20260430124810-125ac2c48014/go.mod h1:4fZ0M0xB5ZtueQI65RilX28J/3794BeK+LaCg4U61Jk= +maunium.net/go/mautrix v0.27.1-0.20260507230413-b25744aa7730 h1:GcBSD72Ez7D3LoFVprsFFQx3mKcaRh983KpLIiifw68= +maunium.net/go/mautrix v0.27.1-0.20260507230413-b25744aa7730/go.mod h1:2ANjihDB+wv2UAqJapkRekmNXw7khSisccAkE5Jg3P0= From 9cdd4c9963726af2d1f2eaaeec41f18adf3284c9 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 8 May 2026 16:57:56 +0300 Subject: [PATCH 16/34] signalmeow: update protobufs --- pkg/signalmeow/protobuf/ContactDiscovery.pb.go | 2 +- pkg/signalmeow/protobuf/DeviceName.pb.go | 2 +- pkg/signalmeow/protobuf/Groups.pb.go | 2 +- pkg/signalmeow/protobuf/Provisioning.pb.go | 2 +- pkg/signalmeow/protobuf/SignalService.pb.go | 2 +- pkg/signalmeow/protobuf/StickerResources.pb.go | 2 +- pkg/signalmeow/protobuf/StorageService.pb.go | 15 ++++++++++++--- pkg/signalmeow/protobuf/StorageService.proto | 1 + .../protobuf/UnidentifiedDelivery.pb.go | 2 +- pkg/signalmeow/protobuf/WebSocketResources.pb.go | 2 +- pkg/signalmeow/protobuf/backuppb/Backup.pb.go | 2 +- pkg/signalmeow/protobuf/update-protos.sh | 4 ++-- 12 files changed, 24 insertions(+), 14 deletions(-) diff --git a/pkg/signalmeow/protobuf/ContactDiscovery.pb.go b/pkg/signalmeow/protobuf/ContactDiscovery.pb.go index 637a2d2..5cb232c 100644 --- a/pkg/signalmeow/protobuf/ContactDiscovery.pb.go +++ b/pkg/signalmeow/protobuf/ContactDiscovery.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: ContactDiscovery.proto // Copyright 2021 Signal Messenger, LLC diff --git a/pkg/signalmeow/protobuf/DeviceName.pb.go b/pkg/signalmeow/protobuf/DeviceName.pb.go index 5666b7e..31b5704 100644 --- a/pkg/signalmeow/protobuf/DeviceName.pb.go +++ b/pkg/signalmeow/protobuf/DeviceName.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: DeviceName.proto // Copyright 2018 Signal Messenger, LLC diff --git a/pkg/signalmeow/protobuf/Groups.pb.go b/pkg/signalmeow/protobuf/Groups.pb.go index 0c2b81b..8d4e2e3 100644 --- a/pkg/signalmeow/protobuf/Groups.pb.go +++ b/pkg/signalmeow/protobuf/Groups.pb.go @@ -5,7 +5,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: Groups.proto package signalpb diff --git a/pkg/signalmeow/protobuf/Provisioning.pb.go b/pkg/signalmeow/protobuf/Provisioning.pb.go index c925fe6..88ebe90 100644 --- a/pkg/signalmeow/protobuf/Provisioning.pb.go +++ b/pkg/signalmeow/protobuf/Provisioning.pb.go @@ -5,7 +5,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: Provisioning.proto package signalpb diff --git a/pkg/signalmeow/protobuf/SignalService.pb.go b/pkg/signalmeow/protobuf/SignalService.pb.go index 32842bf..c4268dd 100644 --- a/pkg/signalmeow/protobuf/SignalService.pb.go +++ b/pkg/signalmeow/protobuf/SignalService.pb.go @@ -5,7 +5,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: SignalService.proto package signalpb diff --git a/pkg/signalmeow/protobuf/StickerResources.pb.go b/pkg/signalmeow/protobuf/StickerResources.pb.go index e83cda1..f8194aa 100644 --- a/pkg/signalmeow/protobuf/StickerResources.pb.go +++ b/pkg/signalmeow/protobuf/StickerResources.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: StickerResources.proto package signalpb diff --git a/pkg/signalmeow/protobuf/StorageService.pb.go b/pkg/signalmeow/protobuf/StorageService.pb.go index 619221f..bbe88ef 100644 --- a/pkg/signalmeow/protobuf/StorageService.pb.go +++ b/pkg/signalmeow/protobuf/StorageService.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: StorageService.proto package signalpb @@ -1401,6 +1401,7 @@ type GroupV2Record struct { HideStory bool `protobuf:"varint,8,opt,name=hideStory,proto3" json:"hideStory,omitempty"` StorySendMode GroupV2Record_StorySendMode `protobuf:"varint,10,opt,name=storySendMode,proto3,enum=signalservice.GroupV2Record_StorySendMode" json:"storySendMode,omitempty"` AvatarColor *AvatarColor `protobuf:"varint,11,opt,name=avatarColor,proto3,enum=signalservice.AvatarColor,oneof" json:"avatarColor,omitempty"` + VerifiedNameHash []byte `protobuf:"bytes,12,opt,name=verifiedNameHash,proto3" json:"verifiedNameHash,omitempty"` // SHA-256 of UTF-8 encoded decrypted group title that was last verified unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1505,6 +1506,13 @@ func (x *GroupV2Record) GetAvatarColor() AvatarColor { return AvatarColor_A100 } +func (x *GroupV2Record) GetVerifiedNameHash() []byte { + if x != nil { + return x.VerifiedNameHash + } + return nil +} + type Payments struct { state protoimpl.MessageState `protogen:"open.v1"` Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` @@ -3195,7 +3203,7 @@ const file_StorageService_proto_rawDesc = "" + "\vwhitelisted\x18\x03 \x01(\bR\vwhitelisted\x12\x1a\n" + "\barchived\x18\x04 \x01(\bR\barchived\x12\"\n" + "\fmarkedUnread\x18\x05 \x01(\bR\fmarkedUnread\x120\n" + - "\x13mutedUntilTimestamp\x18\x06 \x01(\x04R\x13mutedUntilTimestamp\"\xa1\x04\n" + + "\x13mutedUntilTimestamp\x18\x06 \x01(\x04R\x13mutedUntilTimestamp\"\xcd\x04\n" + "\rGroupV2Record\x12\x1c\n" + "\tmasterKey\x18\x01 \x01(\fR\tmasterKey\x12\x18\n" + "\ablocked\x18\x02 \x01(\bR\ablocked\x12 \n" + @@ -3207,7 +3215,8 @@ const file_StorageService_proto_rawDesc = "" + "\thideStory\x18\b \x01(\bR\thideStory\x12P\n" + "\rstorySendMode\x18\n" + " \x01(\x0e2*.signalservice.GroupV2Record.StorySendModeR\rstorySendMode\x12A\n" + - "\vavatarColor\x18\v \x01(\x0e2\x1a.signalservice.AvatarColorH\x00R\vavatarColor\x88\x01\x01\"7\n" + + "\vavatarColor\x18\v \x01(\x0e2\x1a.signalservice.AvatarColorH\x00R\vavatarColor\x88\x01\x01\x12*\n" + + "\x10verifiedNameHash\x18\f \x01(\fR\x10verifiedNameHash\"7\n" + "\rStorySendMode\x12\v\n" + "\aDEFAULT\x10\x00\x12\f\n" + "\bDISABLED\x10\x01\x12\v\n" + diff --git a/pkg/signalmeow/protobuf/StorageService.proto b/pkg/signalmeow/protobuf/StorageService.proto index d22babc..dd232ca 100644 --- a/pkg/signalmeow/protobuf/StorageService.proto +++ b/pkg/signalmeow/protobuf/StorageService.proto @@ -172,6 +172,7 @@ message GroupV2Record { reserved /* storySendEnabled */ 9; StorySendMode storySendMode = 10; optional AvatarColor avatarColor = 11; + bytes verifiedNameHash = 12; // SHA-256 of UTF-8 encoded decrypted group title that was last verified } message Payments { diff --git a/pkg/signalmeow/protobuf/UnidentifiedDelivery.pb.go b/pkg/signalmeow/protobuf/UnidentifiedDelivery.pb.go index e30f6d6..5979a4c 100644 --- a/pkg/signalmeow/protobuf/UnidentifiedDelivery.pb.go +++ b/pkg/signalmeow/protobuf/UnidentifiedDelivery.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: UnidentifiedDelivery.proto // Copyright 2018 Signal Messenger, LLC diff --git a/pkg/signalmeow/protobuf/WebSocketResources.pb.go b/pkg/signalmeow/protobuf/WebSocketResources.pb.go index f35110d..66520eb 100644 --- a/pkg/signalmeow/protobuf/WebSocketResources.pb.go +++ b/pkg/signalmeow/protobuf/WebSocketResources.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: WebSocketResources.proto package signalpb diff --git a/pkg/signalmeow/protobuf/backuppb/Backup.pb.go b/pkg/signalmeow/protobuf/backuppb/Backup.pb.go index 326c170..bc488e7 100644 --- a/pkg/signalmeow/protobuf/backuppb/Backup.pb.go +++ b/pkg/signalmeow/protobuf/backuppb/Backup.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc v6.33.5 +// protoc v7.34.1 // source: backuppb/Backup.proto package backuppb diff --git a/pkg/signalmeow/protobuf/update-protos.sh b/pkg/signalmeow/protobuf/update-protos.sh index ffaa697..f9c86fc 100755 --- a/pkg/signalmeow/protobuf/update-protos.sh +++ b/pkg/signalmeow/protobuf/update-protos.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -ANDROID_GIT_REVISION=${1:-dfd2f7baf96825834f784900ce644e9ead8a9a89} -DESKTOP_GIT_REVISION=${1:-60a1e125452ee672d8747564d0055d5bfec9f679} +ANDROID_GIT_REVISION=${1:-439760e7732585bfd078d92d93732c04cc31e29e} +DESKTOP_GIT_REVISION=${1:-1b2a3e7b283c32c5654a39da12fc04139fd26dbd} update_proto() { case "$1" in From 4545def01787e39cf9c86b5fa7e726330de17b28 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Mon, 11 May 2026 16:16:36 +0300 Subject: [PATCH 17/34] signalmeow/web: log request durations --- pkg/signalmeow/web/web.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/signalmeow/web/web.go b/pkg/signalmeow/web/web.go index e617b40..f211b77 100644 --- a/pkg/signalmeow/web/web.go +++ b/pkg/signalmeow/web/web.go @@ -28,6 +28,7 @@ import ( "net/http" "runtime" "strings" + "time" "github.com/rs/zerolog" @@ -140,12 +141,14 @@ func SendHTTPRequest(ctx context.Context, host, method, path string, opt *HTTPRe httpReqCounter++ log = log.With().Int("request_number", httpReqCounter).Logger() log.Trace().Msg("Sending HTTP request") + start := time.Now() resp, err := SignalHTTPClient.Do(req) + dur := time.Since(start) if err != nil { - log.Err(err).Msg("Error sending request") + log.Err(err).Dur("duration", dur).Msg("Error sending request") return nil, err } - log.Debug().Int("status_code", resp.StatusCode).Msg("received HTTP response") + log.Debug().Int("status_code", resp.StatusCode).Dur("duration", dur).Msg("Received HTTP response") return resp, nil } From 41a37cd1844c63737b1ccca80d54118cf5c02819 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Tue, 12 May 2026 11:43:06 +0200 Subject: [PATCH 18/34] capabilities: drop webp to only partial support (#649) Co-authored-by: Tulir Asokan --- pkg/connector/capabilities.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/connector/capabilities.go b/pkg/connector/capabilities.go index d23285c..5eab6a8 100644 --- a/pkg/connector/capabilities.go +++ b/pkg/connector/capabilities.go @@ -38,7 +38,7 @@ func supportedIfFFmpeg() event.CapabilitySupportLevel { } func capID() string { - base := "fi.mau.signal.capabilities.2025_12_09" + base := "fi.mau.signal.capabilities.2026_05_12" if ffmpeg.Supported() { return base + "+ffmpeg" } @@ -111,7 +111,8 @@ var signalCaps = &event.RoomFeatures{ }, event.CapMsgSticker: { MimeTypes: map[string]event.CapabilitySupportLevel{ - "image/webp": event.CapLevelFullySupported, + // Signal clients will only render static webp, so apng is preferred + "image/webp": event.CapLevelPartialSupport, "image/png": event.CapLevelFullySupported, "image/apng": event.CapLevelFullySupported, "image/gif": supportedIfFFmpeg(), @@ -236,5 +237,5 @@ func (s *SignalConnector) GetCapabilities() *bridgev2.NetworkGeneralCapabilities } func (s *SignalConnector) GetBridgeInfoVersion() (info, capabilities int) { - return 1, 7 + return 1, 8 } From 14592ffdccac3ea222a2ac787c7405133d227cfa Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 12 May 2026 16:00:56 +0300 Subject: [PATCH 19/34] dependencies: update mautrix-go --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c9cf551..db72345 100644 --- a/go.mod +++ b/go.mod @@ -14,14 +14,14 @@ require ( github.com/rs/zerolog v1.35.1 github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.18.0 - go.mau.fi/util v0.9.9-0.20260508133822-4207002539ff + go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25 golang.org/x/crypto v0.50.0 golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f golang.org/x/net v0.53.0 golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.27.1-0.20260507230413-b25744aa7730 + maunium.net/go/mautrix v0.27.1-0.20260512144923-7c0986318ff8 ) require ( diff --git a/go.sum b/go.sum index 69eb732..753b96d 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -go.mau.fi/util v0.9.9-0.20260508133822-4207002539ff h1:nH8zuwSw5uu2pal7p9x5BSAvavuiJqRFN558XvcTtKg= -go.mau.fi/util v0.9.9-0.20260508133822-4207002539ff/go.mod h1:jE9FfhbgEgAwxei6lomO9v8zdCIATcquONUu4vjRwSs= +go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25 h1:YPEmc+li7TF6C9AdRTcSLMb6yCHdF27/wNT7kFLIVNg= +go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25/go.mod h1:jE9FfhbgEgAwxei6lomO9v8zdCIATcquONUu4vjRwSs= go.mau.fi/zeroconfig v0.2.0 h1:e/OGEERqVRRKlgaro7E6bh8xXiKFSXB3eNNIud7FUjU= go.mau.fi/zeroconfig v0.2.0/go.mod h1:J0Vn0prHNOm493oZoQ84kq83ZaNCYZnq+noI1b1eN8w= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.27.1-0.20260507230413-b25744aa7730 h1:GcBSD72Ez7D3LoFVprsFFQx3mKcaRh983KpLIiifw68= -maunium.net/go/mautrix v0.27.1-0.20260507230413-b25744aa7730/go.mod h1:2ANjihDB+wv2UAqJapkRekmNXw7khSisccAkE5Jg3P0= +maunium.net/go/mautrix v0.27.1-0.20260512144923-7c0986318ff8 h1:8eHwxv8J9b8ebVwL4H98mlKE4SSAeqhqwD251oSiEkc= +maunium.net/go/mautrix v0.27.1-0.20260512144923-7c0986318ff8/go.mod h1:3sOGhXi3P1V6/NruTA0gujkvTypXVUraWktCuTGyDuM= From 0df937749bfc3dfa5c06d657b29f49c7548ef4d4 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 13 May 2026 15:05:37 +0300 Subject: [PATCH 20/34] dependencies: update mautrix-go --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index db72345..931af45 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.27.1-0.20260512144923-7c0986318ff8 + maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4 ) require ( diff --git a/go.sum b/go.sum index 753b96d..2f02866 100644 --- a/go.sum +++ b/go.sum @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.27.1-0.20260512144923-7c0986318ff8 h1:8eHwxv8J9b8ebVwL4H98mlKE4SSAeqhqwD251oSiEkc= -maunium.net/go/mautrix v0.27.1-0.20260512144923-7c0986318ff8/go.mod h1:3sOGhXi3P1V6/NruTA0gujkvTypXVUraWktCuTGyDuM= +maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4 h1:zNC9eVAhw8FhKpM3AxNAh/iy75UEYX91uJUvqqAYlvo= +maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4/go.mod h1:3sOGhXi3P1V6/NruTA0gujkvTypXVUraWktCuTGyDuM= From 0c852df4cb188fd4603c833d622e0787be6c578c Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 16 May 2026 13:32:45 +0300 Subject: [PATCH 21/34] Bump version to v26.05 --- CHANGELOG.md | 7 ++++++- cmd/mautrix-signal/main.go | 2 +- go.mod | 20 ++++++++++---------- go.sum | 36 ++++++++++++++++++------------------ 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf9682..5ff5d36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ +# v26.05 + +* Updated libsignal to v0.93.2. +* Added support for importing sticker packs from Signal. + # v26.04 -* Updated libsignal to v0.92.1 +* Updated libsignal to v0.92.1. * Added support for admin message deletes from Signal. * Added support for binary service IDs in storage service. * Fixed `private_chat_portal_meta` option not setting DM room names correctly. diff --git a/cmd/mautrix-signal/main.go b/cmd/mautrix-signal/main.go index 6440669..684c1e4 100644 --- a/cmd/mautrix-signal/main.go +++ b/cmd/mautrix-signal/main.go @@ -37,7 +37,7 @@ var m = mxmain.BridgeMain{ Name: "mautrix-signal", URL: "https://github.com/mautrix/signal", Description: "A Matrix-Signal puppeting bridge.", - Version: "26.04", + Version: "26.05", SemCalVer: true, Connector: &connector.SignalConnector{}, diff --git a/go.mod b/go.mod index 931af45..8a4b6ff 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module go.mau.fi/mautrix-signal go 1.25.0 -toolchain go1.26.2 +toolchain go1.26.3 tool go.mau.fi/util/cmd/maubuild @@ -13,15 +13,15 @@ require ( github.com/mattn/go-pointer v0.0.1 github.com/rs/zerolog v1.35.1 github.com/stretchr/testify v1.11.1 - github.com/tidwall/gjson v1.18.0 - go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25 - golang.org/x/crypto v0.50.0 - golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f - golang.org/x/net v0.53.0 + github.com/tidwall/gjson v1.19.0 + go.mau.fi/util v0.9.9 + golang.org/x/crypto v0.51.0 + golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a + golang.org/x/net v0.54.0 golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4 + maunium.net/go/mautrix v0.28.0 ) require ( @@ -43,9 +43,9 @@ require ( github.com/tidwall/sjson v1.2.5 // indirect github.com/yuin/goldmark v1.8.2 // indirect go.mau.fi/zeroconfig v0.2.0 // indirect - golang.org/x/mod v0.35.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/text v0.36.0 // indirect + golang.org/x/mod v0.36.0 // indirect + golang.org/x/sys v0.44.0 // indirect + golang.org/x/text v0.37.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect maunium.net/go/mauflag v1.0.0 // indirect diff --git a/go.sum b/go.sum index 2f02866..b8c83ad 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDq github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= -github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.19.0 h1:xwxm7n691Uf3u5OFjzngavjGTh55KX5q/9w9xHW88JU= +github.com/tidwall/gjson v1.19.0/go.mod h1:V37/opeE/JbLUOfH0QTXiNez2l0RUjYUhpT4szFQAfc= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM= github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= @@ -61,25 +61,25 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25 h1:YPEmc+li7TF6C9AdRTcSLMb6yCHdF27/wNT7kFLIVNg= -go.mau.fi/util v0.9.9-0.20260511124621-9241e81bdf25/go.mod h1:jE9FfhbgEgAwxei6lomO9v8zdCIATcquONUu4vjRwSs= +go.mau.fi/util v0.9.9 h1:ujDeXCo07HBor5oQLyO1tHklupmqVmPgasc53d7q/NE= +go.mau.fi/util v0.9.9/go.mod h1:pqt4Vcrt+5gcH/CgrHZg11qSx+b34o6mknGzOEA6waY= go.mau.fi/zeroconfig v0.2.0 h1:e/OGEERqVRRKlgaro7E6bh8xXiKFSXB3eNNIud7FUjU= go.mau.fi/zeroconfig v0.2.0/go.mod h1:J0Vn0prHNOm493oZoQ84kq83ZaNCYZnq+noI1b1eN8w= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= -golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= -golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a h1:+3jdDGGB8NGb1Zktc737jlt3/A5f6UlwSzmvqUuufxw= +golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw= +golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= +golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4 h1:zNC9eVAhw8FhKpM3AxNAh/iy75UEYX91uJUvqqAYlvo= -maunium.net/go/mautrix v0.27.1-0.20260513120123-5fba7e3afae4/go.mod h1:3sOGhXi3P1V6/NruTA0gujkvTypXVUraWktCuTGyDuM= +maunium.net/go/mautrix v0.28.0 h1:vBakLzf8MAdfED3NzAKiMeKQbc3AQ4EAS03NC+TVMXQ= +maunium.net/go/mautrix v0.28.0/go.mod h1:/a9A7LGaqb9B3nho4tLd28n0EPcCdwpm2dxkxkLLgh0= From dea24acc9536e8f329b29fc4c41f3b2f8c41365e Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 19 May 2026 17:54:09 +0300 Subject: [PATCH 22/34] dependencies: update mautrix-go --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8a4b6ff..13cb3b7 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( golang.org/x/sync v0.20.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.28.0 + maunium.net/go/mautrix v0.28.1-0.20260519145316-34b5f49408a3 ) require ( diff --git a/go.sum b/go.sum index b8c83ad..b981cb6 100644 --- a/go.sum +++ b/go.sum @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.28.0 h1:vBakLzf8MAdfED3NzAKiMeKQbc3AQ4EAS03NC+TVMXQ= -maunium.net/go/mautrix v0.28.0/go.mod h1:/a9A7LGaqb9B3nho4tLd28n0EPcCdwpm2dxkxkLLgh0= +maunium.net/go/mautrix v0.28.1-0.20260519145316-34b5f49408a3 h1:l86igJY8Te5JEBNPL9NSpZaGv6eHsxtCrAabXv8KPJo= +maunium.net/go/mautrix v0.28.1-0.20260519145316-34b5f49408a3/go.mod h1:/a9A7LGaqb9B3nho4tLd28n0EPcCdwpm2dxkxkLLgh0= From 2252280617e5ed87a47bb64484a9945f12a8ece9 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 21 May 2026 22:59:46 +0300 Subject: [PATCH 23/34] signalmeow: update contact discovery mrenclave --- pkg/signalmeow/contactdiscovery.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/signalmeow/contactdiscovery.go b/pkg/signalmeow/contactdiscovery.go index 07d9b49..e0499a7 100644 --- a/pkg/signalmeow/contactdiscovery.go +++ b/pkg/signalmeow/contactdiscovery.go @@ -40,7 +40,7 @@ import ( ) const ProdContactDiscoveryServer = "cdsi.signal.org" -const ProdContactDiscoveryMrenclave = "ee9503070127120074612b6688e593b67e486b1541449f54d71e387484eb40a3" +const ProdContactDiscoveryMrenclave = "15637fa1e54fe655176d3df1a9f94b87c01ed377acaa570682dc5d72c95ef07b" const ContactDiscoveryAuthTTL = 23 * time.Hour const rateLimitCloseCode = websocket.StatusCode(4008) From 69aca6365ff1944c3005c4fa94bde98d460a6975 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 5 Jun 2026 00:07:51 +0300 Subject: [PATCH 24/34] signalmeow: update protobufs --- pkg/signalmeow/protobuf/SignalService.pb.go | 291 +++++++++++------- pkg/signalmeow/protobuf/SignalService.proto | 5 +- pkg/signalmeow/protobuf/StorageService.pb.go | 245 ++++++++++----- pkg/signalmeow/protobuf/StorageService.proto | 15 +- .../protobuf/WebSocketResources.pb.go | 4 +- .../protobuf/WebSocketResources.proto | 2 +- pkg/signalmeow/protobuf/backuppb/Backup.pb.go | 16 +- pkg/signalmeow/protobuf/backuppb/Backup.proto | 2 +- pkg/signalmeow/protobuf/update-protos.sh | 11 +- 9 files changed, 368 insertions(+), 223 deletions(-) diff --git a/pkg/signalmeow/protobuf/SignalService.pb.go b/pkg/signalmeow/protobuf/SignalService.pb.go index c4268dd..1544d05 100644 --- a/pkg/signalmeow/protobuf/SignalService.pb.go +++ b/pkg/signalmeow/protobuf/SignalService.pb.go @@ -314,7 +314,6 @@ func (CallMessage_Opaque_Urgency) EnumDescriptor() ([]byte, []int) { type DataMessage_Flags int32 const ( - DataMessage_END_SESSION DataMessage_Flags = 1 DataMessage_EXPIRATION_TIMER_UPDATE DataMessage_Flags = 2 DataMessage_PROFILE_KEY_UPDATE DataMessage_Flags = 4 DataMessage_FORWARD DataMessage_Flags = 8 @@ -323,13 +322,11 @@ const ( // Enum value maps for DataMessage_Flags. var ( DataMessage_Flags_name = map[int32]string{ - 1: "END_SESSION", 2: "EXPIRATION_TIMER_UPDATE", 4: "PROFILE_KEY_UPDATE", 8: "FORWARD", } DataMessage_Flags_value = map[string]int32{ - "END_SESSION": 1, "EXPIRATION_TIMER_UPDATE": 2, "PROFILE_KEY_UPDATE": 4, "FORWARD": 8, @@ -3085,6 +3082,7 @@ type SyncMessage struct { // *SyncMessage_DeviceNameChange_ // *SyncMessage_AttachmentBackfillRequest_ // *SyncMessage_AttachmentBackfillResponse_ + // *SyncMessage_UsernameChange_ Content isSyncMessage_Content `protobuf_oneof:"content"` // Protobufs don't allow `repeated` fields to be inside of `oneof` so while // the fields below are mutually exclusive with the rest of the values above @@ -3305,6 +3303,15 @@ func (x *SyncMessage) GetAttachmentBackfillResponse() *SyncMessage_AttachmentBac return nil } +func (x *SyncMessage) GetUsernameChange() *SyncMessage_UsernameChange { + if x != nil { + if x, ok := x.Content.(*SyncMessage_UsernameChange_); ok { + return x.UsernameChange + } + } + return nil +} + func (x *SyncMessage) GetRead() []*SyncMessage_Read { if x != nil { return x.Read @@ -3413,6 +3420,10 @@ type SyncMessage_AttachmentBackfillResponse_ struct { AttachmentBackfillResponse *SyncMessage_AttachmentBackfillResponse `protobuf:"bytes,25,opt,name=attachmentBackfillResponse,oneof"` } +type SyncMessage_UsernameChange_ struct { + UsernameChange *SyncMessage_UsernameChange `protobuf:"bytes,26,opt,name=usernameChange,oneof"` +} + func (*SyncMessage_Sent_) isSyncMessage_Content() {} func (*SyncMessage_Contacts_) isSyncMessage_Content() {} @@ -3451,6 +3462,8 @@ func (*SyncMessage_AttachmentBackfillRequest_) isSyncMessage_Content() {} func (*SyncMessage_AttachmentBackfillResponse_) isSyncMessage_Content() {} +func (*SyncMessage_UsernameChange_) isSyncMessage_Content() {} + type AttachmentPointer struct { state protoimpl.MessageState `protogen:"open.v1"` // Types that are valid to be assigned to AttachmentIdentifier: @@ -7925,6 +7938,42 @@ func (*SyncMessage_AttachmentBackfillResponse_Attachments) isSyncMessage_Attachm func (*SyncMessage_AttachmentBackfillResponse_Error_) isSyncMessage_AttachmentBackfillResponse_Data() { } +type SyncMessage_UsernameChange struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SyncMessage_UsernameChange) Reset() { + *x = SyncMessage_UsernameChange{} + mi := &file_SignalService_proto_msgTypes[77] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SyncMessage_UsernameChange) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncMessage_UsernameChange) ProtoMessage() {} + +func (x *SyncMessage_UsernameChange) ProtoReflect() protoreflect.Message { + mi := &file_SignalService_proto_msgTypes[77] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncMessage_UsernameChange.ProtoReflect.Descriptor instead. +func (*SyncMessage_UsernameChange) Descriptor() ([]byte, []int) { + return file_SignalService_proto_rawDescGZIP(), []int{11, 22} +} + type SyncMessage_Sent_UnidentifiedDeliveryStatus struct { state protoimpl.MessageState `protogen:"open.v1"` DestinationServiceId *string `protobuf:"bytes,3,opt,name=destinationServiceId" json:"destinationServiceId,omitempty"` @@ -7937,7 +7986,7 @@ type SyncMessage_Sent_UnidentifiedDeliveryStatus struct { func (x *SyncMessage_Sent_UnidentifiedDeliveryStatus) Reset() { *x = SyncMessage_Sent_UnidentifiedDeliveryStatus{} - mi := &file_SignalService_proto_msgTypes[77] + mi := &file_SignalService_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7949,7 +7998,7 @@ func (x *SyncMessage_Sent_UnidentifiedDeliveryStatus) String() string { func (*SyncMessage_Sent_UnidentifiedDeliveryStatus) ProtoMessage() {} func (x *SyncMessage_Sent_UnidentifiedDeliveryStatus) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[77] + mi := &file_SignalService_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8005,7 +8054,7 @@ type SyncMessage_Sent_StoryMessageRecipient struct { func (x *SyncMessage_Sent_StoryMessageRecipient) Reset() { *x = SyncMessage_Sent_StoryMessageRecipient{} - mi := &file_SignalService_proto_msgTypes[78] + mi := &file_SignalService_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8017,7 +8066,7 @@ func (x *SyncMessage_Sent_StoryMessageRecipient) String() string { func (*SyncMessage_Sent_StoryMessageRecipient) ProtoMessage() {} func (x *SyncMessage_Sent_StoryMessageRecipient) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[78] + mi := &file_SignalService_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8077,7 +8126,7 @@ type SyncMessage_OutgoingPayment_MobileCoin struct { func (x *SyncMessage_OutgoingPayment_MobileCoin) Reset() { *x = SyncMessage_OutgoingPayment_MobileCoin{} - mi := &file_SignalService_proto_msgTypes[79] + mi := &file_SignalService_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8089,7 +8138,7 @@ func (x *SyncMessage_OutgoingPayment_MobileCoin) String() string { func (*SyncMessage_OutgoingPayment_MobileCoin) ProtoMessage() {} func (x *SyncMessage_OutgoingPayment_MobileCoin) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[79] + mi := &file_SignalService_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8171,7 +8220,7 @@ type SyncMessage_DeleteForMe_MessageDeletes struct { func (x *SyncMessage_DeleteForMe_MessageDeletes) Reset() { *x = SyncMessage_DeleteForMe_MessageDeletes{} - mi := &file_SignalService_proto_msgTypes[80] + mi := &file_SignalService_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8183,7 +8232,7 @@ func (x *SyncMessage_DeleteForMe_MessageDeletes) String() string { func (*SyncMessage_DeleteForMe_MessageDeletes) ProtoMessage() {} func (x *SyncMessage_DeleteForMe_MessageDeletes) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[80] + mi := &file_SignalService_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8229,7 +8278,7 @@ type SyncMessage_DeleteForMe_AttachmentDelete struct { func (x *SyncMessage_DeleteForMe_AttachmentDelete) Reset() { *x = SyncMessage_DeleteForMe_AttachmentDelete{} - mi := &file_SignalService_proto_msgTypes[81] + mi := &file_SignalService_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8241,7 +8290,7 @@ func (x *SyncMessage_DeleteForMe_AttachmentDelete) String() string { func (*SyncMessage_DeleteForMe_AttachmentDelete) ProtoMessage() {} func (x *SyncMessage_DeleteForMe_AttachmentDelete) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[81] + mi := &file_SignalService_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8304,7 +8353,7 @@ type SyncMessage_DeleteForMe_ConversationDelete struct { func (x *SyncMessage_DeleteForMe_ConversationDelete) Reset() { *x = SyncMessage_DeleteForMe_ConversationDelete{} - mi := &file_SignalService_proto_msgTypes[82] + mi := &file_SignalService_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8316,7 +8365,7 @@ func (x *SyncMessage_DeleteForMe_ConversationDelete) String() string { func (*SyncMessage_DeleteForMe_ConversationDelete) ProtoMessage() {} func (x *SyncMessage_DeleteForMe_ConversationDelete) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[82] + mi := &file_SignalService_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8369,7 +8418,7 @@ type SyncMessage_DeleteForMe_LocalOnlyConversationDelete struct { func (x *SyncMessage_DeleteForMe_LocalOnlyConversationDelete) Reset() { *x = SyncMessage_DeleteForMe_LocalOnlyConversationDelete{} - mi := &file_SignalService_proto_msgTypes[83] + mi := &file_SignalService_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8381,7 +8430,7 @@ func (x *SyncMessage_DeleteForMe_LocalOnlyConversationDelete) String() string { func (*SyncMessage_DeleteForMe_LocalOnlyConversationDelete) ProtoMessage() {} func (x *SyncMessage_DeleteForMe_LocalOnlyConversationDelete) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[83] + mi := &file_SignalService_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8417,7 +8466,7 @@ type SyncMessage_AttachmentBackfillResponse_AttachmentData struct { func (x *SyncMessage_AttachmentBackfillResponse_AttachmentData) Reset() { *x = SyncMessage_AttachmentBackfillResponse_AttachmentData{} - mi := &file_SignalService_proto_msgTypes[84] + mi := &file_SignalService_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8429,7 +8478,7 @@ func (x *SyncMessage_AttachmentBackfillResponse_AttachmentData) String() string func (*SyncMessage_AttachmentBackfillResponse_AttachmentData) ProtoMessage() {} func (x *SyncMessage_AttachmentBackfillResponse_AttachmentData) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[84] + mi := &file_SignalService_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8498,7 +8547,7 @@ type SyncMessage_AttachmentBackfillResponse_AttachmentDataList struct { func (x *SyncMessage_AttachmentBackfillResponse_AttachmentDataList) Reset() { *x = SyncMessage_AttachmentBackfillResponse_AttachmentDataList{} - mi := &file_SignalService_proto_msgTypes[85] + mi := &file_SignalService_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8510,7 +8559,7 @@ func (x *SyncMessage_AttachmentBackfillResponse_AttachmentDataList) String() str func (*SyncMessage_AttachmentBackfillResponse_AttachmentDataList) ProtoMessage() {} func (x *SyncMessage_AttachmentBackfillResponse_AttachmentDataList) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[85] + mi := &file_SignalService_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8550,7 +8599,7 @@ type ContactDetails_Avatar struct { func (x *ContactDetails_Avatar) Reset() { *x = ContactDetails_Avatar{} - mi := &file_SignalService_proto_msgTypes[86] + mi := &file_SignalService_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8562,7 +8611,7 @@ func (x *ContactDetails_Avatar) String() string { func (*ContactDetails_Avatar) ProtoMessage() {} func (x *ContactDetails_Avatar) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[86] + mi := &file_SignalService_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8602,7 +8651,7 @@ type PaymentAddress_MobileCoin struct { func (x *PaymentAddress_MobileCoin) Reset() { *x = PaymentAddress_MobileCoin{} - mi := &file_SignalService_proto_msgTypes[87] + mi := &file_SignalService_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8614,7 +8663,7 @@ func (x *PaymentAddress_MobileCoin) String() string { func (*PaymentAddress_MobileCoin) ProtoMessage() {} func (x *PaymentAddress_MobileCoin) ProtoReflect() protoreflect.Message { - mi := &file_SignalService_proto_msgTypes[87] + mi := &file_SignalService_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8732,7 +8781,7 @@ const file_SignalService_proto_rawDesc = "" + "\aurgency\x18\x02 \x01(\x0e2).signalservice.CallMessage.Opaque.UrgencyR\aurgency\"0\n" + "\aUrgency\x12\r\n" + "\tDROPPABLE\x10\x00\x12\x16\n" + - "\x12HANDLE_IMMEDIATELY\x10\x01J\x04\b\x04\x10\x05J\x04\b\x06\x10\aJ\x04\b\b\x10\t\"\x8b.\n" + + "\x12HANDLE_IMMEDIATELY\x10\x01J\x04\b\x04\x10\x05J\x04\b\x06\x10\aJ\x04\b\b\x10\t\"\x80.\n" + "\vDataMessage\x12\x12\n" + "\x04body\x18\x01 \x01(\tR\x04body\x12B\n" + "\vattachments\x18\x02 \x03(\v2 .signalservice.AttachmentPointerR\vattachments\x127\n" + @@ -8926,12 +8975,11 @@ const file_SignalService_proto_rawDesc = "" + "\x13targetSentTimestamp\x18\x02 \x01(\x04R\x13targetSentTimestamp\x1au\n" + "\vAdminDelete\x124\n" + "\x15targetAuthorAciBinary\x18\x01 \x01(\fR\x15targetAuthorAciBinary\x120\n" + - "\x13targetSentTimestamp\x18\x02 \x01(\x04R\x13targetSentTimestamp\"Z\n" + - "\x05Flags\x12\x0f\n" + - "\vEND_SESSION\x10\x01\x12\x1b\n" + + "\x13targetSentTimestamp\x18\x02 \x01(\x04R\x13targetSentTimestamp\"O\n" + + "\x05Flags\x12\x1b\n" + "\x17EXPIRATION_TIMER_UPDATE\x10\x02\x12\x16\n" + "\x12PROFILE_KEY_UPDATE\x10\x04\x12\v\n" + - "\aFORWARD\x10\b\"\xbb\x01\n" + + "\aFORWARD\x10\b\"\x04\b\x01\x10\x01\"\xbb\x01\n" + "\x0fProtocolVersion\x12\v\n" + "\aINITIAL\x10\x00\x12\x12\n" + "\x0eMESSAGE_TIMERS\x10\x01\x12\r\n" + @@ -9015,7 +9063,7 @@ const file_SignalService_proto_rawDesc = "" + "\aDEFAULT\x10\x00\x12\f\n" + "\bVERIFIED\x10\x01\x12\x0e\n" + "\n" + - "UNVERIFIED\x10\x02J\x04\b\x01\x10\x02\"\xf1F\n" + + "UNVERIFIED\x10\x02J\x04\b\x01\x10\x02\"\xd8G\n" + "\vSyncMessage\x125\n" + "\x04sent\x18\x01 \x01(\v2\x1f.signalservice.SyncMessage.SentH\x00R\x04sent\x12A\n" + "\bcontacts\x18\x02 \x01(\v2#.signalservice.SyncMessage.ContactsH\x00R\bcontacts\x12>\n" + @@ -9035,7 +9083,8 @@ const file_SignalService_proto_rawDesc = "" + "\vdeleteForMe\x18\x16 \x01(\v2&.signalservice.SyncMessage.DeleteForMeH\x00R\vdeleteForMe\x12Y\n" + "\x10deviceNameChange\x18\x17 \x01(\v2+.signalservice.SyncMessage.DeviceNameChangeH\x00R\x10deviceNameChange\x12t\n" + "\x19attachmentBackfillRequest\x18\x18 \x01(\v24.signalservice.SyncMessage.AttachmentBackfillRequestH\x00R\x19attachmentBackfillRequest\x12w\n" + - "\x1aattachmentBackfillResponse\x18\x19 \x01(\v25.signalservice.SyncMessage.AttachmentBackfillResponseH\x00R\x1aattachmentBackfillResponse\x123\n" + + "\x1aattachmentBackfillResponse\x18\x19 \x01(\v25.signalservice.SyncMessage.AttachmentBackfillResponseH\x00R\x1aattachmentBackfillResponse\x12S\n" + + "\x0eusernameChange\x18\x1a \x01(\v2).signalservice.SyncMessage.UsernameChangeH\x00R\x0eusernameChange\x123\n" + "\x04read\x18\x05 \x03(\v2\x1f.signalservice.SyncMessage.ReadR\x04read\x12c\n" + "\x14stickerPackOperation\x18\n" + " \x03(\v2/.signalservice.SyncMessage.StickerPackOperationR\x14stickerPackOperation\x129\n" + @@ -9254,7 +9303,8 @@ const file_SignalService_proto_rawDesc = "" + "\blongText\x18\x02 \x01(\v2D.signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataR\blongText\"\x1e\n" + "\x05Error\x12\x15\n" + "\x11MESSAGE_NOT_FOUND\x10\x00B\x06\n" + - "\x04dataB\t\n" + + "\x04data\x1a\x10\n" + + "\x0eUsernameChangeB\t\n" + "\acontentJ\x04\b\x03\x10\x04J\x04\b\x11\x10\x12\"\xe7\x04\n" + "\x11AttachmentPointer\x12\x16\n" + "\x05cdnId\x18\x01 \x01(\x06H\x00R\x05cdnId\x12\x18\n" + @@ -9371,7 +9421,7 @@ func file_SignalService_proto_rawDescGZIP() []byte { } var file_SignalService_proto_enumTypes = make([]protoimpl.EnumInfo, 28) -var file_SignalService_proto_msgTypes = make([]protoimpl.MessageInfo, 88) +var file_SignalService_proto_msgTypes = make([]protoimpl.MessageInfo, 89) var file_SignalService_proto_goTypes = []any{ (Envelope_Type)(0), // 0: signalservice.Envelope.Type (CallMessage_Offer_Type)(0), // 1: signalservice.CallMessage.Offer.Type @@ -9478,17 +9528,18 @@ var file_SignalService_proto_goTypes = []any{ (*SyncMessage_DeviceNameChange)(nil), // 102: signalservice.SyncMessage.DeviceNameChange (*SyncMessage_AttachmentBackfillRequest)(nil), // 103: signalservice.SyncMessage.AttachmentBackfillRequest (*SyncMessage_AttachmentBackfillResponse)(nil), // 104: signalservice.SyncMessage.AttachmentBackfillResponse - (*SyncMessage_Sent_UnidentifiedDeliveryStatus)(nil), // 105: signalservice.SyncMessage.Sent.UnidentifiedDeliveryStatus - (*SyncMessage_Sent_StoryMessageRecipient)(nil), // 106: signalservice.SyncMessage.Sent.StoryMessageRecipient - (*SyncMessage_OutgoingPayment_MobileCoin)(nil), // 107: signalservice.SyncMessage.OutgoingPayment.MobileCoin - (*SyncMessage_DeleteForMe_MessageDeletes)(nil), // 108: signalservice.SyncMessage.DeleteForMe.MessageDeletes - (*SyncMessage_DeleteForMe_AttachmentDelete)(nil), // 109: signalservice.SyncMessage.DeleteForMe.AttachmentDelete - (*SyncMessage_DeleteForMe_ConversationDelete)(nil), // 110: signalservice.SyncMessage.DeleteForMe.ConversationDelete - (*SyncMessage_DeleteForMe_LocalOnlyConversationDelete)(nil), // 111: signalservice.SyncMessage.DeleteForMe.LocalOnlyConversationDelete - (*SyncMessage_AttachmentBackfillResponse_AttachmentData)(nil), // 112: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData - (*SyncMessage_AttachmentBackfillResponse_AttachmentDataList)(nil), // 113: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataList - (*ContactDetails_Avatar)(nil), // 114: signalservice.ContactDetails.Avatar - (*PaymentAddress_MobileCoin)(nil), // 115: signalservice.PaymentAddress.MobileCoin + (*SyncMessage_UsernameChange)(nil), // 105: signalservice.SyncMessage.UsernameChange + (*SyncMessage_Sent_UnidentifiedDeliveryStatus)(nil), // 106: signalservice.SyncMessage.Sent.UnidentifiedDeliveryStatus + (*SyncMessage_Sent_StoryMessageRecipient)(nil), // 107: signalservice.SyncMessage.Sent.StoryMessageRecipient + (*SyncMessage_OutgoingPayment_MobileCoin)(nil), // 108: signalservice.SyncMessage.OutgoingPayment.MobileCoin + (*SyncMessage_DeleteForMe_MessageDeletes)(nil), // 109: signalservice.SyncMessage.DeleteForMe.MessageDeletes + (*SyncMessage_DeleteForMe_AttachmentDelete)(nil), // 110: signalservice.SyncMessage.DeleteForMe.AttachmentDelete + (*SyncMessage_DeleteForMe_ConversationDelete)(nil), // 111: signalservice.SyncMessage.DeleteForMe.ConversationDelete + (*SyncMessage_DeleteForMe_LocalOnlyConversationDelete)(nil), // 112: signalservice.SyncMessage.DeleteForMe.LocalOnlyConversationDelete + (*SyncMessage_AttachmentBackfillResponse_AttachmentData)(nil), // 113: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData + (*SyncMessage_AttachmentBackfillResponse_AttachmentDataList)(nil), // 114: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataList + (*ContactDetails_Avatar)(nil), // 115: signalservice.ContactDetails.Avatar + (*PaymentAddress_MobileCoin)(nil), // 116: signalservice.PaymentAddress.MobileCoin } var file_SignalService_proto_depIdxs = []int32{ 0, // 0: signalservice.Envelope.type:type_name -> signalservice.Envelope.Type @@ -9556,78 +9607,79 @@ var file_SignalService_proto_depIdxs = []int32{ 102, // 62: signalservice.SyncMessage.deviceNameChange:type_name -> signalservice.SyncMessage.DeviceNameChange 103, // 63: signalservice.SyncMessage.attachmentBackfillRequest:type_name -> signalservice.SyncMessage.AttachmentBackfillRequest 104, // 64: signalservice.SyncMessage.attachmentBackfillResponse:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse - 87, // 65: signalservice.SyncMessage.read:type_name -> signalservice.SyncMessage.Read - 90, // 66: signalservice.SyncMessage.stickerPackOperation:type_name -> signalservice.SyncMessage.StickerPackOperation - 88, // 67: signalservice.SyncMessage.viewed:type_name -> signalservice.SyncMessage.Viewed - 114, // 68: signalservice.ContactDetails.avatar:type_name -> signalservice.ContactDetails.Avatar - 115, // 69: signalservice.PaymentAddress.mobileCoin:type_name -> signalservice.PaymentAddress.MobileCoin - 31, // 70: signalservice.EditMessage.dataMessage:type_name -> signalservice.DataMessage - 27, // 71: signalservice.BodyRange.style:type_name -> signalservice.BodyRange.Style - 1, // 72: signalservice.CallMessage.Offer.type:type_name -> signalservice.CallMessage.Offer.Type - 2, // 73: signalservice.CallMessage.Hangup.type:type_name -> signalservice.CallMessage.Hangup.Type - 3, // 74: signalservice.CallMessage.Opaque.urgency:type_name -> signalservice.CallMessage.Opaque.Urgency - 72, // 75: signalservice.DataMessage.Payment.notification:type_name -> signalservice.DataMessage.Payment.Notification - 73, // 76: signalservice.DataMessage.Payment.activation:type_name -> signalservice.DataMessage.Payment.Activation - 76, // 77: signalservice.DataMessage.Quote.attachments:type_name -> signalservice.DataMessage.Quote.QuotedAttachment - 47, // 78: signalservice.DataMessage.Quote.bodyRanges:type_name -> signalservice.BodyRange - 7, // 79: signalservice.DataMessage.Quote.type:type_name -> signalservice.DataMessage.Quote.Type - 77, // 80: signalservice.DataMessage.Contact.name:type_name -> signalservice.DataMessage.Contact.Name - 78, // 81: signalservice.DataMessage.Contact.number:type_name -> signalservice.DataMessage.Contact.Phone - 79, // 82: signalservice.DataMessage.Contact.email:type_name -> signalservice.DataMessage.Contact.Email - 80, // 83: signalservice.DataMessage.Contact.address:type_name -> signalservice.DataMessage.Contact.PostalAddress - 81, // 84: signalservice.DataMessage.Contact.avatar:type_name -> signalservice.DataMessage.Contact.Avatar - 40, // 85: signalservice.DataMessage.Sticker.data:type_name -> signalservice.AttachmentPointer - 74, // 86: signalservice.DataMessage.Payment.Amount.mobileCoin:type_name -> signalservice.DataMessage.Payment.Amount.MobileCoin - 75, // 87: signalservice.DataMessage.Payment.Notification.mobileCoin:type_name -> signalservice.DataMessage.Payment.Notification.MobileCoin - 6, // 88: signalservice.DataMessage.Payment.Activation.type:type_name -> signalservice.DataMessage.Payment.Activation.Type - 40, // 89: signalservice.DataMessage.Quote.QuotedAttachment.thumbnail:type_name -> signalservice.AttachmentPointer - 8, // 90: signalservice.DataMessage.Contact.Phone.type:type_name -> signalservice.DataMessage.Contact.Phone.Type - 9, // 91: signalservice.DataMessage.Contact.Email.type:type_name -> signalservice.DataMessage.Contact.Email.Type - 10, // 92: signalservice.DataMessage.Contact.PostalAddress.type:type_name -> signalservice.DataMessage.Contact.PostalAddress.Type - 40, // 93: signalservice.DataMessage.Contact.Avatar.avatar:type_name -> signalservice.AttachmentPointer - 31, // 94: signalservice.SyncMessage.Sent.message:type_name -> signalservice.DataMessage - 105, // 95: signalservice.SyncMessage.Sent.unidentifiedStatus:type_name -> signalservice.SyncMessage.Sent.UnidentifiedDeliveryStatus - 35, // 96: signalservice.SyncMessage.Sent.storyMessage:type_name -> signalservice.StoryMessage - 106, // 97: signalservice.SyncMessage.Sent.storyMessageRecipients:type_name -> signalservice.SyncMessage.Sent.StoryMessageRecipient - 46, // 98: signalservice.SyncMessage.Sent.editMessage:type_name -> signalservice.EditMessage - 40, // 99: signalservice.SyncMessage.Contacts.blob:type_name -> signalservice.AttachmentPointer - 15, // 100: signalservice.SyncMessage.Request.type:type_name -> signalservice.SyncMessage.Request.Type - 16, // 101: signalservice.SyncMessage.StickerPackOperation.type:type_name -> signalservice.SyncMessage.StickerPackOperation.Type - 17, // 102: signalservice.SyncMessage.FetchLatest.type:type_name -> signalservice.SyncMessage.FetchLatest.Type - 18, // 103: signalservice.SyncMessage.MessageRequestResponse.type:type_name -> signalservice.SyncMessage.MessageRequestResponse.Type - 107, // 104: signalservice.SyncMessage.OutgoingPayment.mobileCoin:type_name -> signalservice.SyncMessage.OutgoingPayment.MobileCoin - 19, // 105: signalservice.SyncMessage.CallEvent.type:type_name -> signalservice.SyncMessage.CallEvent.Type - 20, // 106: signalservice.SyncMessage.CallEvent.direction:type_name -> signalservice.SyncMessage.CallEvent.Direction - 21, // 107: signalservice.SyncMessage.CallEvent.event:type_name -> signalservice.SyncMessage.CallEvent.Event - 22, // 108: signalservice.SyncMessage.CallLinkUpdate.type:type_name -> signalservice.SyncMessage.CallLinkUpdate.Type - 23, // 109: signalservice.SyncMessage.CallLogEvent.type:type_name -> signalservice.SyncMessage.CallLogEvent.Type - 108, // 110: signalservice.SyncMessage.DeleteForMe.messageDeletes:type_name -> signalservice.SyncMessage.DeleteForMe.MessageDeletes - 110, // 111: signalservice.SyncMessage.DeleteForMe.conversationDeletes:type_name -> signalservice.SyncMessage.DeleteForMe.ConversationDelete - 111, // 112: signalservice.SyncMessage.DeleteForMe.localOnlyConversationDeletes:type_name -> signalservice.SyncMessage.DeleteForMe.LocalOnlyConversationDelete - 109, // 113: signalservice.SyncMessage.DeleteForMe.attachmentDeletes:type_name -> signalservice.SyncMessage.DeleteForMe.AttachmentDelete - 48, // 114: signalservice.SyncMessage.AttachmentBackfillRequest.targetMessage:type_name -> signalservice.AddressableMessage - 49, // 115: signalservice.SyncMessage.AttachmentBackfillRequest.targetConversation:type_name -> signalservice.ConversationIdentifier - 48, // 116: signalservice.SyncMessage.AttachmentBackfillResponse.targetMessage:type_name -> signalservice.AddressableMessage - 49, // 117: signalservice.SyncMessage.AttachmentBackfillResponse.targetConversation:type_name -> signalservice.ConversationIdentifier - 113, // 118: signalservice.SyncMessage.AttachmentBackfillResponse.attachments:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataList - 24, // 119: signalservice.SyncMessage.AttachmentBackfillResponse.error:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.Error - 49, // 120: signalservice.SyncMessage.DeleteForMe.MessageDeletes.conversation:type_name -> signalservice.ConversationIdentifier - 48, // 121: signalservice.SyncMessage.DeleteForMe.MessageDeletes.messages:type_name -> signalservice.AddressableMessage - 49, // 122: signalservice.SyncMessage.DeleteForMe.AttachmentDelete.conversation:type_name -> signalservice.ConversationIdentifier - 48, // 123: signalservice.SyncMessage.DeleteForMe.AttachmentDelete.targetMessage:type_name -> signalservice.AddressableMessage - 49, // 124: signalservice.SyncMessage.DeleteForMe.ConversationDelete.conversation:type_name -> signalservice.ConversationIdentifier - 48, // 125: signalservice.SyncMessage.DeleteForMe.ConversationDelete.mostRecentMessages:type_name -> signalservice.AddressableMessage - 48, // 126: signalservice.SyncMessage.DeleteForMe.ConversationDelete.mostRecentNonExpiringMessages:type_name -> signalservice.AddressableMessage - 49, // 127: signalservice.SyncMessage.DeleteForMe.LocalOnlyConversationDelete.conversation:type_name -> signalservice.ConversationIdentifier - 40, // 128: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData.attachment:type_name -> signalservice.AttachmentPointer - 25, // 129: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData.status:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData.Status - 112, // 130: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataList.attachments:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData - 112, // 131: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataList.longText:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData - 132, // [132:132] is the sub-list for method output_type - 132, // [132:132] is the sub-list for method input_type - 132, // [132:132] is the sub-list for extension type_name - 132, // [132:132] is the sub-list for extension extendee - 0, // [0:132] is the sub-list for field type_name + 105, // 65: signalservice.SyncMessage.usernameChange:type_name -> signalservice.SyncMessage.UsernameChange + 87, // 66: signalservice.SyncMessage.read:type_name -> signalservice.SyncMessage.Read + 90, // 67: signalservice.SyncMessage.stickerPackOperation:type_name -> signalservice.SyncMessage.StickerPackOperation + 88, // 68: signalservice.SyncMessage.viewed:type_name -> signalservice.SyncMessage.Viewed + 115, // 69: signalservice.ContactDetails.avatar:type_name -> signalservice.ContactDetails.Avatar + 116, // 70: signalservice.PaymentAddress.mobileCoin:type_name -> signalservice.PaymentAddress.MobileCoin + 31, // 71: signalservice.EditMessage.dataMessage:type_name -> signalservice.DataMessage + 27, // 72: signalservice.BodyRange.style:type_name -> signalservice.BodyRange.Style + 1, // 73: signalservice.CallMessage.Offer.type:type_name -> signalservice.CallMessage.Offer.Type + 2, // 74: signalservice.CallMessage.Hangup.type:type_name -> signalservice.CallMessage.Hangup.Type + 3, // 75: signalservice.CallMessage.Opaque.urgency:type_name -> signalservice.CallMessage.Opaque.Urgency + 72, // 76: signalservice.DataMessage.Payment.notification:type_name -> signalservice.DataMessage.Payment.Notification + 73, // 77: signalservice.DataMessage.Payment.activation:type_name -> signalservice.DataMessage.Payment.Activation + 76, // 78: signalservice.DataMessage.Quote.attachments:type_name -> signalservice.DataMessage.Quote.QuotedAttachment + 47, // 79: signalservice.DataMessage.Quote.bodyRanges:type_name -> signalservice.BodyRange + 7, // 80: signalservice.DataMessage.Quote.type:type_name -> signalservice.DataMessage.Quote.Type + 77, // 81: signalservice.DataMessage.Contact.name:type_name -> signalservice.DataMessage.Contact.Name + 78, // 82: signalservice.DataMessage.Contact.number:type_name -> signalservice.DataMessage.Contact.Phone + 79, // 83: signalservice.DataMessage.Contact.email:type_name -> signalservice.DataMessage.Contact.Email + 80, // 84: signalservice.DataMessage.Contact.address:type_name -> signalservice.DataMessage.Contact.PostalAddress + 81, // 85: signalservice.DataMessage.Contact.avatar:type_name -> signalservice.DataMessage.Contact.Avatar + 40, // 86: signalservice.DataMessage.Sticker.data:type_name -> signalservice.AttachmentPointer + 74, // 87: signalservice.DataMessage.Payment.Amount.mobileCoin:type_name -> signalservice.DataMessage.Payment.Amount.MobileCoin + 75, // 88: signalservice.DataMessage.Payment.Notification.mobileCoin:type_name -> signalservice.DataMessage.Payment.Notification.MobileCoin + 6, // 89: signalservice.DataMessage.Payment.Activation.type:type_name -> signalservice.DataMessage.Payment.Activation.Type + 40, // 90: signalservice.DataMessage.Quote.QuotedAttachment.thumbnail:type_name -> signalservice.AttachmentPointer + 8, // 91: signalservice.DataMessage.Contact.Phone.type:type_name -> signalservice.DataMessage.Contact.Phone.Type + 9, // 92: signalservice.DataMessage.Contact.Email.type:type_name -> signalservice.DataMessage.Contact.Email.Type + 10, // 93: signalservice.DataMessage.Contact.PostalAddress.type:type_name -> signalservice.DataMessage.Contact.PostalAddress.Type + 40, // 94: signalservice.DataMessage.Contact.Avatar.avatar:type_name -> signalservice.AttachmentPointer + 31, // 95: signalservice.SyncMessage.Sent.message:type_name -> signalservice.DataMessage + 106, // 96: signalservice.SyncMessage.Sent.unidentifiedStatus:type_name -> signalservice.SyncMessage.Sent.UnidentifiedDeliveryStatus + 35, // 97: signalservice.SyncMessage.Sent.storyMessage:type_name -> signalservice.StoryMessage + 107, // 98: signalservice.SyncMessage.Sent.storyMessageRecipients:type_name -> signalservice.SyncMessage.Sent.StoryMessageRecipient + 46, // 99: signalservice.SyncMessage.Sent.editMessage:type_name -> signalservice.EditMessage + 40, // 100: signalservice.SyncMessage.Contacts.blob:type_name -> signalservice.AttachmentPointer + 15, // 101: signalservice.SyncMessage.Request.type:type_name -> signalservice.SyncMessage.Request.Type + 16, // 102: signalservice.SyncMessage.StickerPackOperation.type:type_name -> signalservice.SyncMessage.StickerPackOperation.Type + 17, // 103: signalservice.SyncMessage.FetchLatest.type:type_name -> signalservice.SyncMessage.FetchLatest.Type + 18, // 104: signalservice.SyncMessage.MessageRequestResponse.type:type_name -> signalservice.SyncMessage.MessageRequestResponse.Type + 108, // 105: signalservice.SyncMessage.OutgoingPayment.mobileCoin:type_name -> signalservice.SyncMessage.OutgoingPayment.MobileCoin + 19, // 106: signalservice.SyncMessage.CallEvent.type:type_name -> signalservice.SyncMessage.CallEvent.Type + 20, // 107: signalservice.SyncMessage.CallEvent.direction:type_name -> signalservice.SyncMessage.CallEvent.Direction + 21, // 108: signalservice.SyncMessage.CallEvent.event:type_name -> signalservice.SyncMessage.CallEvent.Event + 22, // 109: signalservice.SyncMessage.CallLinkUpdate.type:type_name -> signalservice.SyncMessage.CallLinkUpdate.Type + 23, // 110: signalservice.SyncMessage.CallLogEvent.type:type_name -> signalservice.SyncMessage.CallLogEvent.Type + 109, // 111: signalservice.SyncMessage.DeleteForMe.messageDeletes:type_name -> signalservice.SyncMessage.DeleteForMe.MessageDeletes + 111, // 112: signalservice.SyncMessage.DeleteForMe.conversationDeletes:type_name -> signalservice.SyncMessage.DeleteForMe.ConversationDelete + 112, // 113: signalservice.SyncMessage.DeleteForMe.localOnlyConversationDeletes:type_name -> signalservice.SyncMessage.DeleteForMe.LocalOnlyConversationDelete + 110, // 114: signalservice.SyncMessage.DeleteForMe.attachmentDeletes:type_name -> signalservice.SyncMessage.DeleteForMe.AttachmentDelete + 48, // 115: signalservice.SyncMessage.AttachmentBackfillRequest.targetMessage:type_name -> signalservice.AddressableMessage + 49, // 116: signalservice.SyncMessage.AttachmentBackfillRequest.targetConversation:type_name -> signalservice.ConversationIdentifier + 48, // 117: signalservice.SyncMessage.AttachmentBackfillResponse.targetMessage:type_name -> signalservice.AddressableMessage + 49, // 118: signalservice.SyncMessage.AttachmentBackfillResponse.targetConversation:type_name -> signalservice.ConversationIdentifier + 114, // 119: signalservice.SyncMessage.AttachmentBackfillResponse.attachments:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataList + 24, // 120: signalservice.SyncMessage.AttachmentBackfillResponse.error:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.Error + 49, // 121: signalservice.SyncMessage.DeleteForMe.MessageDeletes.conversation:type_name -> signalservice.ConversationIdentifier + 48, // 122: signalservice.SyncMessage.DeleteForMe.MessageDeletes.messages:type_name -> signalservice.AddressableMessage + 49, // 123: signalservice.SyncMessage.DeleteForMe.AttachmentDelete.conversation:type_name -> signalservice.ConversationIdentifier + 48, // 124: signalservice.SyncMessage.DeleteForMe.AttachmentDelete.targetMessage:type_name -> signalservice.AddressableMessage + 49, // 125: signalservice.SyncMessage.DeleteForMe.ConversationDelete.conversation:type_name -> signalservice.ConversationIdentifier + 48, // 126: signalservice.SyncMessage.DeleteForMe.ConversationDelete.mostRecentMessages:type_name -> signalservice.AddressableMessage + 48, // 127: signalservice.SyncMessage.DeleteForMe.ConversationDelete.mostRecentNonExpiringMessages:type_name -> signalservice.AddressableMessage + 49, // 128: signalservice.SyncMessage.DeleteForMe.LocalOnlyConversationDelete.conversation:type_name -> signalservice.ConversationIdentifier + 40, // 129: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData.attachment:type_name -> signalservice.AttachmentPointer + 25, // 130: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData.status:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData.Status + 113, // 131: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataList.attachments:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData + 113, // 132: signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentDataList.longText:type_name -> signalservice.SyncMessage.AttachmentBackfillResponse.AttachmentData + 133, // [133:133] is the sub-list for method output_type + 133, // [133:133] is the sub-list for method input_type + 133, // [133:133] is the sub-list for extension type_name + 133, // [133:133] is the sub-list for extension extendee + 0, // [0:133] is the sub-list for field type_name } func init() { file_SignalService_proto_init() } @@ -9674,6 +9726,7 @@ func file_SignalService_proto_init() { (*SyncMessage_DeviceNameChange_)(nil), (*SyncMessage_AttachmentBackfillRequest_)(nil), (*SyncMessage_AttachmentBackfillResponse_)(nil), + (*SyncMessage_UsernameChange_)(nil), } file_SignalService_proto_msgTypes[12].OneofWrappers = []any{ (*AttachmentPointer_CdnId)(nil), @@ -9719,7 +9772,7 @@ func file_SignalService_proto_init() { (*SyncMessage_AttachmentBackfillResponse_Attachments)(nil), (*SyncMessage_AttachmentBackfillResponse_Error_)(nil), } - file_SignalService_proto_msgTypes[84].OneofWrappers = []any{ + file_SignalService_proto_msgTypes[85].OneofWrappers = []any{ (*SyncMessage_AttachmentBackfillResponse_AttachmentData_Attachment)(nil), (*SyncMessage_AttachmentBackfillResponse_AttachmentData_Status_)(nil), } @@ -9729,7 +9782,7 @@ func file_SignalService_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_SignalService_proto_rawDesc), len(file_SignalService_proto_rawDesc)), NumEnums: 28, - NumMessages: 88, + NumMessages: 89, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/signalmeow/protobuf/SignalService.proto b/pkg/signalmeow/protobuf/SignalService.proto index 0089a16..58d0b0f 100644 --- a/pkg/signalmeow/protobuf/SignalService.proto +++ b/pkg/signalmeow/protobuf/SignalService.proto @@ -187,7 +187,7 @@ message CallMessage { message DataMessage { enum Flags { - END_SESSION = 1; + reserved /*END_SESSION*/ 1; EXPIRATION_TIMER_UPDATE = 2; PROFILE_KEY_UPDATE = 4; FORWARD = 8; @@ -850,6 +850,8 @@ message SyncMessage { } } + message UsernameChange {} + oneof content { Sent sent = 1; Contacts contacts = 2; @@ -870,6 +872,7 @@ message SyncMessage { DeviceNameChange deviceNameChange = 23; AttachmentBackfillRequest attachmentBackfillRequest = 24; AttachmentBackfillResponse attachmentBackfillResponse = 25; + UsernameChange usernameChange = 26; } reserved /*groups*/ 3; diff --git a/pkg/signalmeow/protobuf/StorageService.pb.go b/pkg/signalmeow/protobuf/StorageService.pb.go index bbe88ef..0d650af 100644 --- a/pkg/signalmeow/protobuf/StorageService.pb.go +++ b/pkg/signalmeow/protobuf/StorageService.pb.go @@ -1566,49 +1566,52 @@ func (x *Payments) GetEntropy() []byte { } type AccountRecord struct { - state protoimpl.MessageState `protogen:"open.v1"` - ProfileKey []byte `protobuf:"bytes,1,opt,name=profileKey,proto3" json:"profileKey,omitempty"` - GivenName string `protobuf:"bytes,2,opt,name=givenName,proto3" json:"givenName,omitempty"` - FamilyName string `protobuf:"bytes,3,opt,name=familyName,proto3" json:"familyName,omitempty"` - AvatarUrlPath string `protobuf:"bytes,4,opt,name=avatarUrlPath,proto3" json:"avatarUrlPath,omitempty"` - NoteToSelfArchived bool `protobuf:"varint,5,opt,name=noteToSelfArchived,proto3" json:"noteToSelfArchived,omitempty"` - ReadReceipts bool `protobuf:"varint,6,opt,name=readReceipts,proto3" json:"readReceipts,omitempty"` - SealedSenderIndicators bool `protobuf:"varint,7,opt,name=sealedSenderIndicators,proto3" json:"sealedSenderIndicators,omitempty"` - TypingIndicators bool `protobuf:"varint,8,opt,name=typingIndicators,proto3" json:"typingIndicators,omitempty"` - NoteToSelfMarkedUnread bool `protobuf:"varint,10,opt,name=noteToSelfMarkedUnread,proto3" json:"noteToSelfMarkedUnread,omitempty"` - LinkPreviews bool `protobuf:"varint,11,opt,name=linkPreviews,proto3" json:"linkPreviews,omitempty"` - PhoneNumberSharingMode AccountRecord_PhoneNumberSharingMode `protobuf:"varint,12,opt,name=phoneNumberSharingMode,proto3,enum=signalservice.AccountRecord_PhoneNumberSharingMode" json:"phoneNumberSharingMode,omitempty"` - UnlistedPhoneNumber bool `protobuf:"varint,13,opt,name=unlistedPhoneNumber,proto3" json:"unlistedPhoneNumber,omitempty"` - PinnedConversations []*AccountRecord_PinnedConversation `protobuf:"bytes,14,rep,name=pinnedConversations,proto3" json:"pinnedConversations,omitempty"` - PreferContactAvatars bool `protobuf:"varint,15,opt,name=preferContactAvatars,proto3" json:"preferContactAvatars,omitempty"` - Payments *Payments `protobuf:"bytes,16,opt,name=payments,proto3" json:"payments,omitempty"` - UniversalExpireTimer uint32 `protobuf:"varint,17,opt,name=universalExpireTimer,proto3" json:"universalExpireTimer,omitempty"` - PrimarySendsSms bool `protobuf:"varint,18,opt,name=primarySendsSms,proto3" json:"primarySendsSms,omitempty"` - PreferredReactionEmoji []string `protobuf:"bytes,20,rep,name=preferredReactionEmoji,proto3" json:"preferredReactionEmoji,omitempty"` - SubscriberId []byte `protobuf:"bytes,21,opt,name=subscriberId,proto3" json:"subscriberId,omitempty"` - SubscriberCurrencyCode string `protobuf:"bytes,22,opt,name=subscriberCurrencyCode,proto3" json:"subscriberCurrencyCode,omitempty"` - DisplayBadgesOnProfile bool `protobuf:"varint,23,opt,name=displayBadgesOnProfile,proto3" json:"displayBadgesOnProfile,omitempty"` - SubscriptionManuallyCancelled bool `protobuf:"varint,24,opt,name=subscriptionManuallyCancelled,proto3" json:"subscriptionManuallyCancelled,omitempty"` - KeepMutedChatsArchived bool `protobuf:"varint,25,opt,name=keepMutedChatsArchived,proto3" json:"keepMutedChatsArchived,omitempty"` - HasSetMyStoriesPrivacy bool `protobuf:"varint,26,opt,name=hasSetMyStoriesPrivacy,proto3" json:"hasSetMyStoriesPrivacy,omitempty"` - HasViewedOnboardingStory bool `protobuf:"varint,27,opt,name=hasViewedOnboardingStory,proto3" json:"hasViewedOnboardingStory,omitempty"` - StoriesDisabled bool `protobuf:"varint,29,opt,name=storiesDisabled,proto3" json:"storiesDisabled,omitempty"` - StoryViewReceiptsEnabled OptionalBool `protobuf:"varint,30,opt,name=storyViewReceiptsEnabled,proto3,enum=signalservice.OptionalBool" json:"storyViewReceiptsEnabled,omitempty"` - HasSeenGroupStoryEducationSheet bool `protobuf:"varint,32,opt,name=hasSeenGroupStoryEducationSheet,proto3" json:"hasSeenGroupStoryEducationSheet,omitempty"` - Username string `protobuf:"bytes,33,opt,name=username,proto3" json:"username,omitempty"` - HasCompletedUsernameOnboarding bool `protobuf:"varint,34,opt,name=hasCompletedUsernameOnboarding,proto3" json:"hasCompletedUsernameOnboarding,omitempty"` - UsernameLink *AccountRecord_UsernameLink `protobuf:"bytes,35,opt,name=usernameLink,proto3" json:"usernameLink,omitempty"` - HasBackup *bool `protobuf:"varint,39,opt,name=hasBackup,proto3,oneof" json:"hasBackup,omitempty"` // Set to true after backups are enabled and one is uploaded. - BackupTier *uint64 `protobuf:"varint,40,opt,name=backupTier,proto3,oneof" json:"backupTier,omitempty"` // See zkgroup for integer particular values. Unset if backups are not enabled. - BackupSubscriberData *AccountRecord_IAPSubscriberData `protobuf:"bytes,41,opt,name=backupSubscriberData,proto3" json:"backupSubscriberData,omitempty"` - AvatarColor *AvatarColor `protobuf:"varint,42,opt,name=avatarColor,proto3,enum=signalservice.AvatarColor,oneof" json:"avatarColor,omitempty"` - BackupTierHistory *AccountRecord_BackupTierHistory `protobuf:"bytes,43,opt,name=backupTierHistory,proto3" json:"backupTierHistory,omitempty"` - NotificationProfileManualOverride *AccountRecord_NotificationProfileManualOverride `protobuf:"bytes,44,opt,name=notificationProfileManualOverride,proto3" json:"notificationProfileManualOverride,omitempty"` - NotificationProfileSyncDisabled bool `protobuf:"varint,45,opt,name=notificationProfileSyncDisabled,proto3" json:"notificationProfileSyncDisabled,omitempty"` - AutomaticKeyVerificationDisabled bool `protobuf:"varint,46,opt,name=automaticKeyVerificationDisabled,proto3" json:"automaticKeyVerificationDisabled,omitempty"` - HasSeenAdminDeleteEducationDialog bool `protobuf:"varint,47,opt,name=hasSeenAdminDeleteEducationDialog,proto3" json:"hasSeenAdminDeleteEducationDialog,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ProfileKey []byte `protobuf:"bytes,1,opt,name=profileKey,proto3" json:"profileKey,omitempty"` + GivenName string `protobuf:"bytes,2,opt,name=givenName,proto3" json:"givenName,omitempty"` + FamilyName string `protobuf:"bytes,3,opt,name=familyName,proto3" json:"familyName,omitempty"` + AvatarUrlPath string `protobuf:"bytes,4,opt,name=avatarUrlPath,proto3" json:"avatarUrlPath,omitempty"` + NoteToSelfArchived bool `protobuf:"varint,5,opt,name=noteToSelfArchived,proto3" json:"noteToSelfArchived,omitempty"` + ReadReceipts bool `protobuf:"varint,6,opt,name=readReceipts,proto3" json:"readReceipts,omitempty"` + SealedSenderIndicators bool `protobuf:"varint,7,opt,name=sealedSenderIndicators,proto3" json:"sealedSenderIndicators,omitempty"` + TypingIndicators bool `protobuf:"varint,8,opt,name=typingIndicators,proto3" json:"typingIndicators,omitempty"` + NoteToSelfMarkedUnread bool `protobuf:"varint,10,opt,name=noteToSelfMarkedUnread,proto3" json:"noteToSelfMarkedUnread,omitempty"` + LinkPreviews bool `protobuf:"varint,11,opt,name=linkPreviews,proto3" json:"linkPreviews,omitempty"` + PhoneNumberSharingMode AccountRecord_PhoneNumberSharingMode `protobuf:"varint,12,opt,name=phoneNumberSharingMode,proto3,enum=signalservice.AccountRecord_PhoneNumberSharingMode" json:"phoneNumberSharingMode,omitempty"` + UnlistedPhoneNumber bool `protobuf:"varint,13,opt,name=unlistedPhoneNumber,proto3" json:"unlistedPhoneNumber,omitempty"` + PinnedConversations []*AccountRecord_PinnedConversation `protobuf:"bytes,14,rep,name=pinnedConversations,proto3" json:"pinnedConversations,omitempty"` + PreferContactAvatars bool `protobuf:"varint,15,opt,name=preferContactAvatars,proto3" json:"preferContactAvatars,omitempty"` + Payments *Payments `protobuf:"bytes,16,opt,name=payments,proto3" json:"payments,omitempty"` + UniversalExpireTimer uint32 `protobuf:"varint,17,opt,name=universalExpireTimer,proto3" json:"universalExpireTimer,omitempty"` + PrimarySendsSms bool `protobuf:"varint,18,opt,name=primarySendsSms,proto3" json:"primarySendsSms,omitempty"` + PreferredReactionEmoji []string `protobuf:"bytes,20,rep,name=preferredReactionEmoji,proto3" json:"preferredReactionEmoji,omitempty"` + SubscriberId []byte `protobuf:"bytes,21,opt,name=subscriberId,proto3" json:"subscriberId,omitempty"` + SubscriberCurrencyCode string `protobuf:"bytes,22,opt,name=subscriberCurrencyCode,proto3" json:"subscriberCurrencyCode,omitempty"` + DisplayBadgesOnProfile bool `protobuf:"varint,23,opt,name=displayBadgesOnProfile,proto3" json:"displayBadgesOnProfile,omitempty"` + SubscriptionManuallyCancelled bool `protobuf:"varint,24,opt,name=subscriptionManuallyCancelled,proto3" json:"subscriptionManuallyCancelled,omitempty"` + KeepMutedChatsArchived bool `protobuf:"varint,25,opt,name=keepMutedChatsArchived,proto3" json:"keepMutedChatsArchived,omitempty"` + HasSetMyStoriesPrivacy bool `protobuf:"varint,26,opt,name=hasSetMyStoriesPrivacy,proto3" json:"hasSetMyStoriesPrivacy,omitempty"` + HasViewedOnboardingStory bool `protobuf:"varint,27,opt,name=hasViewedOnboardingStory,proto3" json:"hasViewedOnboardingStory,omitempty"` + StoriesDisabled bool `protobuf:"varint,29,opt,name=storiesDisabled,proto3" json:"storiesDisabled,omitempty"` + StoryViewReceiptsEnabled OptionalBool `protobuf:"varint,30,opt,name=storyViewReceiptsEnabled,proto3,enum=signalservice.OptionalBool" json:"storyViewReceiptsEnabled,omitempty"` + HasSeenGroupStoryEducationSheet bool `protobuf:"varint,32,opt,name=hasSeenGroupStoryEducationSheet,proto3" json:"hasSeenGroupStoryEducationSheet,omitempty"` + Username string `protobuf:"bytes,33,opt,name=username,proto3" json:"username,omitempty"` + HasCompletedUsernameOnboarding bool `protobuf:"varint,34,opt,name=hasCompletedUsernameOnboarding,proto3" json:"hasCompletedUsernameOnboarding,omitempty"` + UsernameLink *AccountRecord_UsernameLink `protobuf:"bytes,35,opt,name=usernameLink,proto3" json:"usernameLink,omitempty"` + BackupTier *uint64 `protobuf:"varint,40,opt,name=backupTier,proto3,oneof" json:"backupTier,omitempty"` // See zkgroup for integer particular values. Unset if backups are not enabled. + BackupSubscriberData *AccountRecord_IAPSubscriberData `protobuf:"bytes,41,opt,name=backupSubscriberData,proto3" json:"backupSubscriberData,omitempty"` + AvatarColor *AvatarColor `protobuf:"varint,42,opt,name=avatarColor,proto3,enum=signalservice.AvatarColor,oneof" json:"avatarColor,omitempty"` + BackupTierHistory *AccountRecord_BackupTierHistory `protobuf:"bytes,43,opt,name=backupTierHistory,proto3" json:"backupTierHistory,omitempty"` + NotificationProfileManualOverride *AccountRecord_NotificationProfileManualOverride `protobuf:"bytes,44,opt,name=notificationProfileManualOverride,proto3" json:"notificationProfileManualOverride,omitempty"` + NotificationProfileSyncDisabled bool `protobuf:"varint,45,opt,name=notificationProfileSyncDisabled,proto3" json:"notificationProfileSyncDisabled,omitempty"` + AutomaticKeyVerificationDisabled bool `protobuf:"varint,46,opt,name=automaticKeyVerificationDisabled,proto3" json:"automaticKeyVerificationDisabled,omitempty"` + HasSeenAdminDeleteEducationDialog bool `protobuf:"varint,47,opt,name=hasSeenAdminDeleteEducationDialog,proto3" json:"hasSeenAdminDeleteEducationDialog,omitempty"` + ReleaseNotesChatArchived *bool `protobuf:"varint,48,opt,name=releaseNotesChatArchived,proto3,oneof" json:"releaseNotesChatArchived,omitempty"` + ReleaseNotesChatMutedUntilTimestamp *uint64 `protobuf:"varint,49,opt,name=releaseNotesChatMutedUntilTimestamp,proto3,oneof" json:"releaseNotesChatMutedUntilTimestamp,omitempty"` + ReleaseNotesChatBlocked *bool `protobuf:"varint,50,opt,name=releaseNotesChatBlocked,proto3,oneof" json:"releaseNotesChatBlocked,omitempty"` + ReleaseNotesChatMarkedUnread *bool `protobuf:"varint,51,opt,name=releaseNotesChatMarkedUnread,proto3,oneof" json:"releaseNotesChatMarkedUnread,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AccountRecord) Reset() { @@ -1858,13 +1861,6 @@ func (x *AccountRecord) GetUsernameLink() *AccountRecord_UsernameLink { return nil } -func (x *AccountRecord) GetHasBackup() bool { - if x != nil && x.HasBackup != nil { - return *x.HasBackup - } - return false -} - func (x *AccountRecord) GetBackupTier() uint64 { if x != nil && x.BackupTier != nil { return *x.BackupTier @@ -1921,6 +1917,34 @@ func (x *AccountRecord) GetHasSeenAdminDeleteEducationDialog() bool { return false } +func (x *AccountRecord) GetReleaseNotesChatArchived() bool { + if x != nil && x.ReleaseNotesChatArchived != nil { + return *x.ReleaseNotesChatArchived + } + return false +} + +func (x *AccountRecord) GetReleaseNotesChatMutedUntilTimestamp() uint64 { + if x != nil && x.ReleaseNotesChatMutedUntilTimestamp != nil { + return *x.ReleaseNotesChatMutedUntilTimestamp + } + return 0 +} + +func (x *AccountRecord) GetReleaseNotesChatBlocked() bool { + if x != nil && x.ReleaseNotesChatBlocked != nil { + return *x.ReleaseNotesChatBlocked + } + return false +} + +func (x *AccountRecord) GetReleaseNotesChatMarkedUnread() bool { + if x != nil && x.ReleaseNotesChatMarkedUnread != nil { + return *x.ReleaseNotesChatMarkedUnread + } + return false +} + type StoryDistributionListRecord struct { state protoimpl.MessageState `protogen:"open.v1"` Identifier []byte `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"` @@ -2546,6 +2570,7 @@ type AccountRecord_PinnedConversation struct { // *AccountRecord_PinnedConversation_Contact_ // *AccountRecord_PinnedConversation_LegacyGroupId // *AccountRecord_PinnedConversation_GroupMasterKey + // *AccountRecord_PinnedConversation_ReleaseNotes_ Identifier isAccountRecord_PinnedConversation_Identifier `protobuf_oneof:"identifier"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -2615,6 +2640,15 @@ func (x *AccountRecord_PinnedConversation) GetGroupMasterKey() []byte { return nil } +func (x *AccountRecord_PinnedConversation) GetReleaseNotes() *AccountRecord_PinnedConversation_ReleaseNotes { + if x != nil { + if x, ok := x.Identifier.(*AccountRecord_PinnedConversation_ReleaseNotes_); ok { + return x.ReleaseNotes + } + } + return nil +} + type isAccountRecord_PinnedConversation_Identifier interface { isAccountRecord_PinnedConversation_Identifier() } @@ -2631,6 +2665,10 @@ type AccountRecord_PinnedConversation_GroupMasterKey struct { GroupMasterKey []byte `protobuf:"bytes,4,opt,name=groupMasterKey,proto3,oneof"` } +type AccountRecord_PinnedConversation_ReleaseNotes_ struct { + ReleaseNotes *AccountRecord_PinnedConversation_ReleaseNotes `protobuf:"bytes,5,opt,name=releaseNotes,proto3,oneof"` +} + func (*AccountRecord_PinnedConversation_Contact_) isAccountRecord_PinnedConversation_Identifier() {} func (*AccountRecord_PinnedConversation_LegacyGroupId) isAccountRecord_PinnedConversation_Identifier() { @@ -2639,6 +2677,9 @@ func (*AccountRecord_PinnedConversation_LegacyGroupId) isAccountRecord_PinnedCon func (*AccountRecord_PinnedConversation_GroupMasterKey) isAccountRecord_PinnedConversation_Identifier() { } +func (*AccountRecord_PinnedConversation_ReleaseNotes_) isAccountRecord_PinnedConversation_Identifier() { +} + type AccountRecord_UsernameLink struct { state protoimpl.MessageState `protogen:"open.v1"` Entropy []byte `protobuf:"bytes,1,opt,name=entropy,proto3" json:"entropy,omitempty"` // 32 bytes of entropy used for encryption @@ -2990,6 +3031,42 @@ func (x *AccountRecord_PinnedConversation_Contact) GetServiceIdBinary() []byte { return nil } +type AccountRecord_PinnedConversation_ReleaseNotes struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AccountRecord_PinnedConversation_ReleaseNotes) Reset() { + *x = AccountRecord_PinnedConversation_ReleaseNotes{} + mi := &file_StorageService_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AccountRecord_PinnedConversation_ReleaseNotes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccountRecord_PinnedConversation_ReleaseNotes) ProtoMessage() {} + +func (x *AccountRecord_PinnedConversation_ReleaseNotes) ProtoReflect() protoreflect.Message { + mi := &file_StorageService_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AccountRecord_PinnedConversation_ReleaseNotes.ProtoReflect.Descriptor instead. +func (*AccountRecord_PinnedConversation_ReleaseNotes) Descriptor() ([]byte, []int) { + return file_StorageService_proto_rawDescGZIP(), []int{11, 0, 1} +} + type AccountRecord_NotificationProfileManualOverride_ManuallyEnabled struct { state protoimpl.MessageState `protogen:"open.v1"` Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` @@ -3001,7 +3078,7 @@ type AccountRecord_NotificationProfileManualOverride_ManuallyEnabled struct { func (x *AccountRecord_NotificationProfileManualOverride_ManuallyEnabled) Reset() { *x = AccountRecord_NotificationProfileManualOverride_ManuallyEnabled{} - mi := &file_StorageService_proto_msgTypes[25] + mi := &file_StorageService_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3013,7 +3090,7 @@ func (x *AccountRecord_NotificationProfileManualOverride_ManuallyEnabled) String func (*AccountRecord_NotificationProfileManualOverride_ManuallyEnabled) ProtoMessage() {} func (x *AccountRecord_NotificationProfileManualOverride_ManuallyEnabled) ProtoReflect() protoreflect.Message { - mi := &file_StorageService_proto_msgTypes[25] + mi := &file_StorageService_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3054,7 +3131,7 @@ type Recipient_Contact struct { func (x *Recipient_Contact) Reset() { *x = Recipient_Contact{} - mi := &file_StorageService_proto_msgTypes[26] + mi := &file_StorageService_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3066,7 +3143,7 @@ func (x *Recipient_Contact) String() string { func (*Recipient_Contact) ProtoMessage() {} func (x *Recipient_Contact) ProtoReflect() protoreflect.Message { - mi := &file_StorageService_proto_msgTypes[26] + mi := &file_StorageService_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3225,7 +3302,7 @@ const file_StorageService_proto_rawDesc = "" + "\">\n" + "\bPayments\x12\x18\n" + "\aenabled\x18\x01 \x01(\bR\aenabled\x12\x18\n" + - "\aentropy\x18\x02 \x01(\fR\aentropy\"\x99\x1d\n" + + "\aentropy\x18\x02 \x01(\fR\aentropy\"\x84!\n" + "\rAccountRecord\x12\x1e\n" + "\n" + "profileKey\x18\x01 \x01(\fR\n" + @@ -3262,26 +3339,31 @@ const file_StorageService_proto_rawDesc = "" + "\x1fhasSeenGroupStoryEducationSheet\x18 \x01(\bR\x1fhasSeenGroupStoryEducationSheet\x12\x1a\n" + "\busername\x18! \x01(\tR\busername\x12F\n" + "\x1ehasCompletedUsernameOnboarding\x18\" \x01(\bR\x1ehasCompletedUsernameOnboarding\x12M\n" + - "\fusernameLink\x18# \x01(\v2).signalservice.AccountRecord.UsernameLinkR\fusernameLink\x12!\n" + - "\thasBackup\x18' \x01(\bH\x00R\thasBackup\x88\x01\x01\x12#\n" + + "\fusernameLink\x18# \x01(\v2).signalservice.AccountRecord.UsernameLinkR\fusernameLink\x12#\n" + "\n" + - "backupTier\x18( \x01(\x04H\x01R\n" + + "backupTier\x18( \x01(\x04H\x00R\n" + "backupTier\x88\x01\x01\x12b\n" + "\x14backupSubscriberData\x18) \x01(\v2..signalservice.AccountRecord.IAPSubscriberDataR\x14backupSubscriberData\x12A\n" + - "\vavatarColor\x18* \x01(\x0e2\x1a.signalservice.AvatarColorH\x02R\vavatarColor\x88\x01\x01\x12\\\n" + + "\vavatarColor\x18* \x01(\x0e2\x1a.signalservice.AvatarColorH\x01R\vavatarColor\x88\x01\x01\x12\\\n" + "\x11backupTierHistory\x18+ \x01(\v2..signalservice.AccountRecord.BackupTierHistoryR\x11backupTierHistory\x12\x8c\x01\n" + "!notificationProfileManualOverride\x18, \x01(\v2>.signalservice.AccountRecord.NotificationProfileManualOverrideR!notificationProfileManualOverride\x12H\n" + "\x1fnotificationProfileSyncDisabled\x18- \x01(\bR\x1fnotificationProfileSyncDisabled\x12J\n" + " automaticKeyVerificationDisabled\x18. \x01(\bR automaticKeyVerificationDisabled\x12L\n" + - "!hasSeenAdminDeleteEducationDialog\x18/ \x01(\bR!hasSeenAdminDeleteEducationDialog\x1a\xb0\x02\n" + + "!hasSeenAdminDeleteEducationDialog\x18/ \x01(\bR!hasSeenAdminDeleteEducationDialog\x12?\n" + + "\x18releaseNotesChatArchived\x180 \x01(\bH\x02R\x18releaseNotesChatArchived\x88\x01\x01\x12U\n" + + "#releaseNotesChatMutedUntilTimestamp\x181 \x01(\x04H\x03R#releaseNotesChatMutedUntilTimestamp\x88\x01\x01\x12=\n" + + "\x17releaseNotesChatBlocked\x182 \x01(\bH\x04R\x17releaseNotesChatBlocked\x88\x01\x01\x12G\n" + + "\x1creleaseNotesChatMarkedUnread\x183 \x01(\bH\x05R\x1creleaseNotesChatMarkedUnread\x88\x01\x01\x1a\xa4\x03\n" + "\x12PinnedConversation\x12S\n" + "\acontact\x18\x01 \x01(\v27.signalservice.AccountRecord.PinnedConversation.ContactH\x00R\acontact\x12&\n" + "\rlegacyGroupId\x18\x03 \x01(\fH\x00R\rlegacyGroupId\x12(\n" + - "\x0egroupMasterKey\x18\x04 \x01(\fH\x00R\x0egroupMasterKey\x1ae\n" + + "\x0egroupMasterKey\x18\x04 \x01(\fH\x00R\x0egroupMasterKey\x12b\n" + + "\freleaseNotes\x18\x05 \x01(\v2<.signalservice.AccountRecord.PinnedConversation.ReleaseNotesH\x00R\freleaseNotes\x1ae\n" + "\aContact\x12\x1c\n" + "\tserviceId\x18\x01 \x01(\tR\tserviceId\x12\x12\n" + "\x04e164\x18\x02 \x01(\tR\x04e164\x12(\n" + - "\x0fserviceIdBinary\x18\x03 \x01(\fR\x0fserviceIdBinaryB\f\n" + + "\x0fserviceIdBinary\x18\x03 \x01(\fR\x0fserviceIdBinary\x1a\x0e\n" + + "\fReleaseNotesB\f\n" + "\n" + "identifier\x1a\xf8\x01\n" + "\fUsernameLink\x12\x18\n" + @@ -3324,12 +3406,14 @@ const file_StorageService_proto_rawDesc = "" + "\aUNKNOWN\x10\x00\x12\r\n" + "\tEVERYBODY\x10\x01\x12\n" + "\n" + - "\x06NOBODY\x10\x02B\f\n" + - "\n" + - "_hasBackupB\r\n" + + "\x06NOBODY\x10\x02B\r\n" + "\v_backupTierB\x0e\n" + - "\f_avatarColorJ\x04\b\t\x10\n" + - "J\x04\b\x13\x10\x14J\x04\b\x1c\x10\x1dJ\x04\b\x1f\x10 J\x04\b$\x10%J\x04\b%\x10&J\x04\b&\x10'\"\xb9\x02\n" + + "\f_avatarColorB\x1b\n" + + "\x19_releaseNotesChatArchivedB&\n" + + "$_releaseNotesChatMutedUntilTimestampB\x1a\n" + + "\x18_releaseNotesChatBlockedB\x1f\n" + + "\x1d_releaseNotesChatMarkedUnreadJ\x04\b\t\x10\n" + + "J\x04\b\x13\x10\x14J\x04\b\x1c\x10\x1dJ\x04\b\x1f\x10 J\x04\b$\x10%J\x04\b%\x10&J\x04\b&\x10'J\x04\b'\x10(\"\xb9\x02\n" + "\x1bStoryDistributionListRecord\x12\x1e\n" + "\n" + "identifier\x18\x01 \x01(\fR\n" + @@ -3438,7 +3522,7 @@ func file_StorageService_proto_rawDescGZIP() []byte { } var file_StorageService_proto_enumTypes = make([]protoimpl.EnumInfo, 9) -var file_StorageService_proto_msgTypes = make([]protoimpl.MessageInfo, 27) +var file_StorageService_proto_msgTypes = make([]protoimpl.MessageInfo, 28) var file_StorageService_proto_goTypes = []any{ (OptionalBool)(0), // 0: signalservice.OptionalBool (AvatarColor)(0), // 1: signalservice.AvatarColor @@ -3474,8 +3558,9 @@ var file_StorageService_proto_goTypes = []any{ (*AccountRecord_BackupTierHistory)(nil), // 31: signalservice.AccountRecord.BackupTierHistory (*AccountRecord_NotificationProfileManualOverride)(nil), // 32: signalservice.AccountRecord.NotificationProfileManualOverride (*AccountRecord_PinnedConversation_Contact)(nil), // 33: signalservice.AccountRecord.PinnedConversation.Contact - (*AccountRecord_NotificationProfileManualOverride_ManuallyEnabled)(nil), // 34: signalservice.AccountRecord.NotificationProfileManualOverride.ManuallyEnabled - (*Recipient_Contact)(nil), // 35: signalservice.Recipient.Contact + (*AccountRecord_PinnedConversation_ReleaseNotes)(nil), // 34: signalservice.AccountRecord.PinnedConversation.ReleaseNotes + (*AccountRecord_NotificationProfileManualOverride_ManuallyEnabled)(nil), // 35: signalservice.AccountRecord.NotificationProfileManualOverride.ManuallyEnabled + (*Recipient_Contact)(nil), // 36: signalservice.Recipient.Contact } var file_StorageService_proto_depIdxs = []int32{ 10, // 0: signalservice.StorageItems.items:type_name -> signalservice.StorageItem @@ -3504,7 +3589,7 @@ var file_StorageService_proto_depIdxs = []int32{ 1, // 23: signalservice.AccountRecord.avatarColor:type_name -> signalservice.AvatarColor 31, // 24: signalservice.AccountRecord.backupTierHistory:type_name -> signalservice.AccountRecord.BackupTierHistory 32, // 25: signalservice.AccountRecord.notificationProfileManualOverride:type_name -> signalservice.AccountRecord.NotificationProfileManualOverride - 35, // 26: signalservice.Recipient.contact:type_name -> signalservice.Recipient.Contact + 36, // 26: signalservice.Recipient.contact:type_name -> signalservice.Recipient.Contact 7, // 27: signalservice.ChatFolderRecord.folderType:type_name -> signalservice.ChatFolderRecord.FolderType 23, // 28: signalservice.ChatFolderRecord.includedRecipients:type_name -> signalservice.Recipient 23, // 29: signalservice.ChatFolderRecord.excludedRecipients:type_name -> signalservice.Recipient @@ -3512,13 +3597,14 @@ var file_StorageService_proto_depIdxs = []int32{ 8, // 31: signalservice.NotificationProfile.scheduleDaysEnabled:type_name -> signalservice.NotificationProfile.DayOfWeek 2, // 32: signalservice.ManifestRecord.Identifier.type:type_name -> signalservice.ManifestRecord.Identifier.Type 33, // 33: signalservice.AccountRecord.PinnedConversation.contact:type_name -> signalservice.AccountRecord.PinnedConversation.Contact - 6, // 34: signalservice.AccountRecord.UsernameLink.color:type_name -> signalservice.AccountRecord.UsernameLink.Color - 34, // 35: signalservice.AccountRecord.NotificationProfileManualOverride.enabled:type_name -> signalservice.AccountRecord.NotificationProfileManualOverride.ManuallyEnabled - 36, // [36:36] is the sub-list for method output_type - 36, // [36:36] is the sub-list for method input_type - 36, // [36:36] is the sub-list for extension type_name - 36, // [36:36] is the sub-list for extension extendee - 0, // [0:36] is the sub-list for field type_name + 34, // 34: signalservice.AccountRecord.PinnedConversation.releaseNotes:type_name -> signalservice.AccountRecord.PinnedConversation.ReleaseNotes + 6, // 35: signalservice.AccountRecord.UsernameLink.color:type_name -> signalservice.AccountRecord.UsernameLink.Color + 35, // 36: signalservice.AccountRecord.NotificationProfileManualOverride.enabled:type_name -> signalservice.AccountRecord.NotificationProfileManualOverride.ManuallyEnabled + 37, // [37:37] is the sub-list for method output_type + 37, // [37:37] is the sub-list for method input_type + 37, // [37:37] is the sub-list for extension type_name + 37, // [37:37] is the sub-list for extension extendee + 0, // [0:37] is the sub-list for field type_name } func init() { file_StorageService_proto_init() } @@ -3549,6 +3635,7 @@ func file_StorageService_proto_init() { (*AccountRecord_PinnedConversation_Contact_)(nil), (*AccountRecord_PinnedConversation_LegacyGroupId)(nil), (*AccountRecord_PinnedConversation_GroupMasterKey)(nil), + (*AccountRecord_PinnedConversation_ReleaseNotes_)(nil), } file_StorageService_proto_msgTypes[21].OneofWrappers = []any{ (*AccountRecord_IAPSubscriberData_PurchaseToken)(nil), @@ -3565,7 +3652,7 @@ func file_StorageService_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_StorageService_proto_rawDesc), len(file_StorageService_proto_rawDesc)), NumEnums: 9, - NumMessages: 27, + NumMessages: 28, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/signalmeow/protobuf/StorageService.proto b/pkg/signalmeow/protobuf/StorageService.proto index dd232ca..0072714 100644 --- a/pkg/signalmeow/protobuf/StorageService.proto +++ b/pkg/signalmeow/protobuf/StorageService.proto @@ -195,10 +195,13 @@ message AccountRecord { bytes serviceIdBinary = 3; // service ID binary (i.e. 16 byte UUID for ACI, 1 byte prefix + 16 byte UUID for PNI) } + message ReleaseNotes {} + oneof identifier { - Contact contact = 1; - bytes legacyGroupId = 3; - bytes groupMasterKey = 4; + Contact contact = 1; + bytes legacyGroupId = 3; + bytes groupMasterKey = 4; + ReleaseNotes releaseNotes = 5; } } @@ -289,7 +292,7 @@ message AccountRecord { reserved /* backupsSubscriberId */ 36; reserved /* backupsSubscriberCurrencyCode */ 37; reserved /* backupsSubscriptionManuallyCancelled */ 38; - optional bool hasBackup = 39; // Set to true after backups are enabled and one is uploaded. + reserved /* hasBackup */ 39; optional uint64 backupTier = 40; // See zkgroup for integer particular values. Unset if backups are not enabled. IAPSubscriberData backupSubscriberData = 41; optional AvatarColor avatarColor = 42; @@ -298,6 +301,10 @@ message AccountRecord { bool notificationProfileSyncDisabled = 45; bool automaticKeyVerificationDisabled = 46; bool hasSeenAdminDeleteEducationDialog = 47; + optional bool releaseNotesChatArchived = 48; + optional uint64 releaseNotesChatMutedUntilTimestamp = 49; + optional bool releaseNotesChatBlocked = 50; + optional bool releaseNotesChatMarkedUnread = 51; } message StoryDistributionListRecord { diff --git a/pkg/signalmeow/protobuf/WebSocketResources.pb.go b/pkg/signalmeow/protobuf/WebSocketResources.pb.go index 66520eb..d52ae1e 100644 --- a/pkg/signalmeow/protobuf/WebSocketResources.pb.go +++ b/pkg/signalmeow/protobuf/WebSocketResources.pb.go @@ -321,8 +321,8 @@ const file_WebSocketResources_proto_rawDesc = "" + "\x04Type\x12\v\n" + "\aUNKNOWN\x10\x00\x12\v\n" + "\aREQUEST\x10\x01\x12\f\n" + - "\bRESPONSE\x10\x02BF\n" + - "3org.whispersystems.signalservice.internal.websocketB\x0fWebSocketProtos" + "\bRESPONSE\x10\x02B/\n" + + "\x1corg.signal.network.websocketB\x0fWebSocketProtos" var ( file_WebSocketResources_proto_rawDescOnce sync.Once diff --git a/pkg/signalmeow/protobuf/WebSocketResources.proto b/pkg/signalmeow/protobuf/WebSocketResources.proto index 376f8b2..e230ad7 100644 --- a/pkg/signalmeow/protobuf/WebSocketResources.proto +++ b/pkg/signalmeow/protobuf/WebSocketResources.proto @@ -7,7 +7,7 @@ syntax = "proto2"; package signalservice; -option java_package = "org.whispersystems.signalservice.internal.websocket"; +option java_package = "org.signal.network.websocket"; option java_outer_classname = "WebSocketProtos"; message WebSocketRequestMessage { diff --git a/pkg/signalmeow/protobuf/backuppb/Backup.pb.go b/pkg/signalmeow/protobuf/backuppb/Backup.pb.go index bc488e7..975fd50 100644 --- a/pkg/signalmeow/protobuf/backuppb/Backup.pb.go +++ b/pkg/signalmeow/protobuf/backuppb/Backup.pb.go @@ -2406,7 +2406,6 @@ type AccountData struct { AndroidSpecificSettings *AccountData_AndroidSpecificSettings `protobuf:"bytes,12,opt,name=androidSpecificSettings,proto3" json:"androidSpecificSettings,omitempty"` BioText string `protobuf:"bytes,13,opt,name=bioText,proto3" json:"bioText,omitempty"` BioEmoji string `protobuf:"bytes,14,opt,name=bioEmoji,proto3" json:"bioEmoji,omitempty"` - KeyTransparencyData []byte `protobuf:"bytes,15,opt,name=keyTransparencyData,proto3,oneof" json:"keyTransparencyData,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -2532,13 +2531,6 @@ func (x *AccountData) GetBioEmoji() string { return "" } -func (x *AccountData) GetKeyTransparencyData() []byte { - if x != nil { - return x.KeyTransparencyData - } - return nil -} - type Recipient struct { state protoimpl.MessageState `protogen:"open.v1"` Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` // generated id for reference only within this file @@ -12264,7 +12256,7 @@ const file_backuppb_Backup_proto_rawDesc = "" + "\n" + "chatFolder\x18\b \x01(\v2\x19.signal.backup.ChatFolderH\x00R\n" + "chatFolderB\x06\n" + - "\x04item\"\xc7#\n" + + "\x04item\"\xfe\"\n" + "\vAccountData\x12\x1e\n" + "\n" + "profileKey\x18\x01 \x01(\fR\n" + @@ -12283,8 +12275,7 @@ const file_backuppb_Backup_proto_rawDesc = "" + "\x06svrPin\x18\v \x01(\tR\x06svrPin\x12l\n" + "\x17androidSpecificSettings\x18\f \x01(\v22.signal.backup.AccountData.AndroidSpecificSettingsR\x17androidSpecificSettings\x12\x18\n" + "\abioText\x18\r \x01(\tR\abioText\x12\x1a\n" + - "\bbioEmoji\x18\x0e \x01(\tR\bbioEmoji\x125\n" + - "\x13keyTransparencyData\x18\x0f \x01(\fH\x01R\x13keyTransparencyData\x88\x01\x01\x1a\xf6\x01\n" + + "\bbioEmoji\x18\x0e \x01(\tR\bbioEmoji\x1a\xf6\x01\n" + "\fUsernameLink\x12\x18\n" + "\aentropy\x18\x01 \x01(\fR\aentropy\x12\x1a\n" + "\bserverId\x18\x02 \x01(\fR\bserverId\x12C\n" + @@ -12387,8 +12378,7 @@ const file_backuppb_Backup_proto_rawDesc = "" + "\x05NEVER\x10\x01\x12\x14\n" + "\x10MOBILE_DATA_ONLY\x10\x02\x12\x18\n" + "\x14WIFI_AND_MOBILE_DATA\x10\x03B\v\n" + - "\t_usernameB\x16\n" + - "\x14_keyTransparencyDataJ\x04\b\b\x10\t\"\x84\x03\n" + + "\t_usernameJ\x04\b\b\x10\tJ\x04\b\x0f\x10\x10\"\x84\x03\n" + "\tRecipient\x12\x0e\n" + "\x02id\x18\x01 \x01(\x04R\x02id\x122\n" + "\acontact\x18\x02 \x01(\v2\x16.signal.backup.ContactH\x00R\acontact\x12,\n" + diff --git a/pkg/signalmeow/protobuf/backuppb/Backup.proto b/pkg/signalmeow/protobuf/backuppb/Backup.proto index d7407cb..512bdaf 100644 --- a/pkg/signalmeow/protobuf/backuppb/Backup.proto +++ b/pkg/signalmeow/protobuf/backuppb/Backup.proto @@ -182,7 +182,7 @@ message AccountData { AndroidSpecificSettings androidSpecificSettings = 12; string bioText = 13; string bioEmoji = 14; - optional bytes keyTransparencyData = 15; + reserved /*keyTransparencyData*/ 15; // No longer want to persist self-KT data } message Recipient { diff --git a/pkg/signalmeow/protobuf/update-protos.sh b/pkg/signalmeow/protobuf/update-protos.sh index f9c86fc..621a628 100755 --- a/pkg/signalmeow/protobuf/update-protos.sh +++ b/pkg/signalmeow/protobuf/update-protos.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -ANDROID_GIT_REVISION=${1:-439760e7732585bfd078d92d93732c04cc31e29e} -DESKTOP_GIT_REVISION=${1:-1b2a3e7b283c32c5654a39da12fc04139fd26dbd} +ANDROID_GIT_REVISION=${1:-aa9591211ba0c77376318bdd5f014e064b8e8de4} +DESKTOP_GIT_REVISION=${1:-a0af83d7488930c213a7b6dd554490ebe9e65628} update_proto() { case "$1" in @@ -16,6 +16,11 @@ update_proto() { prefix="lib/archive/src/main/protowire/" GIT_REVISION=$ANDROID_GIT_REVISION ;; + Signal-Android-Network) + REPO="Signal-Android" + prefix="core/network/src/main/protowire/" + GIT_REVISION=$ANDROID_GIT_REVISION + ;; Signal-Desktop) REPO="Signal-Desktop" prefix="protos/" @@ -31,7 +36,7 @@ update_proto Signal-Android Groups.proto update_proto Signal-Android Provisioning.proto update_proto Signal-Android SignalService.proto update_proto Signal-Android StickerResources.proto -update_proto Signal-Android WebSocketResources.proto +update_proto Signal-Android-Network WebSocketResources.proto update_proto Signal-Android StorageService.proto update_proto Signal-Android-Archive Backup.proto From 04fc9acaf4ffb7c469c70eaba456474aeae37a3e Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 5 Jun 2026 00:12:12 +0300 Subject: [PATCH 25/34] signalmeow: switch to fetching cds2.proto from libsignal --- pkg/signalmeow/contactdiscovery.go | 18 +- .../protobuf/ContactDiscovery.pb.go | 272 ------------------ pkg/signalmeow/protobuf/build-protos.sh | 4 + pkg/signalmeow/protobuf/cds2pb/cds2.pb.go | 259 +++++++++++++++++ .../cds2.proto} | 41 +-- pkg/signalmeow/protobuf/update-protos.sh | 11 +- 6 files changed, 306 insertions(+), 299 deletions(-) delete mode 100644 pkg/signalmeow/protobuf/ContactDiscovery.pb.go create mode 100644 pkg/signalmeow/protobuf/cds2pb/cds2.pb.go rename pkg/signalmeow/protobuf/{ContactDiscovery.proto => cds2pb/cds2.proto} (70%) diff --git a/pkg/signalmeow/contactdiscovery.go b/pkg/signalmeow/contactdiscovery.go index e0499a7..14b7fd6 100644 --- a/pkg/signalmeow/contactdiscovery.go +++ b/pkg/signalmeow/contactdiscovery.go @@ -35,12 +35,14 @@ import ( "google.golang.org/protobuf/proto" "go.mau.fi/mautrix-signal/pkg/libsignalgo" - signalpb "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf" + "go.mau.fi/mautrix-signal/pkg/signalmeow/protobuf/cds2pb" "go.mau.fi/mautrix-signal/pkg/signalmeow/web" ) -const ProdContactDiscoveryServer = "cdsi.signal.org" +// ProdContactDiscoveryMrenclave should always match ENCLAVE_ID_CDSI_PROD from libsignal +// https://github.com/signalapp/libsignal/blob/main/rust/attest/src/constants.rs#L69 const ProdContactDiscoveryMrenclave = "15637fa1e54fe655176d3df1a9f94b87c01ed377acaa570682dc5d72c95ef07b" +const ProdContactDiscoveryServer = "cdsi.signal.org" const ContactDiscoveryAuthTTL = 23 * time.Hour const rateLimitCloseCode = websocket.StatusCode(4008) @@ -81,7 +83,7 @@ func (cli *Client) LookupPhone(ctx context.Context, e164s ...uint64) (ContactDis } ctx, cancel := context.WithTimeout(ctx, 20*time.Second) defer cancel() - resp, token, err := cli.doContactDiscovery(ctx, &signalpb.CDSClientRequest{ + resp, token, err := cli.doContactDiscovery(ctx, &cds2pb.ClientRequest{ // TODO figure out if tokens are useful // (it's meant for old_e164s) //Token: cli.cdToken, @@ -93,7 +95,7 @@ func (cli *Client) LookupPhone(ctx context.Context, e164s ...uint64) (ContactDis return resp, err } -func (cli *Client) doContactDiscovery(ctx context.Context, req *signalpb.CDSClientRequest) (ContactDiscoveryResponse, []byte, error) { +func (cli *Client) doContactDiscovery(ctx context.Context, req *cds2pb.ClientRequest) (ContactDiscoveryResponse, []byte, error) { creds, err := cli.getContactDiscoveryCredentials(ctx) if err != nil { return nil, nil, fmt.Errorf("failed to fetch contact discovery auth: %w", err) @@ -185,7 +187,7 @@ func (cdc *ContactDiscoveryClient) Handshake(ctx context.Context) error { return nil } -func (cdc *ContactDiscoveryClient) SendRequest(ctx context.Context, req *signalpb.CDSClientRequest) error { +func (cdc *ContactDiscoveryClient) SendRequest(ctx context.Context, req *cds2pb.ClientRequest) error { plaintext, err := proto.Marshal(req) if err != nil { return fmt.Errorf("failed to marshal request: %w", err) @@ -222,15 +224,15 @@ func (cdc *ContactDiscoveryClient) handleResponse(ctx context.Context, msg []byt if err != nil { return fmt.Errorf("failed to decrypt message: %w", err) } - var cdsClientResp signalpb.CDSClientResponse + var cdsClientResp cds2pb.ClientResponse err = proto.Unmarshal(decrypted, &cdsClientResp) if err != nil { return fmt.Errorf("failed to unmarshal message: %w", err) } if cdsClientResp.Token != nil { cdc.Token = cdsClientResp.Token - err = cdc.SendRequest(ctx, &signalpb.CDSClientRequest{ - TokenAck: proto.Bool(true), + err = cdc.SendRequest(ctx, &cds2pb.ClientRequest{ + TokenAck: true, }) if err != nil { return fmt.Errorf("failed to send token ack request: %w", err) diff --git a/pkg/signalmeow/protobuf/ContactDiscovery.pb.go b/pkg/signalmeow/protobuf/ContactDiscovery.pb.go deleted file mode 100644 index 5cb232c..0000000 --- a/pkg/signalmeow/protobuf/ContactDiscovery.pb.go +++ /dev/null @@ -1,272 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.11 -// protoc v7.34.1 -// source: ContactDiscovery.proto - -// Copyright 2021 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -package signalpb - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type CDSClientRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Each ACI/UAK pair is a 32-byte buffer, containing the 16-byte ACI followed - // by its 16-byte UAK. - AciUakPairs []byte `protobuf:"bytes,1,opt,name=aci_uak_pairs,json=aciUakPairs" json:"aci_uak_pairs,omitempty"` - // Each E164 is an 8-byte big-endian number, as 8 bytes. - PrevE164S []byte `protobuf:"bytes,2,opt,name=prev_e164s,json=prevE164s" json:"prev_e164s,omitempty"` - NewE164S []byte `protobuf:"bytes,3,opt,name=new_e164s,json=newE164s" json:"new_e164s,omitempty"` - DiscardE164S []byte `protobuf:"bytes,4,opt,name=discard_e164s,json=discardE164s" json:"discard_e164s,omitempty"` - // If true, the client has more pairs or e164s to send. If false or unset, - // this is the client's last request, and processing should commence. - HasMore *bool `protobuf:"varint,5,opt,name=has_more,json=hasMore" json:"has_more,omitempty"` - // If set, a token which allows rate limiting to discount the e164s in - // the request's prev_e164s, only counting new_e164s. If not set, then - // rate limiting considers both prev_e164s' and new_e164s' size. - Token []byte `protobuf:"bytes,6,opt,name=token" json:"token,omitempty"` - // After receiving a new token from the server, send back a message just - // containing a token_ack. - TokenAck *bool `protobuf:"varint,7,opt,name=token_ack,json=tokenAck" json:"token_ack,omitempty"` - // Request that, if the server allows, both ACI and PNI be returned even - // if the aci_uak_pairs don't match. - ReturnAcisWithoutUaks *bool `protobuf:"varint,8,opt,name=return_acis_without_uaks,json=returnAcisWithoutUaks" json:"return_acis_without_uaks,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CDSClientRequest) Reset() { - *x = CDSClientRequest{} - mi := &file_ContactDiscovery_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CDSClientRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CDSClientRequest) ProtoMessage() {} - -func (x *CDSClientRequest) ProtoReflect() protoreflect.Message { - mi := &file_ContactDiscovery_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CDSClientRequest.ProtoReflect.Descriptor instead. -func (*CDSClientRequest) Descriptor() ([]byte, []int) { - return file_ContactDiscovery_proto_rawDescGZIP(), []int{0} -} - -func (x *CDSClientRequest) GetAciUakPairs() []byte { - if x != nil { - return x.AciUakPairs - } - return nil -} - -func (x *CDSClientRequest) GetPrevE164S() []byte { - if x != nil { - return x.PrevE164S - } - return nil -} - -func (x *CDSClientRequest) GetNewE164S() []byte { - if x != nil { - return x.NewE164S - } - return nil -} - -func (x *CDSClientRequest) GetDiscardE164S() []byte { - if x != nil { - return x.DiscardE164S - } - return nil -} - -func (x *CDSClientRequest) GetHasMore() bool { - if x != nil && x.HasMore != nil { - return *x.HasMore - } - return false -} - -func (x *CDSClientRequest) GetToken() []byte { - if x != nil { - return x.Token - } - return nil -} - -func (x *CDSClientRequest) GetTokenAck() bool { - if x != nil && x.TokenAck != nil { - return *x.TokenAck - } - return false -} - -func (x *CDSClientRequest) GetReturnAcisWithoutUaks() bool { - if x != nil && x.ReturnAcisWithoutUaks != nil { - return *x.ReturnAcisWithoutUaks - } - return false -} - -type CDSClientResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Each triple is an 8-byte e164, a 16-byte PNI, and a 16-byte ACI. - // If the e164 was not found, PNI and ACI are all zeros. If the PNI - // was found but the ACI was not, the PNI will be non-zero and the ACI - // will be all zeros. ACI will be returned if one of the returned - // PNIs has an ACI/UAK pair that matches. - // - // Should the request be successful (IE: a successful status returned), - // |e164_pni_aci_triple| will always equal |e164| of the request, - // so the entire marshalled size of the response will be (2+32)*|e164|, - // where the additional 2 bytes are the id/type/length additions of the - // protobuf marshaling added to each byte array. This avoids any data - // leakage based on the size of the encrypted output. - E164PniAciTriples []byte `protobuf:"bytes,1,opt,name=e164_pni_aci_triples,json=e164PniAciTriples" json:"e164_pni_aci_triples,omitempty"` - // A token which allows subsequent calls' rate limiting to discount the - // e164s sent up in this request, only counting those in the next - // request's new_e164s. - Token []byte `protobuf:"bytes,3,opt,name=token" json:"token,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CDSClientResponse) Reset() { - *x = CDSClientResponse{} - mi := &file_ContactDiscovery_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CDSClientResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CDSClientResponse) ProtoMessage() {} - -func (x *CDSClientResponse) ProtoReflect() protoreflect.Message { - mi := &file_ContactDiscovery_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CDSClientResponse.ProtoReflect.Descriptor instead. -func (*CDSClientResponse) Descriptor() ([]byte, []int) { - return file_ContactDiscovery_proto_rawDescGZIP(), []int{1} -} - -func (x *CDSClientResponse) GetE164PniAciTriples() []byte { - if x != nil { - return x.E164PniAciTriples - } - return nil -} - -func (x *CDSClientResponse) GetToken() []byte { - if x != nil { - return x.Token - } - return nil -} - -var File_ContactDiscovery_proto protoreflect.FileDescriptor - -const file_ContactDiscovery_proto_rawDesc = "" + - "\n" + - "\x16ContactDiscovery.proto\x12\rsignalservice\"\x9e\x02\n" + - "\x10CDSClientRequest\x12\"\n" + - "\raci_uak_pairs\x18\x01 \x01(\fR\vaciUakPairs\x12\x1d\n" + - "\n" + - "prev_e164s\x18\x02 \x01(\fR\tprevE164s\x12\x1b\n" + - "\tnew_e164s\x18\x03 \x01(\fR\bnewE164s\x12#\n" + - "\rdiscard_e164s\x18\x04 \x01(\fR\fdiscardE164s\x12\x19\n" + - "\bhas_more\x18\x05 \x01(\bR\ahasMore\x12\x14\n" + - "\x05token\x18\x06 \x01(\fR\x05token\x12\x1b\n" + - "\ttoken_ack\x18\a \x01(\bR\btokenAck\x127\n" + - "\x18return_acis_without_uaks\x18\b \x01(\bR\x15returnAcisWithoutUaks\"Z\n" + - "\x11CDSClientResponse\x12/\n" + - "\x14e164_pni_aci_triples\x18\x01 \x01(\fR\x11e164PniAciTriples\x12\x14\n" + - "\x05token\x18\x03 \x01(\fR\x05token" - -var ( - file_ContactDiscovery_proto_rawDescOnce sync.Once - file_ContactDiscovery_proto_rawDescData []byte -) - -func file_ContactDiscovery_proto_rawDescGZIP() []byte { - file_ContactDiscovery_proto_rawDescOnce.Do(func() { - file_ContactDiscovery_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_ContactDiscovery_proto_rawDesc), len(file_ContactDiscovery_proto_rawDesc))) - }) - return file_ContactDiscovery_proto_rawDescData -} - -var file_ContactDiscovery_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_ContactDiscovery_proto_goTypes = []any{ - (*CDSClientRequest)(nil), // 0: signalservice.CDSClientRequest - (*CDSClientResponse)(nil), // 1: signalservice.CDSClientResponse -} -var file_ContactDiscovery_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_ContactDiscovery_proto_init() } -func file_ContactDiscovery_proto_init() { - if File_ContactDiscovery_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_ContactDiscovery_proto_rawDesc), len(file_ContactDiscovery_proto_rawDesc)), - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_ContactDiscovery_proto_goTypes, - DependencyIndexes: file_ContactDiscovery_proto_depIdxs, - MessageInfos: file_ContactDiscovery_proto_msgTypes, - }.Build() - File_ContactDiscovery_proto = out.File - file_ContactDiscovery_proto_goTypes = nil - file_ContactDiscovery_proto_depIdxs = nil -} diff --git a/pkg/signalmeow/protobuf/build-protos.sh b/pkg/signalmeow/protobuf/build-protos.sh index 54116ec..372b791 100755 --- a/pkg/signalmeow/protobuf/build-protos.sh +++ b/pkg/signalmeow/protobuf/build-protos.sh @@ -12,4 +12,8 @@ protoc --go_out=. \ --go_opt=Mbackuppb/Backup.proto=$PKG_IMPORT_PATH/backuppb \ --go_opt=paths=source_relative \ backuppb/Backup.proto +protoc --go_out=. \ + --go_opt=Mcds2pb/cds2.proto=$PKG_IMPORT_PATH/cds2pb \ + --go_opt=paths=source_relative \ + cds2pb/cds2.proto pre-commit run -a diff --git a/pkg/signalmeow/protobuf/cds2pb/cds2.pb.go b/pkg/signalmeow/protobuf/cds2pb/cds2.pb.go new file mode 100644 index 0000000..2c8634a --- /dev/null +++ b/pkg/signalmeow/protobuf/cds2pb/cds2.pb.go @@ -0,0 +1,259 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v7.34.1 +// source: cds2pb/cds2.proto + +package cds2pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ClientRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Each ACI/UAK pair is a 32-byte buffer, containing the 16-byte ACI followed + // by its 16-byte UAK. + AciUakPairs []byte `protobuf:"bytes,1,opt,name=aci_uak_pairs,json=aciUakPairs,proto3" json:"aci_uak_pairs,omitempty"` + // Each E164 is an 8-byte big-endian number, as 8 bytes. + PrevE164S []byte `protobuf:"bytes,2,opt,name=prev_e164s,json=prevE164s,proto3" json:"prev_e164s,omitempty"` + NewE164S []byte `protobuf:"bytes,3,opt,name=new_e164s,json=newE164s,proto3" json:"new_e164s,omitempty"` + DiscardE164S []byte `protobuf:"bytes,4,opt,name=discard_e164s,json=discardE164s,proto3" json:"discard_e164s,omitempty"` + // If set, a token which allows rate limiting to discount the e164s in + // the request's prev_e164s, only counting new_e164s. If not set, then + // rate limiting considers both prev_e164s' and new_e164s' size. + Token []byte `protobuf:"bytes,6,opt,name=token,proto3" json:"token,omitempty"` + // After receiving a new token from the server, send back a message just + // containing a token_ack. + TokenAck bool `protobuf:"varint,7,opt,name=token_ack,json=tokenAck,proto3" json:"token_ack,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClientRequest) Reset() { + *x = ClientRequest{} + mi := &file_cds2pb_cds2_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClientRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClientRequest) ProtoMessage() {} + +func (x *ClientRequest) ProtoReflect() protoreflect.Message { + mi := &file_cds2pb_cds2_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClientRequest.ProtoReflect.Descriptor instead. +func (*ClientRequest) Descriptor() ([]byte, []int) { + return file_cds2pb_cds2_proto_rawDescGZIP(), []int{0} +} + +func (x *ClientRequest) GetAciUakPairs() []byte { + if x != nil { + return x.AciUakPairs + } + return nil +} + +func (x *ClientRequest) GetPrevE164S() []byte { + if x != nil { + return x.PrevE164S + } + return nil +} + +func (x *ClientRequest) GetNewE164S() []byte { + if x != nil { + return x.NewE164S + } + return nil +} + +func (x *ClientRequest) GetDiscardE164S() []byte { + if x != nil { + return x.DiscardE164S + } + return nil +} + +func (x *ClientRequest) GetToken() []byte { + if x != nil { + return x.Token + } + return nil +} + +func (x *ClientRequest) GetTokenAck() bool { + if x != nil { + return x.TokenAck + } + return false +} + +type ClientResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Each triple is an 8-byte e164, a 16-byte PNI, and a 16-byte ACI. + // If the e164 was not found, PNI and ACI are all zeros. If the PNI + // was found but the ACI was not, the PNI will be non-zero and the ACI + // will be all zeros. ACI will be returned if one of the returned + // PNIs has an ACI/UAK pair that matches. + // + // Should the request be successful (IE: a successful status returned), + // |e164_pni_aci_triple| will always equal |e164| of the request, + // so the entire marshalled size of the response will be (2+32)*|e164|, + // where the additional 2 bytes are the id/type/length additions of the + // protobuf marshaling added to each byte array. This avoids any data + // leakage based on the size of the encrypted output. + E164PniAciTriples []byte `protobuf:"bytes,1,opt,name=e164_pni_aci_triples,json=e164PniAciTriples,proto3" json:"e164_pni_aci_triples,omitempty"` + // A token which allows subsequent calls' rate limiting to discount the + // e164s sent up in this request, only counting those in the next + // request's new_e164s. + Token []byte `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"` + // On a successful response to a token_ack request, the number of permits + // that were deducted from the user's rate-limit in order to process the + // request + DebugPermitsUsed int32 `protobuf:"varint,4,opt,name=debug_permits_used,json=debugPermitsUsed,proto3" json:"debug_permits_used,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClientResponse) Reset() { + *x = ClientResponse{} + mi := &file_cds2pb_cds2_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClientResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClientResponse) ProtoMessage() {} + +func (x *ClientResponse) ProtoReflect() protoreflect.Message { + mi := &file_cds2pb_cds2_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClientResponse.ProtoReflect.Descriptor instead. +func (*ClientResponse) Descriptor() ([]byte, []int) { + return file_cds2pb_cds2_proto_rawDescGZIP(), []int{1} +} + +func (x *ClientResponse) GetE164PniAciTriples() []byte { + if x != nil { + return x.E164PniAciTriples + } + return nil +} + +func (x *ClientResponse) GetToken() []byte { + if x != nil { + return x.Token + } + return nil +} + +func (x *ClientResponse) GetDebugPermitsUsed() int32 { + if x != nil { + return x.DebugPermitsUsed + } + return 0 +} + +var File_cds2pb_cds2_proto protoreflect.FileDescriptor + +const file_cds2pb_cds2_proto_rawDesc = "" + + "\n" + + "\x11cds2pb/cds2.proto\x12\x0forg.signal.cdsi\"\xd3\x01\n" + + "\rClientRequest\x12\"\n" + + "\raci_uak_pairs\x18\x01 \x01(\fR\vaciUakPairs\x12\x1d\n" + + "\n" + + "prev_e164s\x18\x02 \x01(\fR\tprevE164s\x12\x1b\n" + + "\tnew_e164s\x18\x03 \x01(\fR\bnewE164s\x12#\n" + + "\rdiscard_e164s\x18\x04 \x01(\fR\fdiscardE164s\x12\x14\n" + + "\x05token\x18\x06 \x01(\fR\x05token\x12\x1b\n" + + "\ttoken_ack\x18\a \x01(\bR\btokenAckJ\x04\b\x05\x10\x06J\x04\b\b\x10\t\"\x8b\x01\n" + + "\x0eClientResponse\x12/\n" + + "\x14e164_pni_aci_triples\x18\x01 \x01(\fR\x11e164PniAciTriples\x12\x14\n" + + "\x05token\x18\x03 \x01(\fR\x05token\x12,\n" + + "\x12debug_permits_used\x18\x04 \x01(\x05R\x10debugPermitsUsedJ\x04\b\x02\x10\x03b\x06proto3" + +var ( + file_cds2pb_cds2_proto_rawDescOnce sync.Once + file_cds2pb_cds2_proto_rawDescData []byte +) + +func file_cds2pb_cds2_proto_rawDescGZIP() []byte { + file_cds2pb_cds2_proto_rawDescOnce.Do(func() { + file_cds2pb_cds2_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_cds2pb_cds2_proto_rawDesc), len(file_cds2pb_cds2_proto_rawDesc))) + }) + return file_cds2pb_cds2_proto_rawDescData +} + +var file_cds2pb_cds2_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_cds2pb_cds2_proto_goTypes = []any{ + (*ClientRequest)(nil), // 0: org.signal.cdsi.ClientRequest + (*ClientResponse)(nil), // 1: org.signal.cdsi.ClientResponse +} +var file_cds2pb_cds2_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_cds2pb_cds2_proto_init() } +func file_cds2pb_cds2_proto_init() { + if File_cds2pb_cds2_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_cds2pb_cds2_proto_rawDesc), len(file_cds2pb_cds2_proto_rawDesc)), + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cds2pb_cds2_proto_goTypes, + DependencyIndexes: file_cds2pb_cds2_proto_depIdxs, + MessageInfos: file_cds2pb_cds2_proto_msgTypes, + }.Build() + File_cds2pb_cds2_proto = out.File + file_cds2pb_cds2_proto_goTypes = nil + file_cds2pb_cds2_proto_depIdxs = nil +} diff --git a/pkg/signalmeow/protobuf/ContactDiscovery.proto b/pkg/signalmeow/protobuf/cds2pb/cds2.proto similarity index 70% rename from pkg/signalmeow/protobuf/ContactDiscovery.proto rename to pkg/signalmeow/protobuf/cds2pb/cds2.proto index d1f5e04..0b5cd3f 100644 --- a/pkg/signalmeow/protobuf/ContactDiscovery.proto +++ b/pkg/signalmeow/protobuf/cds2pb/cds2.proto @@ -1,37 +1,36 @@ -// Copyright 2021 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only +syntax = "proto3"; -package signalservice; +package org.signal.cdsi; -message CDSClientRequest { +message ClientRequest { // Each ACI/UAK pair is a 32-byte buffer, containing the 16-byte ACI followed // by its 16-byte UAK. - optional bytes aci_uak_pairs = 1; + bytes aci_uak_pairs = 1; // Each E164 is an 8-byte big-endian number, as 8 bytes. - optional bytes prev_e164s = 2; - optional bytes new_e164s = 3; - optional bytes discard_e164s = 4; + bytes prev_e164s = 2; + bytes new_e164s = 3; + bytes discard_e164s = 4; // If true, the client has more pairs or e164s to send. If false or unset, // this is the client's last request, and processing should commence. - optional bool has_more = 5; + // bool has_more = 5; + reserved 5; // If set, a token which allows rate limiting to discount the e164s in // the request's prev_e164s, only counting new_e164s. If not set, then // rate limiting considers both prev_e164s' and new_e164s' size. - optional bytes token = 6; + bytes token = 6; // After receiving a new token from the server, send back a message just // containing a token_ack. - optional bool token_ack = 7; + bool token_ack = 7; - // Request that, if the server allows, both ACI and PNI be returned even - // if the aci_uak_pairs don't match. - optional bool return_acis_without_uaks = 8; + // [deprecated] bool return_acis_without_uaks = 8 + reserved 8; } -message CDSClientResponse { +message ClientResponse { // Each triple is an 8-byte e164, a 16-byte PNI, and a 16-byte ACI. // If the e164 was not found, PNI and ACI are all zeros. If the PNI // was found but the ACI was not, the PNI will be non-zero and the ACI @@ -44,10 +43,18 @@ message CDSClientResponse { // where the additional 2 bytes are the id/type/length additions of the // protobuf marshaling added to each byte array. This avoids any data // leakage based on the size of the encrypted output. - optional bytes e164_pni_aci_triples = 1; + bytes e164_pni_aci_triples = 1; + + // int32 retry_after_secs = 2 [deprecated] + reserved 2; // A token which allows subsequent calls' rate limiting to discount the // e164s sent up in this request, only counting those in the next // request's new_e164s. - optional bytes token = 3; + bytes token = 3; + + // On a successful response to a token_ack request, the number of permits + // that were deducted from the user's rate-limit in order to process the + // request + int32 debug_permits_used = 4; } diff --git a/pkg/signalmeow/protobuf/update-protos.sh b/pkg/signalmeow/protobuf/update-protos.sh index 621a628..9bc1023 100755 --- a/pkg/signalmeow/protobuf/update-protos.sh +++ b/pkg/signalmeow/protobuf/update-protos.sh @@ -2,7 +2,8 @@ set -euo pipefail ANDROID_GIT_REVISION=${1:-aa9591211ba0c77376318bdd5f014e064b8e8de4} -DESKTOP_GIT_REVISION=${1:-a0af83d7488930c213a7b6dd554490ebe9e65628} +DESKTOP_GIT_REVISION=${2:-a0af83d7488930c213a7b6dd554490ebe9e65628} +LIBSIGNAL_GIT_REVISION=${3:-46d867c986f66201e34e7ae20ce423eec742bf3f} update_proto() { case "$1" in @@ -26,6 +27,11 @@ update_proto() { prefix="protos/" GIT_REVISION=$DESKTOP_GIT_REVISION ;; + libsignal) + REPO="libsignal" + prefix="rust/net/src/proto/" + GIT_REVISION=$LIBSIGNAL_GIT_REVISION + ;; esac echo https://raw.githubusercontent.com/signalapp/${REPO}/${GIT_REVISION}/${prefix}${2} curl -LOf https://raw.githubusercontent.com/signalapp/${REPO}/${GIT_REVISION}/${prefix}${2} @@ -43,6 +49,7 @@ update_proto Signal-Android-Archive Backup.proto mv Backup.proto backuppb/Backup.proto update_proto Signal-Desktop DeviceName.proto +update_proto libsignal cds2.proto +mv cds2.proto cds2pb/cds2.proto # TODO these were moved to libsignal only #update_proto Signal-Desktop UnidentifiedDelivery.proto -#update_proto Signal-Desktop ContactDiscovery.proto From d54de94b9a28f14342ef8e5e1b3b0dd13fdde6de Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 5 Jun 2026 00:22:40 +0300 Subject: [PATCH 26/34] libsignal: update to v0.94.4 --- pkg/libsignalgo/address.go | 2 +- pkg/libsignalgo/conversions.go | 2 +- pkg/libsignalgo/error.go | 2 +- pkg/libsignalgo/fingerprint.go | 2 +- pkg/libsignalgo/libsignal | 2 +- pkg/libsignalgo/libsignal-ffi.h | 215 ++++++++++++++++++--------- pkg/libsignalgo/logging.go | 4 +- pkg/libsignalgo/message.go | 19 --- pkg/libsignalgo/sendercertificate.go | 4 +- pkg/libsignalgo/sessionrecord.go | 1 + pkg/libsignalgo/version.go | 2 +- 11 files changed, 157 insertions(+), 98 deletions(-) diff --git a/pkg/libsignalgo/address.go b/pkg/libsignalgo/address.go index cfc6e58..3f54b44 100644 --- a/pkg/libsignalgo/address.go +++ b/pkg/libsignalgo/address.go @@ -81,7 +81,7 @@ func (pa *Address) CancelFinalizer() { } func (pa *Address) Name() (string, error) { - var name *C.char + var name C.SignalCStringPtr signalFfiError := C.signal_address_get_name(&name, pa.constPtr()) runtime.KeepAlive(pa) if signalFfiError != nil { diff --git a/pkg/libsignalgo/conversions.go b/pkg/libsignalgo/conversions.go index 1963687..efaafa4 100644 --- a/pkg/libsignalgo/conversions.go +++ b/pkg/libsignalgo/conversions.go @@ -22,7 +22,7 @@ package libsignalgo import "C" import "unsafe" -func CopyCStringToString(cString *C.char) (s string) { +func CopyCStringToString(cString C.SignalCStringPtr) (s string) { s = C.GoString(cString) C.signal_free_string(cString) return diff --git a/pkg/libsignalgo/error.go b/pkg/libsignalgo/error.go index 888f8ea..cf46b94 100644 --- a/pkg/libsignalgo/error.go +++ b/pkg/libsignalgo/error.go @@ -152,7 +152,7 @@ func wrapError(signalError *C.SignalFfiError) error { } func wrapSignalError(signalError *C.SignalFfiError, errorType C.uint32_t) error { - var messageBytes *C.char + var messageBytes C.SignalCStringPtr getMessageError := C.signal_error_get_message(&messageBytes, signalError) if getMessageError != nil { // Ignore any errors from this, it will just end up being an empty string. diff --git a/pkg/libsignalgo/fingerprint.go b/pkg/libsignalgo/fingerprint.go index b2ef8ce..b69ee71 100644 --- a/pkg/libsignalgo/fingerprint.go +++ b/pkg/libsignalgo/fingerprint.go @@ -92,7 +92,7 @@ func (f *Fingerprint) ScannableEncoding() ([]byte, error) { } func (f *Fingerprint) DisplayString() (string, error) { - var displayString *C.char + var displayString C.SignalCStringPtr signalFfiError := C.signal_fingerprint_display_string(&displayString, f.constPtr()) runtime.KeepAlive(f) if signalFfiError != nil { diff --git a/pkg/libsignalgo/libsignal b/pkg/libsignalgo/libsignal index bbc1688..46d867c 160000 --- a/pkg/libsignalgo/libsignal +++ b/pkg/libsignalgo/libsignal @@ -1 +1 @@ -Subproject commit bbc16886cae2feab1cd1fe271ccc651e8860ce96 +Subproject commit 46d867c986f66201e34e7ae20ce423eec742bf3f diff --git a/pkg/libsignalgo/libsignal-ffi.h b/pkg/libsignalgo/libsignal-ffi.h index b75462a..27ac1f3 100644 --- a/pkg/libsignalgo/libsignal-ffi.h +++ b/pkg/libsignalgo/libsignal-ffi.h @@ -29,6 +29,14 @@ SPDX-License-Identifier: AGPL-3.0-only #define SignalBackupId_LEN 16 +#define SignalAes256GcmEncryption_TAG_SIZE SignalTAG_SIZE + +#define SignalAes256GcmEncryption_NONCE_SIZE SignalNONCE_SIZE + +#define SignalAes256GcmDecryption_TAG_SIZE SignalTAG_SIZE + +#define SignalAes256GcmDecryption_NONCE_SIZE SignalNONCE_SIZE + #define SignalCallLinkSecretParams_ROOT_KEY_MAX_BYTES_FOR_SHO 16 #define SignalNUM_AUTH_CRED_ATTRIBUTES 3 @@ -127,12 +135,31 @@ SPDX-License-Identifier: AGPL-3.0-only */ #define SignalFourCC_ENCODED_LEN 4 +typedef enum { + SignalLogLevelError = 1, + SignalLogLevelWarn, + SignalLogLevelInfo, + SignalLogLevelDebug, + SignalLogLevelTrace, +} SignalLogLevel; + +enum SignalFfiPublicKeyType { + SignalFfiPublicKeyTypeECC, + SignalFfiPublicKeyTypeKyber, +}; +typedef uint8_t SignalFfiPublicKeyType; + enum SignalChallengeOption { SignalChallengeOptionPushChallenge, SignalChallengeOptionCaptcha, }; typedef uint8_t SignalChallengeOption; +typedef enum { + SignalDirectionSending = 0, + SignalDirectionReceiving = 1, +} SignalDirection; + typedef enum { SignalCiphertextMessageTypeWhisper = 2, SignalCiphertextMessageTypePreKey = 3, @@ -146,17 +173,6 @@ typedef enum { SignalContentHintImplicit = 2, } SignalContentHint; -typedef enum { - SignalDirectionSending = 0, - SignalDirectionReceiving = 1, -} SignalDirection; - -enum SignalFfiPublicKeyType { - SignalFfiPublicKeyTypeECC, - SignalFfiPublicKeyTypeKyber, -}; -typedef uint8_t SignalFfiPublicKeyType; - /** * The result of saving a new identity key for a protocol address. */ @@ -171,14 +187,6 @@ typedef enum { SignalIdentityChangeReplacedExisting, } SignalIdentityChange; -typedef enum { - SignalLogLevelError = 1, - SignalLogLevelWarn, - SignalLogLevelInfo, - SignalLogLevelDebug, - SignalLogLevelTrace, -} SignalLogLevel; - typedef enum { SignalErrorCodeUnknownError = 1, SignalErrorCodeInvalidState = 2, @@ -405,6 +413,12 @@ typedef struct SignalUnidentifiedSenderMessageContent SignalUnidentifiedSenderMe typedef struct SignalValidatingMac SignalValidatingMac; +/** + * A type alias to be used with [`OwnedBufferOf`], so that `OwnedBufferOf` and + * `OwnedBufferOf<*const c_char>` get distinct names. + */ +typedef const char *SignalCStringPtr; + typedef struct { SignalProtocolAddress *raw; } SignalMutPointerProtocolAddress; @@ -512,12 +526,6 @@ typedef struct { const SignalAuthenticatedChatConnection *raw; } SignalConstPointerAuthenticatedChatConnection; -/** - * A type alias to be used with [`OwnedBufferOf`], so that `OwnedBufferOf` and - * `OwnedBufferOf<*const c_char>` get distinct names. - */ -typedef const char *SignalCStringPtr; - /** * A representation of a array allocated on the Rust heap for use in C code. */ @@ -650,6 +658,21 @@ typedef struct { size_t length; } SignalBorrowedSliceOfConstPointerCiphertextMessage; +/** + * A C callback used to report the results of Rust futures. + * + * cbindgen will produce independent C types like `SignalCPromisei32` and + * `SignalCPromiseProtocolAddress`. + * + * This derives Copy because it behaves like a C type; nevertheless, a promise should still only be + * completed once. + */ +typedef struct { + void (*complete)(SignalFfiError *error, const SignalOwnedBuffer *result, const void *context); + const void *context; + SignalCancellationId cancellation_id; +} SignalCPromiseOwnedBufferOfc_uchar; + /** * A wrapper type for raw UUIDs, because C treats arrays specially in argument position. */ @@ -931,9 +954,9 @@ typedef struct { typedef const SignalFfiError *SignalUnwindSafeArgSignalFfiError; typedef struct { - const char *first; + SignalCStringPtr first; uint32_t second; -} SignalPairOfc_charu32; +} SignalPairOfCStringPtru32; /** * A representation of a array allocated on the Rust heap for use in C code. @@ -965,19 +988,19 @@ typedef struct { } SignalOwnedBufferOfFfiMismatchedDevicesError; typedef struct { - const char *first; + SignalCStringPtr first; SignalOwnedBuffer second; -} SignalPairOfc_charOwnedBufferOfc_uchar; +} SignalPairOfCStringPtrOwnedBufferOfc_uchar; typedef struct { - SignalPairOfc_charOwnedBufferOfc_uchar first; + SignalPairOfCStringPtrOwnedBufferOfc_uchar first; int64_t second; -} SignalPairOfPairOfc_charOwnedBufferOfc_uchari64; +} SignalPairOfPairOfCStringPtrOwnedBufferOfc_uchari64; typedef struct { - const char *first; + SignalCStringPtr first; bool second; -} SignalPairOfc_charbool; +} SignalPairOfCStringPtrbool; typedef struct { SignalFingerprint *raw; @@ -1102,7 +1125,7 @@ typedef struct { SignalIncrementalMac *raw; } SignalMutPointerIncrementalMac; -typedef int (*SignalFfiLoggerLog)(void *ctx, SignalLogLevel level, const char *file, uint32_t line, const char *message); +typedef int (*SignalFfiLoggerLog)(void *ctx, SignalLogLevel level, SignalCStringPtr file, uint32_t line, SignalCStringPtr message); typedef int (*SignalFfiLoggerFlush)(void *ctx); @@ -1203,18 +1226,20 @@ typedef struct { const SignalMessageBackupValidationOutcome *raw; } SignalConstPointerMessageBackupValidationOutcome; -typedef int (*SignalFfiInputStreamRead)(void *ctx, size_t *out, SignalBorrowedMutableBuffer buf); +typedef int (*SignalFfiSyncInputStreamRead)(void *ctx, size_t *out, SignalBorrowedMutableBuffer buf); -typedef int (*SignalFfiInputStreamSkip)(void *ctx, uint64_t amount); +typedef int (*SignalFfiSyncInputStreamSkip)(void *ctx, uint64_t amount); -typedef void (*SignalFfiInputStreamDestroy)(void *ctx); +typedef void (*SignalFfiSyncInputStreamDestroy)(void *ctx); typedef struct { void *ctx; - SignalFfiInputStreamRead read; - SignalFfiInputStreamSkip skip; - SignalFfiInputStreamDestroy destroy; -} SignalInputStream; + SignalFfiSyncInputStreamRead read; + SignalFfiSyncInputStreamSkip skip; + SignalFfiSyncInputStreamDestroy destroy; +} SignalSyncInputStream; + +typedef SignalSyncInputStream SignalInputStream; typedef struct { const SignalInputStream *raw; @@ -1283,7 +1308,7 @@ typedef struct { const SignalProvisioningChatConnection *raw; } SignalConstPointerProvisioningChatConnection; -typedef int (*SignalFfiProvisioningListenerReceivedAddress)(void *ctx, const char *address, SignalMutPointerServerMessageAck send_ack); +typedef int (*SignalFfiProvisioningListenerReceivedAddress)(void *ctx, SignalCStringPtr address, SignalMutPointerServerMessageAck send_ack); typedef int (*SignalFfiProvisioningListenerReceivedEnvelope)(void *ctx, SignalOwnedBuffer envelope, SignalMutPointerServerMessageAck send_ack); @@ -1554,6 +1579,46 @@ typedef struct { SignalTokioAsyncContext *raw; } SignalMutPointerTokioAsyncContext; +typedef struct { + SignalOwnedBufferOfCStringPtr first; + SignalOwnedBufferOfCStringPtr second; +} SignalPairOfOwnedBufferOfCStringPtrOwnedBufferOfCStringPtr; + +/** + * A C callback used to report the results of Rust futures. + * + * cbindgen will produce independent C types like `SignalCPromisei32` and + * `SignalCPromiseProtocolAddress`. + * + * This derives Copy because it behaves like a C type; nevertheless, a promise should still only be + * completed once. + */ +typedef struct { + void (*complete)(SignalFfiError *error, const SignalPairOfOwnedBufferOfCStringPtrOwnedBufferOfCStringPtr *result, const void *context); + const void *context; + SignalCancellationId cancellation_id; +} SignalCPromisePairOfOwnedBufferOfCStringPtrOwnedBufferOfCStringPtr; + +typedef struct { + SignalCStringPtr first; + SignalCStringPtr second; +} SignalPairOfCStringPtrCStringPtr; + +/** + * A C callback used to report the results of Rust futures. + * + * cbindgen will produce independent C types like `SignalCPromisei32` and + * `SignalCPromiseProtocolAddress`. + * + * This derives Copy because it behaves like a C type; nevertheless, a promise should still only be + * completed once. + */ +typedef struct { + void (*complete)(SignalFfiError *error, const SignalPairOfCStringPtrCStringPtr *result, const void *context); + const void *context; + SignalCancellationId cancellation_id; +} SignalCPromisePairOfCStringPtrCStringPtr; + typedef struct { SignalUnauthenticatedChatConnection *raw; } SignalMutPointerUnauthenticatedChatConnection; @@ -1610,9 +1675,9 @@ typedef struct { typedef struct { bool present; - const char *first; + SignalCStringPtr first; uint8_t second[32]; -} SignalOptionalPairOfc_charu832; +} SignalOptionalPairOfCStringPtru832; /** * A C callback used to report the results of Rust futures. @@ -1624,10 +1689,10 @@ typedef struct { * completed once. */ typedef struct { - void (*complete)(SignalFfiError *error, const SignalOptionalPairOfc_charu832 *result, const void *context); + void (*complete)(SignalFfiError *error, const SignalOptionalPairOfCStringPtru832 *result, const void *context); const void *context; SignalCancellationId cancellation_id; -} SignalCPromiseOptionalPairOfc_charu832; +} SignalCPromiseOptionalPairOfCStringPtru832; /** * A C callback used to report the results of Rust futures. @@ -1648,8 +1713,6 @@ typedef struct { SignalValidatingMac *raw; } SignalMutPointerValidatingMac; -typedef SignalInputStream SignalSyncInputStream; - typedef struct { const SignalSyncInputStream *raw; } SignalConstPointerFfiSyncInputStreamStruct; @@ -1664,7 +1727,7 @@ SignalFfiError *signal_account_entropy_pool_derive_backup_key(uint8_t (*out)[Sig SignalFfiError *signal_account_entropy_pool_derive_svr_key(uint8_t (*out)[SignalSVR_KEY_LEN], const char *account_entropy); -SignalFfiError *signal_account_entropy_pool_generate(const char **out); +SignalFfiError *signal_account_entropy_pool_generate(SignalCStringPtr *out); SignalFfiError *signal_account_entropy_pool_is_valid(bool *out, const char *account_entropy); @@ -1674,7 +1737,7 @@ SignalFfiError *signal_address_destroy(SignalMutPointerProtocolAddress p); SignalFfiError *signal_address_get_device_id(uint32_t *out, SignalConstPointerProtocolAddress obj); -SignalFfiError *signal_address_get_name(const char **out, SignalConstPointerProtocolAddress obj); +SignalFfiError *signal_address_get_name(SignalCStringPtr *out, SignalConstPointerProtocolAddress obj); SignalFfiError *signal_address_new(SignalMutPointerProtocolAddress *out, const char *name, uint32_t device_id); @@ -1738,6 +1801,8 @@ SignalFfiError *signal_authenticated_chat_connection_send(SignalCPromiseFfiChatR SignalFfiError *signal_authenticated_chat_connection_send_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *destination, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfConstPointerCiphertextMessage contents, bool online_only, bool is_urgent); +SignalFfiError *signal_authenticated_chat_connection_send_raw_grpc(SignalCPromiseOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, const char *service, const char *method, SignalBorrowedBuffer payload); + SignalFfiError *signal_authenticated_chat_connection_send_sync_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfConstPointerCiphertextMessage contents, bool is_urgent); SignalFfiError *signal_backup_auth_credential_check_valid_contents(SignalBorrowedBuffer params_bytes); @@ -1840,7 +1905,7 @@ SignalFfiError *signal_cdsi_lookup_new(SignalCPromiseMutPointerCdsiLookup *promi SignalFfiError *signal_cdsi_lookup_token(SignalOwnedBuffer *out, SignalConstPointerCdsiLookup lookup); -SignalFfiError *signal_chat_connection_info_description(const char **out, SignalConstPointerChatConnectionInfo connection_info); +SignalFfiError *signal_chat_connection_info_description(SignalCStringPtr *out, SignalConstPointerChatConnectionInfo connection_info); SignalFfiError *signal_chat_connection_info_ip_version(uint8_t *out, SignalConstPointerChatConnectionInfo connection_info); @@ -1934,17 +1999,17 @@ void signal_error_free(SignalFfiError *err); SignalFfiError *signal_error_get_address(SignalMutPointerProtocolAddress *out, SignalUnwindSafeArgSignalFfiError err); -SignalFfiError *signal_error_get_invalid_protocol_address(SignalPairOfc_charu32 *out, SignalUnwindSafeArgSignalFfiError err); +SignalFfiError *signal_error_get_invalid_protocol_address(SignalPairOfCStringPtru32 *out, SignalUnwindSafeArgSignalFfiError err); -SignalFfiError *signal_error_get_message(const char **out, SignalUnwindSafeArgSignalFfiError err); +SignalFfiError *signal_error_get_message(SignalCStringPtr *out, SignalUnwindSafeArgSignalFfiError err); SignalFfiError *signal_error_get_mismatched_device_errors(SignalOwnedBufferOfFfiMismatchedDevicesError *out, SignalUnwindSafeArgSignalFfiError err); SignalFfiError *signal_error_get_our_fingerprint_version(uint32_t *out, SignalUnwindSafeArgSignalFfiError err); -SignalFfiError *signal_error_get_rate_limit_challenge(SignalPairOfPairOfc_charOwnedBufferOfc_uchari64 *out, SignalUnwindSafeArgSignalFfiError err); +SignalFfiError *signal_error_get_rate_limit_challenge(SignalPairOfPairOfCStringPtrOwnedBufferOfc_uchari64 *out, SignalUnwindSafeArgSignalFfiError err); -SignalFfiError *signal_error_get_registration_error_not_deliverable(SignalPairOfc_charbool *out, SignalUnwindSafeArgSignalFfiError err); +SignalFfiError *signal_error_get_registration_error_not_deliverable(SignalPairOfCStringPtrbool *out, SignalUnwindSafeArgSignalFfiError err); SignalFfiError *signal_error_get_registration_lock(uint64_t *out_time_remaining_seconds, const char **out_svr2_username, const char **out_svr2_password, const SignalFfiError *err); @@ -1972,7 +2037,7 @@ SignalFfiError *signal_fingerprint_compare(bool *out, SignalBorrowedBuffer fprin SignalFfiError *signal_fingerprint_destroy(SignalMutPointerFingerprint p); -SignalFfiError *signal_fingerprint_display_string(const char **out, SignalConstPointerFingerprint obj); +SignalFfiError *signal_fingerprint_display_string(SignalCStringPtr *out, SignalConstPointerFingerprint obj); SignalFfiError *signal_fingerprint_new(SignalMutPointerFingerprint *out, uint32_t iterations, uint32_t version, SignalBorrowedBuffer local_identifier, SignalConstPointerPublicKey local_key, SignalBorrowedBuffer remote_identifier, SignalConstPointerPublicKey remote_key); @@ -2125,6 +2190,8 @@ SignalFfiError *signal_key_transparency_check(SignalCPromisePairOfOwnedBufferOfc SignalFfiError *signal_key_transparency_e164_search_key(SignalOwnedBuffer *out, const char *e164); +SignalFfiError *signal_key_transparency_reset_data_field(SignalOwnedBuffer *out, SignalBorrowedBuffer account_data, uint8_t field); + SignalFfiError *signal_key_transparency_username_hash_search_key(SignalOwnedBuffer *out, SignalBorrowedBuffer hash); SignalFfiError *signal_kyber_key_pair_clone(SignalMutPointerKyberKeyPair *new_obj, SignalConstPointerKyberKeyPair obj); @@ -2201,7 +2268,7 @@ SignalFfiError *signal_message_backup_key_get_hmac_key(uint8_t (*out)[32], Signa SignalFfiError *signal_message_backup_validation_outcome_destroy(SignalMutPointerMessageBackupValidationOutcome p); -SignalFfiError *signal_message_backup_validation_outcome_get_error_message(const char **out, SignalConstPointerMessageBackupValidationOutcome outcome); +SignalFfiError *signal_message_backup_validation_outcome_get_error_message(SignalCStringPtr *out, SignalConstPointerMessageBackupValidationOutcome outcome); SignalFfiError *signal_message_backup_validation_outcome_get_unknown_fields(SignalStringArray *out, SignalConstPointerMessageBackupValidationOutcome outcome); @@ -2227,8 +2294,6 @@ SignalFfiError *signal_message_get_serialized(SignalOwnedBuffer *out, SignalCons SignalFfiError *signal_message_new(SignalMutPointerSignalMessage *out, uint8_t message_version, SignalBorrowedBuffer mac_key, SignalConstPointerPublicKey sender_ratchet_key, uint32_t counter, uint32_t previous_counter, SignalBorrowedBuffer ciphertext, SignalConstPointerPublicKey sender_identity_key, SignalConstPointerPublicKey receiver_identity_key, SignalBorrowedBuffer pq_ratchet); -SignalFfiError *signal_message_verify_mac(bool *out, SignalConstPointerSignalMessage msg, SignalConstPointerPublicKey sender_identity_key, SignalConstPointerPublicKey receiver_identity_key, SignalBorrowedBuffer mac_key); - SignalFfiError *signal_mp4_sanitizer_sanitize(SignalMutPointerSanitizedMetadata *out, SignalConstPointerFfiInputStreamStruct input, uint64_t len); SignalFfiError *signal_online_backup_validator_add_frame(SignalMutPointerOnlineBackupValidator backup, SignalBorrowedBuffer frame); @@ -2251,7 +2316,7 @@ SignalFfiError *signal_pin_hash_from_salt(SignalMutPointerPinHash *out, SignalBo SignalFfiError *signal_pin_hash_from_username_mrenclave(SignalMutPointerPinHash *out, SignalBorrowedBuffer pin, const char *username, SignalBorrowedBuffer mrenclave); -SignalFfiError *signal_pin_local_hash(const char **out, SignalBorrowedBuffer pin); +SignalFfiError *signal_pin_local_hash(SignalCStringPtr *out, SignalBorrowedBuffer pin); SignalFfiError *signal_pin_verify_local_hash(bool *out, const char *encoded_hash, SignalBorrowedBuffer pin); @@ -2457,7 +2522,7 @@ SignalFfiError *signal_register_account_response_get_entitlement_badges(SignalOw SignalFfiError *signal_register_account_response_get_identity(SignalServiceIdFixedWidthBinaryBytes *out, SignalConstPointerRegisterAccountResponse response, uint8_t identity_type); -SignalFfiError *signal_register_account_response_get_number(const char **out, SignalConstPointerRegisterAccountResponse response); +SignalFfiError *signal_register_account_response_get_number(SignalCStringPtr *out, SignalConstPointerRegisterAccountResponse response); SignalFfiError *signal_register_account_response_get_reregistration(bool *out, SignalConstPointerRegisterAccountResponse response); @@ -2489,7 +2554,7 @@ SignalFfiError *signal_registration_service_reregister_account(SignalCPromiseMut SignalFfiError *signal_registration_service_resume_session(SignalCPromiseMutPointerRegistrationService *promise, SignalConstPointerTokioAsyncContext async_runtime, const char *session_id, const char *number, SignalConstPointerFfiConnectChatBridgeStruct connect_chat); -SignalFfiError *signal_registration_service_session_id(const char **out, SignalConstPointerRegistrationService service); +SignalFfiError *signal_registration_service_session_id(SignalCStringPtr *out, SignalConstPointerRegistrationService service); SignalFfiError *signal_registration_service_submit_captcha(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerRegistrationService service, const char *captcha_value); @@ -2551,9 +2616,9 @@ SignalFfiError *signal_sender_certificate_get_expiration(uint64_t *out, SignalCo SignalFfiError *signal_sender_certificate_get_key(SignalMutPointerPublicKey *out, SignalConstPointerSenderCertificate obj); -SignalFfiError *signal_sender_certificate_get_sender_e164(const char **out, SignalConstPointerSenderCertificate obj); +SignalFfiError *signal_sender_certificate_get_sender_e164(SignalCStringPtr *out, SignalConstPointerSenderCertificate obj); -SignalFfiError *signal_sender_certificate_get_sender_uuid(const char **out, SignalConstPointerSenderCertificate obj); +SignalFfiError *signal_sender_certificate_get_sender_uuid(SignalCStringPtr *out, SignalConstPointerSenderCertificate obj); SignalFfiError *signal_sender_certificate_get_serialized(SignalOwnedBuffer *out, SignalConstPointerSenderCertificate obj); @@ -2693,9 +2758,9 @@ SignalFfiError *signal_service_id_parse_from_service_id_string(SignalServiceIdFi SignalFfiError *signal_service_id_service_id_binary(SignalOwnedBuffer *out, const SignalServiceIdFixedWidthBinaryBytes *value); -SignalFfiError *signal_service_id_service_id_log(const char **out, const SignalServiceIdFixedWidthBinaryBytes *value); +SignalFfiError *signal_service_id_service_id_log(SignalCStringPtr *out, const SignalServiceIdFixedWidthBinaryBytes *value); -SignalFfiError *signal_service_id_service_id_string(const char **out, const SignalServiceIdFixedWidthBinaryBytes *value); +SignalFfiError *signal_service_id_service_id_string(SignalCStringPtr *out, const SignalServiceIdFixedWidthBinaryBytes *value); SignalFfiError *signal_session_record_archive_current_state(SignalMutPointerSessionRecord session_record); @@ -2711,7 +2776,7 @@ SignalFfiError *signal_session_record_get_local_registration_id(uint32_t *out, S SignalFfiError *signal_session_record_get_remote_registration_id(uint32_t *out, SignalConstPointerSessionRecord obj); -SignalFfiError *signal_session_record_has_usable_sender_chain(bool *out, SignalConstPointerSessionRecord s, uint64_t now); +SignalFfiError *signal_session_record_has_usable_sender_chain(bool *out, SignalConstPointerSessionRecord s, double require_pq_ratio, uint64_t now); SignalFfiError *signal_session_record_serialize(SignalOwnedBuffer *out, SignalConstPointerSessionRecord obj); @@ -2757,10 +2822,20 @@ SignalFfiError *signal_tokio_async_context_new(SignalMutPointerTokioAsyncContext SignalFfiError *signal_unauthenticated_chat_connection_account_exists(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const SignalServiceIdFixedWidthBinaryBytes *account); +SignalFfiError *signal_unauthenticated_chat_connection_backup_delete_all(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, int64_t rng); + +SignalFfiError *signal_unauthenticated_chat_connection_backup_get_cdn_credentials(SignalCPromisePairOfOwnedBufferOfCStringPtrOwnedBufferOfCStringPtr *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, int32_t cdn, int64_t rng); + SignalFfiError *signal_unauthenticated_chat_connection_backup_get_media_upload_form(SignalCPromiseFfiUploadForm *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, uint64_t upload_size, int64_t rng); +SignalFfiError *signal_unauthenticated_chat_connection_backup_get_svrb_credentials(SignalCPromisePairOfCStringPtrCStringPtr *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, int64_t rng); + SignalFfiError *signal_unauthenticated_chat_connection_backup_get_upload_form(SignalCPromiseFfiUploadForm *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, uint64_t upload_size, int64_t rng); +SignalFfiError *signal_unauthenticated_chat_connection_backup_refresh(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, int64_t rng); + +SignalFfiError *signal_unauthenticated_chat_connection_backup_set_public_key(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer credential, SignalBorrowedBuffer server_keys, SignalConstPointerPrivateKey signing_key, int64_t rng); + SignalFfiError *signal_unauthenticated_chat_connection_connect(SignalCPromiseMutPointerUnauthenticatedChatConnection *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerConnectionManager connection_manager, SignalBorrowedBytestringArray languages); SignalFfiError *signal_unauthenticated_chat_connection_destroy(SignalMutPointerUnauthenticatedChatConnection p); @@ -2779,7 +2854,7 @@ SignalFfiError *signal_unauthenticated_chat_connection_init_listener(SignalConst SignalFfiError *signal_unauthenticated_chat_connection_look_up_username_hash(SignalCPromiseOptionalUuid *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer hash); -SignalFfiError *signal_unauthenticated_chat_connection_look_up_username_link(SignalCPromiseOptionalPairOfc_charu832 *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalUuid uuid, SignalBorrowedBuffer entropy); +SignalFfiError *signal_unauthenticated_chat_connection_look_up_username_link(SignalCPromiseOptionalPairOfCStringPtru832 *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalUuid uuid, SignalBorrowedBuffer entropy); SignalFfiError *signal_unauthenticated_chat_connection_send(SignalCPromiseFfiChatResponse *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalConstPointerHttpRequest http_request, uint32_t timeout_millis); @@ -2787,6 +2862,8 @@ SignalFfiError *signal_unauthenticated_chat_connection_send_message(SignalCPromi SignalFfiError *signal_unauthenticated_chat_connection_send_multi_recipient_message(SignalCPromiseOwnedBufferOfServiceIdFixedWidthBinaryBytes *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, SignalBorrowedBuffer payload, uint64_t timestamp, SignalBorrowedBuffer auth, bool online_only, bool is_urgent); +SignalFfiError *signal_unauthenticated_chat_connection_send_raw_grpc(SignalCPromiseOwnedBufferOfc_uchar *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerUnauthenticatedChatConnection chat, const char *service, const char *method, SignalBorrowedBuffer payload); + SignalFfiError *signal_unidentified_sender_message_content_deserialize(SignalMutPointerUnidentifiedSenderMessageContent *out, SignalBorrowedBuffer data); SignalFfiError *signal_unidentified_sender_message_content_destroy(SignalMutPointerUnidentifiedSenderMessageContent p); @@ -2815,7 +2892,7 @@ SignalFfiError *signal_username_hash_from_parts(uint8_t (*out)[32], const char * SignalFfiError *signal_username_link_create(SignalOwnedBuffer *out, const char *username, SignalBorrowedBuffer entropy); -SignalFfiError *signal_username_link_decrypt_username(const char **out, SignalBorrowedBuffer entropy, SignalBorrowedBuffer encrypted_username); +SignalFfiError *signal_username_link_decrypt_username(SignalCStringPtr *out, SignalBorrowedBuffer entropy, SignalBorrowedBuffer encrypted_username); SignalFfiError *signal_username_proof(SignalOwnedBuffer *out, const char *username, const uint8_t (*randomness)[32]); diff --git a/pkg/libsignalgo/logging.go b/pkg/libsignalgo/logging.go index 1926c23..59a9ab7 100644 --- a/pkg/libsignalgo/logging.go +++ b/pkg/libsignalgo/logging.go @@ -19,7 +19,7 @@ package libsignalgo /* #include <./libsignal-ffi.h> -extern void signal_log_callback(void *ctx, SignalLogLevel level, char *file, uint32_t line, char *message); +extern void signal_log_callback(void *ctx, SignalLogLevel level, SignalCStringPtr file, uint32_t line, SignalCStringPtr message); extern void signal_log_flush_callback(void *ctx); extern void signal_log_destroy_callback(void *ctx); */ @@ -32,7 +32,7 @@ import ( var ffiLogger Logger //export signal_log_callback -func signal_log_callback(ctx unsafe.Pointer, level C.SignalLogLevel, file *C.char, line C.uint32_t, message *C.char) { +func signal_log_callback(ctx unsafe.Pointer, level C.SignalLogLevel, file C.SignalCStringPtr, line C.uint32_t, message C.SignalCStringPtr) { ffiLogger.Log(LogLevel(int(level)), C.GoString(file), uint(line), C.GoString(message)) } diff --git a/pkg/libsignalgo/message.go b/pkg/libsignalgo/message.go index 6cba873..b781eaf 100644 --- a/pkg/libsignalgo/message.go +++ b/pkg/libsignalgo/message.go @@ -156,22 +156,3 @@ func (m *Message) GetCounter() (uint32, error) { } return uint32(counter), nil } - -func (m *Message) VerifyMAC(sender, receiver *PublicKey, macKey []byte) (bool, error) { - var result C.bool - signalFfiError := C.signal_message_verify_mac( - &result, - m.constPtr(), - sender.constPtr(), - receiver.constPtr(), - BytesToBuffer(macKey), - ) - runtime.KeepAlive(m) - runtime.KeepAlive(sender) - runtime.KeepAlive(receiver) - runtime.KeepAlive(macKey) - if signalFfiError != nil { - return false, wrapError(signalFfiError) - } - return bool(result), nil -} diff --git a/pkg/libsignalgo/sendercertificate.go b/pkg/libsignalgo/sendercertificate.go index 47cf958..eb71d1a 100644 --- a/pkg/libsignalgo/sendercertificate.go +++ b/pkg/libsignalgo/sendercertificate.go @@ -135,7 +135,7 @@ func (sc *SenderCertificate) GetSignature() ([]byte, error) { } func (sc *SenderCertificate) GetSenderUUID() (uuid.UUID, error) { - var rawUUID *C.char + var rawUUID C.SignalCStringPtr signalFfiError := C.signal_sender_certificate_get_sender_uuid(&rawUUID, sc.constPtr()) runtime.KeepAlive(sc) if signalFfiError != nil { @@ -145,7 +145,7 @@ func (sc *SenderCertificate) GetSenderUUID() (uuid.UUID, error) { } func (sc *SenderCertificate) GetSenderE164() (string, error) { - var e164 *C.char + var e164 C.SignalCStringPtr signalFfiError := C.signal_sender_certificate_get_sender_e164(&e164, sc.constPtr()) runtime.KeepAlive(sc) if signalFfiError != nil { diff --git a/pkg/libsignalgo/sessionrecord.go b/pkg/libsignalgo/sessionrecord.go index b4f2afb..fddff28 100644 --- a/pkg/libsignalgo/sessionrecord.go +++ b/pkg/libsignalgo/sessionrecord.go @@ -105,6 +105,7 @@ func (sr *SessionRecord) HasCurrentState() (bool, error) { signalFfiError := C.signal_session_record_has_usable_sender_chain( &result, sr.constPtr(), + C.double(0.0), C.uint64_t(time.Now().Unix()), ) runtime.KeepAlive(sr) diff --git a/pkg/libsignalgo/version.go b/pkg/libsignalgo/version.go index 1f7e94d..c5037df 100644 --- a/pkg/libsignalgo/version.go +++ b/pkg/libsignalgo/version.go @@ -2,4 +2,4 @@ package libsignalgo -const Version = "v0.93.2" +const Version = "v0.94.4" From fe3a952c2f231dbc5ca9816be345dce1c54f2f34 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 5 Jun 2026 00:22:54 +0300 Subject: [PATCH 27/34] signalmeow/sending: remove unnecessary log context propagation --- pkg/signalmeow/sending.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/signalmeow/sending.go b/pkg/signalmeow/sending.go index a485b54..756e673 100644 --- a/pkg/signalmeow/sending.go +++ b/pkg/signalmeow/sending.go @@ -960,7 +960,6 @@ func (cli *Client) sendContent( Uint64("response_id", *response.Id). Uint32("response_status", *response.Status). Logger() - ctx = log.WithContext(ctx) if json.Valid(response.GetBody()) { log.Debug().RawJSON("response_body", response.GetBody()).Msg("DEBUG: message send response data") } else { From 2a8769e32a850ce5ac62329eb2f19adfc9cbf886 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 9 Jun 2026 17:10:26 +0300 Subject: [PATCH 28/34] signalmeow/receiving: check handler success before deleting buffered plaintext --- pkg/signalmeow/receiving.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/signalmeow/receiving.go b/pkg/signalmeow/receiving.go index 6b92d04..e592c98 100644 --- a/pkg/signalmeow/receiving.go +++ b/pkg/signalmeow/receiving.go @@ -414,8 +414,12 @@ func (cli *Client) handleDecryptedResult( return ctx.Err() } log := zerolog.Ctx(ctx) - if result.CiphertextHash != nil { - defer func() { + handlerSuccess := true + defer func() { + if retErr == nil && !handlerSuccess { + retErr = ErrHandlerFailed + } + if result.CiphertextHash != nil && handlerSuccess { err := cli.Store.EventBuffer.ClearBufferedEventPlaintext(ctx, *result.CiphertextHash) if err != nil { log.Err(err). @@ -426,8 +430,10 @@ func (cli *Client) handleDecryptedResult( Hex("ciphertext_hash", result.CiphertextHash[:]). Msg("Deleted event plaintext from buffer") } - }() - } + } else if result.CiphertextHash != nil { + log.Warn().Msg("Not clearing buffered event plaintext due to handler failure") + } + }() var theirServiceID libsignalgo.ServiceID var err error @@ -455,12 +461,6 @@ func (cli *Client) handleDecryptedResult( } cli.Store.RecipientStore.MarkUnregistered(ctx, theirServiceID, false) - handlerSuccess := true - defer func() { - if retErr == nil && !handlerSuccess { - retErr = ErrHandlerFailed - } - }() // result.Err is set if there was an error during decryption and we // should notifiy the user that the message could not be decrypted if result.Err != nil { From 605693e29480b0b48b4c5f716d4081ea780830f9 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 9 Jun 2026 17:10:51 +0300 Subject: [PATCH 29/34] handlematrix: auto-join ghost after knock accept --- pkg/connector/handlematrix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/connector/handlematrix.go b/pkg/connector/handlematrix.go index 7bcb214..82f005c 100644 --- a/pkg/connector/handlematrix.go +++ b/pkg/connector/handlematrix.go @@ -538,7 +538,7 @@ func (s *SignalClient) HandleMatrixMembership(ctx context.Context, msg *bridgev2 if err != nil { return nil, err } - if msg.Type == bridgev2.Invite && targetSignalID.Type != libsignalgo.ServiceIDTypePNI { + if (msg.Type == bridgev2.Invite || msg.Type == bridgev2.AcceptKnock) && targetSignalID.Type != libsignalgo.ServiceIDTypePNI { err = targetIntent.EnsureJoined(ctx, msg.Portal.MXID) if err != nil { return nil, err From 316e7b311dde90aec43e7b069bd52f93c70ede16 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 16 Jun 2026 15:13:03 +0300 Subject: [PATCH 30/34] Bump version to v26.06 --- CHANGELOG.md | 6 ++++++ cmd/mautrix-signal/main.go | 2 +- go.mod | 24 ++++++++++----------- go.sum | 44 +++++++++++++++++++------------------- 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ff5d36..c75bcab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v26.06 + +* Updated libsignal to v0.94.4 +* Updated mrenclave to fix looking up phone numbers. +* Changed knock accept handling to auto-join the ghost user afterwards. + # v26.05 * Updated libsignal to v0.93.2. diff --git a/cmd/mautrix-signal/main.go b/cmd/mautrix-signal/main.go index 684c1e4..3f83a28 100644 --- a/cmd/mautrix-signal/main.go +++ b/cmd/mautrix-signal/main.go @@ -37,7 +37,7 @@ var m = mxmain.BridgeMain{ Name: "mautrix-signal", URL: "https://github.com/mautrix/signal", Description: "A Matrix-Signal puppeting bridge.", - Version: "26.05", + Version: "26.06", SemCalVer: true, Connector: &connector.SignalConnector{}, diff --git a/go.mod b/go.mod index 13cb3b7..1538759 100644 --- a/go.mod +++ b/go.mod @@ -2,26 +2,26 @@ module go.mau.fi/mautrix-signal go 1.25.0 -toolchain go1.26.3 +toolchain go1.26.4 tool go.mau.fi/util/cmd/maubuild require ( - github.com/coder/websocket v1.8.14 + github.com/coder/websocket v1.8.15 github.com/emersion/go-vcard v0.0.0-20241024213814-c9703dde27ff github.com/google/uuid v1.6.0 github.com/mattn/go-pointer v0.0.1 github.com/rs/zerolog v1.35.1 github.com/stretchr/testify v1.11.1 github.com/tidwall/gjson v1.19.0 - go.mau.fi/util v0.9.9 - golang.org/x/crypto v0.51.0 - golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a - golang.org/x/net v0.54.0 - golang.org/x/sync v0.20.0 + go.mau.fi/util v0.9.10 + golang.org/x/crypto v0.53.0 + golang.org/x/exp v0.0.0-20260611194520-c48552f49976 + golang.org/x/net v0.56.0 + golang.org/x/sync v0.21.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.28.1-0.20260519145316-34b5f49408a3 + maunium.net/go/mautrix v0.28.1 ) require ( @@ -32,7 +32,7 @@ require ( github.com/lib/pq v1.12.3 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-sqlite3 v1.14.44 // indirect + github.com/mattn/go-sqlite3 v1.14.45 // indirect github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect @@ -43,9 +43,9 @@ require ( github.com/tidwall/sjson v1.2.5 // indirect github.com/yuin/goldmark v1.8.2 // indirect go.mau.fi/zeroconfig v0.2.0 // indirect - golang.org/x/mod v0.36.0 // indirect - golang.org/x/sys v0.44.0 // indirect - golang.org/x/text v0.37.0 // indirect + golang.org/x/mod v0.37.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/text v0.38.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect maunium.net/go/mauflag v1.0.0 // indirect diff --git a/go.sum b/go.sum index b981cb6..cbd9c09 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= +github.com/coder/websocket v1.8.15 h1:6B2JPeOGlpff2Uz6vOEH1Vzpi0iUz20A+lPVhPHtNUA= +github.com/coder/websocket v1.8.15/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -30,8 +30,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= -github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8= -github.com/mattn/go-sqlite3 v1.14.44/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ= +github.com/mattn/go-sqlite3 v1.14.45 h1:6KA/spDguL3KV8rnybG7ezSaE4SeMR3KC9VbUoAQaIk= +github.com/mattn/go-sqlite3 v1.14.45/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ= github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 h1:WDsQxOJDy0N1VRAjXLpi8sCEZRSGarLWQevDxpTBRrM= github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -61,25 +61,25 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -go.mau.fi/util v0.9.9 h1:ujDeXCo07HBor5oQLyO1tHklupmqVmPgasc53d7q/NE= -go.mau.fi/util v0.9.9/go.mod h1:pqt4Vcrt+5gcH/CgrHZg11qSx+b34o6mknGzOEA6waY= +go.mau.fi/util v0.9.10 h1:wzvz5iDHyqDXB8vgisD4d3SzucLXNM3iNY+1O1RoHtg= +go.mau.fi/util v0.9.10/go.mod h1:YQOxySn+ZE3qSYqNxvyX7Yi3suA8YK17PS6QqBREW7A= go.mau.fi/zeroconfig v0.2.0 h1:e/OGEERqVRRKlgaro7E6bh8xXiKFSXB3eNNIud7FUjU= go.mau.fi/zeroconfig v0.2.0/go.mod h1:J0Vn0prHNOm493oZoQ84kq83ZaNCYZnq+noI1b1eN8w= -golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= -golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= -golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a h1:+3jdDGGB8NGb1Zktc737jlt3/A5f6UlwSzmvqUuufxw= -golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw= -golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= -golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= -golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= -golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= +golang.org/x/exp v0.0.0-20260611194520-c48552f49976 h1:X8Hz2ImujgbmetVuW+w2YkyZChE3cBpZi2P158rTG9M= +golang.org/x/exp v0.0.0-20260611194520-c48552f49976/go.mod h1:vnf4pv9iKZXY58sQE1L86zmNWJ4159e1RkcWiLCkeEY= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= -golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -91,5 +91,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.28.1-0.20260519145316-34b5f49408a3 h1:l86igJY8Te5JEBNPL9NSpZaGv6eHsxtCrAabXv8KPJo= -maunium.net/go/mautrix v0.28.1-0.20260519145316-34b5f49408a3/go.mod h1:/a9A7LGaqb9B3nho4tLd28n0EPcCdwpm2dxkxkLLgh0= +maunium.net/go/mautrix v0.28.1 h1:Hic3oDMPbLbQu1fhboTRAKZcORMjzzkjxsa+SGk60b0= +maunium.net/go/mautrix v0.28.1/go.mod h1:mWXQNmOlrq4VTDU9f1HO03BSIswdUIyyY4wUKHqwzzY= From 8217fb9e42f0b4ebd30eae1f296fedf83eb0af85 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 21 Jun 2026 20:12:32 +0300 Subject: [PATCH 31/34] signalmeow/provisioning: update capabilities --- pkg/signalmeow/provisioning.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/signalmeow/provisioning.go b/pkg/signalmeow/provisioning.go index 8e0fa96..787e2d8 100644 --- a/pkg/signalmeow/provisioning.go +++ b/pkg/signalmeow/provisioning.go @@ -268,7 +268,7 @@ func startProvisioning(ctx context.Context, ws *websocket.Conn, provisioningCiph return "", fmt.Errorf("failed to unmarshal provisioning UUID: %w", err) } - linkCapabilities := []string{"backup4,backup5"} + linkCapabilities := []string{"backup5"} if !allowBackup { linkCapabilities = []string{} } @@ -328,8 +328,9 @@ func continueProvisioning(ctx context.Context, ws *websocket.Conn, provisioningC } var signalCapabilities = map[string]any{ - "attachmentBackfill": true, - "spqr": true, + "attachmentBackfill": true, + "spqr": true, + "usernameChangeSyncMessage": true, } var signalCapabilitiesBody = exerrors.Must(json.Marshal(signalCapabilities)) From facfe86a50f97adf9bd42398beed2b7b002c4fb6 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 21 Jun 2026 20:17:04 +0300 Subject: [PATCH 32/34] libsignal: update to v0.96.2 --- pkg/libsignalgo/libsignal | 2 +- pkg/libsignalgo/libsignal-ffi.h | 86 ++++++++++++++++++++++++++++++--- pkg/libsignalgo/version.go | 2 +- 3 files changed, 80 insertions(+), 10 deletions(-) diff --git a/pkg/libsignalgo/libsignal b/pkg/libsignalgo/libsignal index 46d867c..38428a7 160000 --- a/pkg/libsignalgo/libsignal +++ b/pkg/libsignalgo/libsignal @@ -1 +1 @@ -Subproject commit 46d867c986f66201e34e7ae20ce423eec742bf3f +Subproject commit 38428a7bb70509910d72b3f78208c1daf33774d8 diff --git a/pkg/libsignalgo/libsignal-ffi.h b/pkg/libsignalgo/libsignal-ffi.h index 27ac1f3..b17e10f 100644 --- a/pkg/libsignalgo/libsignal-ffi.h +++ b/pkg/libsignalgo/libsignal-ffi.h @@ -948,6 +948,14 @@ typedef struct { const SignalDecryptionErrorMessage *raw; } SignalConstPointerDecryptionErrorMessage; +typedef struct { + const SignalServerSecretParams *raw; +} SignalConstPointerServerSecretParams; + +typedef struct { + const SignalServerPublicParams *raw; +} SignalConstPointerServerPublicParams; + /** * Like [`std::panic::AssertUnwindSafe`], but FFI-compatible. */ @@ -1087,19 +1095,11 @@ typedef struct { const SignalSenderKeyStore *raw; } SignalConstPointerFfiSenderKeyStoreStruct; -typedef struct { - const SignalServerSecretParams *raw; -} SignalConstPointerServerSecretParams; - typedef struct { const SignalBorrowedBuffer *base; size_t length; } SignalBorrowedSliceOfBuffers; -typedef struct { - const SignalServerPublicParams *raw; -} SignalConstPointerServerPublicParams; - typedef struct { SignalHsmEnclaveClient *raw; } SignalMutPointerHsmEnclaveClient; @@ -1805,6 +1805,36 @@ SignalFfiError *signal_authenticated_chat_connection_send_raw_grpc(SignalCPromis SignalFfiError *signal_authenticated_chat_connection_send_sync_message(SignalCPromisebool *promise, SignalConstPointerTokioAsyncContext async_runtime, SignalConstPointerAuthenticatedChatConnection chat, uint64_t timestamp, SignalBorrowedSliceOfu32 device_ids, SignalBorrowedSliceOfu32 registration_ids, SignalBorrowedSliceOfConstPointerCiphertextMessage contents, bool is_urgent); +SignalFfiError *signal_avatar_upload_credential_check_valid_contents(SignalBorrowedBuffer credential_bytes); + +SignalFfiError *signal_avatar_upload_credential_get_cm(uint8_t (*out)[32], SignalBorrowedBuffer credential_bytes); + +SignalFfiError *signal_avatar_upload_credential_get_redemption_time(uint64_t *out, SignalBorrowedBuffer credential_bytes); + +SignalFfiError *signal_avatar_upload_credential_present_deterministic(SignalOwnedBuffer *out, SignalBorrowedBuffer credential_bytes, SignalBorrowedBuffer server_params_bytes, const uint8_t (*randomness)[SignalRANDOMNESS_LEN]); + +SignalFfiError *signal_avatar_upload_credential_presentation_check_valid_contents(SignalBorrowedBuffer presentation_bytes); + +SignalFfiError *signal_avatar_upload_credential_presentation_get_cm(uint8_t (*out)[32], SignalBorrowedBuffer presentation_bytes); + +SignalFfiError *signal_avatar_upload_credential_presentation_get_redemption_time(uint64_t *out, SignalBorrowedBuffer presentation_bytes); + +SignalFfiError *signal_avatar_upload_credential_presentation_verify(SignalBorrowedBuffer presentation_bytes, uint64_t current_time, SignalBorrowedBuffer server_params_bytes); + +SignalFfiError *signal_avatar_upload_credential_request_check_valid_contents(SignalBorrowedBuffer request_bytes); + +SignalFfiError *signal_avatar_upload_credential_request_context_check_valid_contents(SignalBorrowedBuffer context_bytes); + +SignalFfiError *signal_avatar_upload_credential_request_context_get_request(SignalOwnedBuffer *out, SignalBorrowedBuffer context_bytes); + +SignalFfiError *signal_avatar_upload_credential_request_context_new(SignalOwnedBuffer *out, const SignalServiceIdFixedWidthBinaryBytes *aci, SignalBorrowedBuffer zk_credential_key_pair_bytes, uint64_t rotation_id, const uint8_t (*randomness)[SignalRANDOMNESS_LEN]); + +SignalFfiError *signal_avatar_upload_credential_request_context_receive_response(SignalOwnedBuffer *out, SignalBorrowedBuffer context_bytes, SignalBorrowedBuffer response_bytes, uint64_t current_time, SignalBorrowedBuffer params_bytes); + +SignalFfiError *signal_avatar_upload_credential_request_issue_deterministic(SignalOwnedBuffer *out, SignalBorrowedBuffer request_bytes, const SignalServiceIdFixedWidthBinaryBytes *aci, SignalBorrowedBuffer zk_credential_key_pub_bytes, uint64_t rotation_id, uint64_t redemption_time, SignalBorrowedBuffer params_bytes, const uint8_t (*randomness)[SignalRANDOMNESS_LEN]); + +SignalFfiError *signal_avatar_upload_credential_response_check_valid_contents(SignalBorrowedBuffer response_bytes); + SignalFfiError *signal_backup_auth_credential_check_valid_contents(SignalBorrowedBuffer params_bytes); SignalFfiError *signal_backup_auth_credential_get_backup_id(uint8_t (*out)[16], SignalBorrowedBuffer credential_bytes); @@ -1993,6 +2023,38 @@ SignalFfiError *signal_device_transfer_generate_private_key(SignalOwnedBuffer *o SignalFfiError *signal_device_transfer_generate_private_key_with_format(SignalOwnedBuffer *out, uint8_t key_format); +SignalFfiError *signal_donation_permit_check_valid_contents(SignalBorrowedBuffer buffer); + +SignalFfiError *signal_donation_permit_derived_key_pair_check_valid_contents(SignalBorrowedBuffer buffer); + +SignalFfiError *signal_donation_permit_derived_key_pair_for_expiration(SignalOwnedBuffer *out, uint64_t timestamp, SignalConstPointerServerSecretParams root); + +SignalFfiError *signal_donation_permit_expiration(uint64_t *out, SignalBorrowedBuffer donation_permit); + +SignalFfiError *signal_donation_permit_request_check_valid_contents(SignalBorrowedBuffer buffer); + +SignalFfiError *signal_donation_permit_request_context_check_valid_contents(SignalBorrowedBuffer buffer); + +SignalFfiError *signal_donation_permit_request_context_new_deterministic(SignalOwnedBuffer *out, int32_t count, const uint8_t (*randomness)[SignalRANDOMNESS_LEN]); + +SignalFfiError *signal_donation_permit_request_context_receive(SignalBytestringArray *out, SignalBorrowedBuffer context, SignalBorrowedBuffer response, SignalConstPointerServerPublicParams public_params, uint64_t now); + +SignalFfiError *signal_donation_permit_request_context_request(SignalOwnedBuffer *out, SignalBorrowedBuffer ctx); + +SignalFfiError *signal_donation_permit_request_len(int32_t *out, SignalBorrowedBuffer donation_permit_request); + +SignalFfiError *signal_donation_permit_response_check_valid_contents(SignalBorrowedBuffer buffer); + +SignalFfiError *signal_donation_permit_response_default_expiration(uint64_t *out, uint64_t current_time); + +SignalFfiError *signal_donation_permit_response_get_expiration(uint64_t *out, SignalBorrowedBuffer response); + +SignalFfiError *signal_donation_permit_response_issue_deterministic(SignalOwnedBuffer *out, SignalBorrowedBuffer request, SignalBorrowedBuffer key_pair, const uint8_t (*seed)[SignalRANDOMNESS_LEN]); + +SignalFfiError *signal_donation_permit_spend_id(SignalOwnedBuffer *out, SignalBorrowedBuffer donation_permit); + +SignalFfiError *signal_donation_permit_verify(SignalBorrowedBuffer permit, uint64_t now, SignalBorrowedBuffer key_pair); + SignalFfiError *signal_encrypt_message(SignalMutPointerCiphertextMessage *out, SignalBorrowedBuffer ptext, SignalConstPointerProtocolAddress protocol_address, SignalConstPointerProtocolAddress local_address, SignalConstPointerFfiSessionStoreStruct session_store, SignalConstPointerFfiIdentityKeyStoreStruct identity_key_store, uint64_t now); void signal_error_free(SignalFfiError *err); @@ -2910,4 +2972,12 @@ SignalFfiError *signal_validating_mac_update(int32_t *out, SignalMutPointerValid SignalFfiError *signal_webp_sanitizer_sanitize(SignalConstPointerFfiSyncInputStreamStruct input); +SignalFfiError *signal_zk_credential_key_pair_check_valid_contents(SignalBorrowedBuffer key_pair_bytes); + +SignalFfiError *signal_zk_credential_key_pair_generate_deterministic(SignalOwnedBuffer *out, const uint8_t (*randomness)[SignalRANDOMNESS_LEN]); + +SignalFfiError *signal_zk_credential_key_pair_get_public_key(SignalOwnedBuffer *out, SignalBorrowedBuffer key_pair_bytes); + +SignalFfiError *signal_zk_credential_public_key_check_valid_contents(SignalBorrowedBuffer public_key_bytes); + #endif /* SIGNAL_FFI_H_ */ diff --git a/pkg/libsignalgo/version.go b/pkg/libsignalgo/version.go index c5037df..0e07549 100644 --- a/pkg/libsignalgo/version.go +++ b/pkg/libsignalgo/version.go @@ -2,4 +2,4 @@ package libsignalgo -const Version = "v0.94.4" +const Version = "v0.96.2" From 8c4d5e1e7c219ed82320bd59fc11c0ea6d877ace Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 2 Jul 2026 16:59:34 +0300 Subject: [PATCH 33/34] signalmeow: simplify some errors --- pkg/connector/chatsync.go | 5 ++++- pkg/signalmeow/groups.go | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/connector/chatsync.go b/pkg/connector/chatsync.go index 636cad7..47963d7 100644 --- a/pkg/connector/chatsync.go +++ b/pkg/connector/chatsync.go @@ -151,7 +151,10 @@ func (s *SignalClient) syncChats(ctx context.Context, cancel context.CancelFunc) groupID := types.GroupIdentifier(base64.StdEncoding.EncodeToString(rawGroupID[:])) groupInfo, err := s.getGroupInfo(ctx, groupID, dest.Group.GetSnapshot().GetVersion(), chat) if err != nil { - zerolog.Ctx(ctx).Err(err).Msg("Failed to get full group info") + zerolog.Ctx(ctx).Err(err). + Uint64("recipient_id", recipient.Id). + Stringer("group_id", groupID). + Msg("Failed to get full group info") continue } resyncEvt.PortalKey = s.makePortalKey(string(groupID)) diff --git a/pkg/signalmeow/groups.go b/pkg/signalmeow/groups.go index 147d63d..f028f2b 100644 --- a/pkg/signalmeow/groups.go +++ b/pkg/signalmeow/groups.go @@ -641,7 +641,7 @@ func (cli *Client) fetchGroupWithMasterKey(ctx context.Context, groupMasterKey t return nil, err } if response.StatusCode != 200 { - return nil, fmt.Errorf("fetchGroupByID SendHTTPRequest bad status: %d", response.StatusCode) + return nil, fmt.Errorf("unexpected response status: %d", response.StatusCode) } return cli.parseGroupResponse(ctx, response, groupMasterKey) } @@ -1780,7 +1780,7 @@ func (cli *Client) GetGroupHistoryPage(ctx context.Context, gid types.GroupIdent return nil, err } if response.StatusCode != 200 { - return nil, fmt.Errorf("fetchGroupByID SendHTTPRequest bad status: %d", response.StatusCode) + return nil, fmt.Errorf("unexpected response status: %d", response.StatusCode) } var encryptedGroupChanges signalpb.GroupChanges groupChangesBytes, err := io.ReadAll(response.Body) From 3e7a2287ee46930a7933918ce93da3a2aca86a1c Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 2 Jul 2026 16:59:56 +0300 Subject: [PATCH 34/34] signalmeow: retry sender key sends on session not found error --- pkg/signalmeow/senderkey.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/signalmeow/senderkey.go b/pkg/signalmeow/senderkey.go index 48a3203..93f11d9 100644 --- a/pkg/signalmeow/senderkey.go +++ b/pkg/signalmeow/senderkey.go @@ -180,6 +180,13 @@ func (cli *Client) sendToGroupWithSenderKey( } ssCiphertext, err := cli.encryptWithSenderKey(ctx, groupID, ski.DistributionID, myAddress, senderKeyRecipients, content) if err != nil { + if errors.Is(err, libsignalgo.ErrorCodeSessionNotFound) { + log.Warn().Err(err).Msg("Got session not found error for group send from libsignal, resetting session and retrying") + if err = cli.Store.SenderKeyStore.DeleteSenderKeyInfo(ctx, groupIDStr); err != nil { + return nil, fmt.Errorf("failed to delete sender key info: %w", err) + } + return cli.sendToGroupWithSenderKey(ctx, groupID, allRecipients, sec, content, messageTimestamp, retries+1) + } return nil, err } for recipientID := range ski.SharedWith {