element-hq / element-desktop

A glossy Matrix collaboration client for desktop.
https://element.io
GNU Affero General Public License v3.0
1.14k stars 261 forks source link

Loading the session fails with "Unable to load session Error decrypting secret access_token: bad MAC" #1077

Open justjanne opened 1 year ago

justjanne commented 1 year ago

None of the previous reporters included any reproduction steps. They all reported element refusing to launch with the aforementioned error.

Element fails with the following stacktrace:

2023-02-16T19:42:57.280Z I Got pickle key
2023-02-16T19:42:57.281Z E Unable to load session Error decrypting secret access_token: bad MAC
Error: Error decrypting secret access_token: bad MAC
    at  s (webpack:///node_modules/matrix-js-sdk/src/crypto/aes.ts:95:14)
    at async te (webpack:///node_modules/matrix-react-sdk/src/Lifecycle.ts:455:16)
    at async Object.q (webpack:///node_modules/matrix-react-sdk/src/Lifecycle.ts:149:8)
    at async webpack:///node_modules/matrix-react-sdk/src/components/structures/MatrixChat.tsx:343:16
t3chguy commented 1 year ago

Vast majority of reports are from Linux, 3 from Windows. Theory: race condition between app launch and keyring unlocking

Johennes commented 1 year ago

Removing from our board as this is not a fire based on our definition of it and, thus, won't be picked up by our processes.

CC @daniellekirkwood / @andybalaam

richvdh commented 2 months ago

Given the number of reports we receive of this, I'm updating the labels

richvdh commented 2 months ago

Contrary to what you might expect given the error message, this is not related to end-to-end encryption.

Specifically, the problem comes from trying to decrypt the matrix access token, which is stored, encrypted, in indexeddb, in matrix-react-sdk.account, as an IEncryptedPayload, which has the format:

export interface IEncryptedPayload {
    /** the initialization vector in base64 */
    iv: string;
    /** the ciphertext in base64 */
    ciphertext: string;
    /** the HMAC in base64 */
    mac: string;
}

When encrypting the access token, we:

When decrypting, we therefore derive the same pair of keys, and then verify that a signature on ciphertext matches mac. For this error to occur, in other words, implies that a different pickle key is being

The (misnamed) restoreFromLocalStorage method first retrieves the encrypted access token from indexeddb, and then calls PlatformPeg.getPickleKey to fetch the pickle key. On the Electron platform, getPickleKey uses keytar to fetch a password named <userId>|<deviceId> from the element.io service in the system keyring. That password should be 32-byte random array created when the user logged in.

What is particularly strange here is that, somehow, a completely different pickle key is being hallucinated somehow. It's not that there is a total absence of pickle key; that would be more understandable, as some sort of failure to talk to the system keychain.

richvdh commented 2 months ago

I wonder if this could be something like: the user has logged out and logged in again, causing a new picklekey to be created, and new user id/device id to be stored in localstorage.

However, indexeddb is having a bit of a moment, and the access token is not correctly persisted in indexeddb. Hence, on restore, we get the picklekey for the old encrypted access token.

richvdh commented 2 months ago

I added some logging which might help diagnose this, in https://github.com/matrix-org/matrix-react-sdk/pull/12831. Interested to hear from people who observe it in nightlies or 1.11.72 or later.