matrix-org / matrix-js-sdk

Matrix Client-Server SDK for JavaScript
Apache License 2.0
1.6k stars 590 forks source link

[Question] How to verify new session? Cross-signing and secret storage bootstrapped. #1513

Closed menturion closed 3 weeks ago

menturion commented 4 years ago

Setup: -- JS based client (running in browser) -- Bootstrapping cross-signing and secret storage were successfully completed -- Backup has been created and gets updated -- IndexedDBs: cryptoStore, syncStore

When starting a fresh new session (restarting the browser, deleted IndexedDBs, etc.) the device and cross-signing keys are downloaded and the backup gets restored with the below cross-signing status (excerpt):

XS status:

 crossSigningPublicKeysOnDevice = null
 selfSigningPrivateKeyCached = false
 userSigningPrivateKeyCached = false

getCrossSigningId() returns null. Cross-signing keys are available in secret storage only. They are not cached. Verifying own device does not succeed due to missing self_signing key, although available (.getStoredCrossSigningForUser(userId)).

How do I verify this session (programmatically), i.e. how do I "fix" the above XS status so that.isSecretStorageReady() would return true?

crimue commented 3 years ago

Hey @menturion, did you solve this issue? I am trying to implement cross-signing in my js-app. I only found this article (https://matrix.org/docs/guides/implementing-more-advanced-e-2-ee-features-such-as-cross-signing) but I am unable to translate this over to the matrix-js-sdk. The documentation (https://matrix-org.github.io/matrix-js-sdk/15.1.0/index.html) about this topic is sadly nonexistent... Thank you very much!

crimue commented 2 years ago

Hi @menturion! Thank you for your fast answer! This is really helpful! I will try to understand it. So you were able to build a working cross-signing?

crimue commented 2 years ago

Is it possible that you maybe please give a short description what you have used to get it working? I started working with the matrix-react-sdk source code. I am struggling to find the problem why I am not able to even answer the first "crypto.verification.request" event... Device hydration is not so important for me... but getting the chat history is important and would be awesome! 😀 Thank you very much!

crimue commented 2 years ago

@menturion Any news on that? 😀

I tried to implement the verification (element app verification request to custom matrix-js-sdk web app) like:

client.on("crypto.verification.request", async (event) => {
        if (!isReady) return;
        console.debug("Verification request incoming");
        console.debug(event);

        let acceptResult = await event.accept();

        console.debug(acceptResult);

    });

But the element web app gets stuck after "verify by emoji" and just shows the circular spinner... Sorry for the reping and thanks for your help!

crimue commented 2 years ago

Thanks @menturion for the ressources! I was able to build a working verification process. Atm it is of course really dirty and not safe for production use! It only should be used as a starting point! Thank you for your help! Feel free to improve this snippet.

Initiating client

Send a verification request to a other client

async sendVerificationRequest() {

            let currentVerificationRequest;

            // send request to specific account
            currentVerificationRequest = await client.requestVerification("@userIdToVerify:matrix.org");

            // on change listener to react to phase changes
            currentVerificationRequest.on("change", this.sendVerificationRequestMonitor);

        },

Watch for phase changes in your sent verification request

 async sendVerificationRequestMonitor() {
            console.debug("sendVerificationRequestMonitor")
            console.debug(this)

            // check if _verifier exists - if not build one - why: 
            // element webclient <--> matrix js sdk; builds a _verifier for you
            // matrix js sdk <--> matrix js sdk; no _verifier is build, you have to build it yourself with beginKeyVerification()
            if (!this._verifier) {
                console.debug("---- start _verifier ---- ")
                // beginKeyVerification is deprecated since 15.0.0 - but I did not find an alternative to this function?
                const verifier = this.beginKeyVerification(verificationMethods.SAS);

                try {
                    // start verification process after verifier is build
                    await verifier.verify();
                } catch (err) {
                    console.debug(err);
                }
            }
            else {
                // start verification process when _verifier was build by element client
                this._verifier.verify();
            }

            let currentRequest = this;

            // setTimeout simulates user-input
            // show emojis/decimals and present a "They match" or "They don't match" buttons
            // if they match execute data._verifier.sasEvent.confirm();
            setTimeout(function () {
                console.debug("--- verify is ready, confirmation needed---")
                currentRequest._verifier.sasEvent.confirm();

                console.debug(currentRequest)

                //finishRequest();
            }, 5000);
        },

Receiving client

  client.on("crypto.verification.request", async function (data) {
                // matrix client must be ready
                if (!isReady) return;

                console.debug("Verification request incoming");
                console.debug(data);

                currentVerificationRequest = data;

                // Accept request to get to next phase
                data.accept();

                // change listener to log/debug changes
                data.on("change", onVerificationRequestChange);

                data.on('change', async function () {

                    console.debug("VerificationRequest.change", this, this.phase);
                    console.debug("--- Change verification vequest ---")

                    // phase 4 allows to start verify process
                    if (this.phase === 4) {
                        console.debug("--- PHASE 4 ---")

                        // start verify process
                        data._verifier.verify();

                        // setTimeout simulates user-input
                        // show emojis/decimals and present a "They match" or "They don't match" buttons
                        // if they match execute data._verifier.sasEvent.confirm();
                        setTimeout(function () {
                            console.debug("--- verify ist durch ---")
                            console.debug(data)
                            data._verifier.sasEvent.confirm();

                            // data._verifier.verify();
                            //finishRequest();
                        }, 5000);

                    }
                });

Debugging function

 function onVerificationRequestChange() {
                console.debug("Phase change in verification request!")
                console.debug(currentVerificationRequest);
            }
thar0x29a commented 2 years ago

I ran into my own issues if i try to request an Verification. Its almost the same route that @crimue went.

  1. start requestVerification. It returns an verifyer
  2. listen to its 'change' event and wait for phase 4
  3. trigger the verify process by calling verify() ... not on the first result but reather on the last event._verifier result.
  4. check the emojis in your sasevent.sas object and call confirm on it.

It should work. But it doesnt. It results into an "chanceled". Not sure why.

crimue commented 2 years ago

Hey @thar0x29a, is the problem solved? I answered the Matrix message that your project partner send me but I did not get an answer.

You can also take a look here: https://github.com/hmendes00/matrix-js-sdk-e2ee-helpers. @hmendes00 describes some ways to implement verification and SSSS 😀

richvdh commented 3 weeks ago

The documentation in this area has been improved significantly as part of the Rust crypto project, so hopefully this is better now. Improved examples are also welcome (cf #430)