matrix-js-sdk: Retriving stored backup ends up with error: OLM.BAD_MESSAGE_MAC

This error occurs when I delete my app or remove the app caches mainly the indexedDB data and after that when I try to restore the data this error occurs. With some docs and code this seems to happen when the signature has been invalided and in our case the backup signature. Not sure why this happens. Any sort of help would be appreciated. With this any new messages being received are not being decrypted.

My understanding is that the backup is not device specific but dependent on device Id .

Some common errors

  • The sender’s device has not sent us the keys for this message.
  • The secure channel with the sender was corrupted. Trying to create a new secure channel and re-requesting the keys.

Sharing how I am setting the backup and restoring it.

Setup Backup

  async setAndEnableBackup() {
    const client = await this.getClient();
    const keypharse = 'secure';
    if (!client) {
      return alert('Client does not exist');
    }
    const backup = await this.getBackup();
    if (backup && backup.backupInfo) {
      this.restoreBackup(backup, client, keypharse);
    }
  }
}

Check & Create Backup

async getBackup() {
  const client = await this.getClient();
  let backup = await client.checkKeyBackup();
  console.log('KEY BACKUP - checkKeyBackup', backup);

  if (!backup.backupInfo) {
    console.log('KEY BACKUP - createSecureBackup');
    return this.createSecureBackup(client);
    // throw new Error('Backup broken or not there');
  }
  console.log('KEY BACKUP - retrivedBackup');
  return backup;
}

Creating Backup

  async createSecureBackup() {
    const client = await this.getClient();
    const keypharse = 'secure';
    // const client = await this.getClient();
    console.log('KEY BACKUP - keypharse', keypharse);
    const prepareKeybackup = await client.prepareKeyBackupVersion(keypharse);
    console.log('KEY BACKUP - prepareKeyBackupVersion', prepareKeybackup);
    const newKeybackup = await client.createKeyBackupVersion(prepareKeybackup);
    console.log('KEY BACKUP - createKeyBackupVersion', newKeybackup);
    return newKeybackup;
  }

Restoring Backup

async restoreBackup(backup, client, passphrase) {
    if (
      backup.backupInfo.auth_data?.private_key_salt &&
      backup.backupInfo.auth_data?.private_key_iterations
    ) {
      const backupWithPassword = await client.restoreKeyBackupWithPassword(
        passphrase,
        undefined,
        undefined,
        backup.backupInfo,
        {},
      );
      console.log(
        'KEY BACKUP - restoreKeyBackupWithPassword',
        backupWithPassword,
      );
    } else {
      console.log('KEY BACKUP - enableKeybackup');
      try {
        await client.enableKeyBackup(backup.backupInfo);
        if (!backup.trustInfo.usable) {
          // this will also set trust usable and local trust true.
          const recoverInfo = await client.restoreKeyBackupWithSecretStorage(
            backup.backupInfo,
            undefined,
            undefined,
          );
          console.log('RECOVER INFO', recoverInfo);
        }
      } catch (e) {
        console.error('Error in restore backup', e);
      }
    }
  }

What have I done to make it work, but it’s not the best case help in validating the backup would be awesome

To resolve the error, I create/setup a new backup after the invalided one, it seems to work fine, but what happens is that any new messages after the new backup seems to be the not decrypted on receive but after syncing the keys with the other members of the room it works just fine. So maybe if the backup is restored with a valid signature. this would not be required.

And this happens for some cases, but most times what happens is that the encrypted session gets deleted, while I do not see the warning on my own client, I can see a little shield on element specifying that this message has been sent by a deleted encrypted session. Plus element seems to decrypt the message but my client with the invalidated backup does not even after creating a new backup.

I get this log

When handling UISI from @rohan:localhost (sender key zz/mf0Yoo4mtWjiobhj+UOwrKPvZgW4yErPg+evR9W8): recent session problem with that sender
  async requestRoomKeys(roomId, event) {
    const client = await this.getClient();
    const room = client.getRoom(roomId);
    const userId = this.userId;
    const deviceId = this.deviceId;
    const sessionId = client.getSessionId();
    const senderkey = client.getDeviceCurve25519Key();
    const members = room.getMembers().map(user => ({
      userId: user.userId,
      deviceId: client.getStoredDevicesForUser(user.userId)[0].deviceId,
    }));
    const roomKeyRequest = {
      algorithm: 'm.megolm.v1.aes-sha2',
      room_id: roomId,
      session_id: sessionId,
      sender_key: senderkey,
      recipients: members,
    };

    console.log('Sender Key', roomKeyRequest);

    const res = await client.crypto.requestRoomKey(
      roomKeyRequest,
      members,
      true,
    );
    console.log('RES', res);
  } 

matrix-js-sdk: 23.1.1

About this issue

Most upvoted comments

I understand, thank you and I’ll let you know if I get anywhere with this.