From 43bf8045156686ce7a6d95aa03e045afc8590e9b Mon Sep 17 00:00:00 2001 From: saces Date: Tue, 28 Apr 2026 18:46:20 +0200 Subject: [PATCH] api: add self sign endpoint --- libmxclient/mxclient/client.go | 51 ++++++++++++++++++++++++++++++++++ libmxclient/mxclientlib.go | 10 +++++++ pygomx/build_ffi.py | 1 + pygomx/libmxclient.def | 1 + pygomx/src/pygomx/apiv0.py | 4 +++ 5 files changed, 67 insertions(+) diff --git a/libmxclient/mxclient/client.go b/libmxclient/mxclient/client.go index 0a05680..8f7de4e 100644 --- a/libmxclient/mxclient/client.go +++ b/libmxclient/mxclient/client.go @@ -232,6 +232,57 @@ func (mxc *MXClient) SendRoomMessage(ctx context.Context, data string) (*mautrix } +func (mxc *MXClient) SelfSign(ctx context.Context) error { + + log := zerolog.Ctx(ctx) + + helper := mxc.Crypto.(*cryptohelper.CryptoHelper) + + mach := helper.Machine() + + hasKeys, isVerified, err := mach.GetOwnVerificationStatus(ctx) + if err != nil { + //log.WithLevel(zerolog.FatalLevel).Err(err).Msg("Failed to check verification status") + return err + } + log.Debug().Bool("has_keys", hasKeys).Bool("is_verified", isVerified).Msg("Checked verification status") + + // TODO + // get recovery key from mxpass (base58) + // for now only 'new' is supported + keyInDB := "" + if !hasKeys || keyInDB == "overwrite" { + if keyInDB != "" && keyInDB != "overwrite" { + //log.WithLevel(zerolog.FatalLevel). + // Msg("No keys on server, but database already has recovery key. Delete `recovery_key` from `kv_store` manually to continue.") + return errors.New("") + } + recoveryKey, err := mach.GenerateAndVerifyWithRecoveryKey(ctx) + if recoveryKey != "" { + // TODO + // store recovery key in mxpass (base58) + } + if err != nil { + //log.WithLevel(zerolog.FatalLevel).Err(err).Msg("Failed to generate recovery key and self-sign") + return err + } + log.Info().Msg("Generated new recovery key and self-signed bot device") + } else if !isVerified { + if keyInDB == "" { + //log.WithLevel(zerolog.FatalLevel). + // Msg("Server already has cross-signing keys, but no key in database. Add `recovery_key` to `kv_store`, or set it to `overwrite` to generate new keys.") + return errors.New("") + } + err = mach.VerifyWithRecoveryKey(ctx, keyInDB) + if err != nil { + log.WithLevel(zerolog.FatalLevel).Err(err).Msg("Failed to verify with recovery key") + return err + } + log.Info().Msg("Verified bot device with existing recovery key") + } + return nil +} + // NewMXClient creates a new Matrix Client ready for syncing func NewMXClient(homeserverURL string, userID id.UserID, accessToken string) (*MXClient, error) { client, err := mautrix.NewClient(homeserverURL, userID, accessToken) diff --git a/libmxclient/mxclientlib.go b/libmxclient/mxclientlib.go index aa4b290..c8ec44d 100644 --- a/libmxclient/mxclientlib.go +++ b/libmxclient/mxclientlib.go @@ -701,6 +701,16 @@ func apiv0_getuserdm(cid C.int, userid *C.char) *C.char { return returnJSON(list, nil) } +//export apiv0_self_sign +func apiv0_self_sign(cid C.int) *C.char { + cli, err := getClient(int(cid)) + if err != nil { + return returnErr(err) + } + err = cli.SelfSign(context.Background()) + return returnErr(err) +} + //export apiv0_removeclient func apiv0_removeclient(cid C.int) C.int { return 0 diff --git a/pygomx/build_ffi.py b/pygomx/build_ffi.py index 6889ea1..6bcc3e6 100644 --- a/pygomx/build_ffi.py +++ b/pygomx/build_ffi.py @@ -76,6 +76,7 @@ ffibuilder.cdef( extern char* apiv0_createdm(int cid, char* uid); extern char* apiv0_genericrequest(int cid, char* method, char* path, char* data); extern char* apiv0_getuserdm(int cid, char* userid); + extern char* apiv0_self_sign(int cid); extern int apiv0_removeclient(int cid); extern char* apiv0_listclients(); extern char* apiv0_getoptions(int cid); diff --git a/pygomx/libmxclient.def b/pygomx/libmxclient.def index 54469e8..d0779a8 100644 --- a/pygomx/libmxclient.def +++ b/pygomx/libmxclient.def @@ -32,6 +32,7 @@ apiv0_set_on_sys_handler apiv0_setoptions apiv0_startclient apiv0_stopclient +apiv0_self_sign cliv0_accountinfo cliv0_clearaccount cliv0_discoverhs diff --git a/pygomx/src/pygomx/apiv0.py b/pygomx/src/pygomx/apiv0.py index d255e3b..fa2d7c6 100644 --- a/pygomx/src/pygomx/apiv0.py +++ b/pygomx/src/pygomx/apiv0.py @@ -141,6 +141,10 @@ class ApiV0Api: lib.apiv0_getevent(cid, _autostring(roomid), _autostring(eventid)) ) + @staticmethod + def self_sign(cid): + return _stringresult(lib.apiv0_self_sign(cid)) + class ApiV0: """ApiV0"""