Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC4048: Authenticated key backup #4048

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
108 changes: 108 additions & 0 deletions proposals/4048-signed-key-backup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# MSC4048: Signed key backup

The [server-side key
backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups)
allows clients to store event decryption keys so that when the user logs in to
a new device, they can decrypt old messages. The current algorithm encrypts
the event keys using a symmetric algorithm, allowing clients to upload keys to
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
the backup without necessarily giving them the ability to read from the
backup. For example, this allows for a partially-trusted client to be able to
read (and save the keys for) current messages, but not read old messages.

However, since the event decryption keys are encrypted using a symmetric
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
algorithm, this allows anyone who knows the public key to write to the backup.
As a result, keys loaded from the backup must be marked as unauthenticated,
leading to [usability
issues](https://github.com/vector-im/element-web/issues/14323).

[MSC3270](https://github.com/matrix-org/matrix-spec-proposals/pull/3270) tries
to fix this issue by using a symmetric, authenticated encryption algorithm,
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
which ensures that only someone who knows the secret key can write to the
backup. However this removes the ability for a client to be able to write to
the backup without being able to read from it.
Comment on lines +21 to +22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This MSC could really do with explaining why the ability to write to the backup but not read from it it is useful.

Something something bots, I gather?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not just bots, but also as a prerequisite component for less privileged clients which don't have the ability to read all of history while still being able to participate in a room.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do any such clients or bots exist currently?

I feel like a bot or client writing but not reading from backup really should be an implementation requirement of this MSC to prove that it is actually useful to keep the ability to write but not read from the backup.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether they exist at the moment. But retaining the ability to have clients of reduced power (rather than requiring that they are all of equal, maximal power) seems like an obviously useful property.

Can you expand on how an example implementation would prove this further than a thought experiment? Or why the benefits are not obvious from the thought experiment?

Copy link
Contributor

@sumnerevans sumnerevans Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not obvious to me that a non-maximally-powerful client is useful. Maybe I have not been privy to some discussions about such potential use-cases?

Even the bot case that @richvdh mentioned doesn't really make sense to me. Why would I provide the bot access to my account?

I also don't know of any other chat network which has the concept of less-privileged clients (so as far as I know we are not copying prior art). It feels like such a client would be very confusing to end users.

I'm just a bit wary of doing things because it's a "useful property" when the property has not actually been shown to be useful (think: the overcomplicated megolm ratchet which has a mechanism for skipping by multiples of $$2^n$$ but is not used for >100 messages in most cases rendering the complexity pointless).


We propose to continue using a symmetric encryption algorithm in the backup,
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
but to ensure authenticity by signing the backup data.

## Proposal

A user has a new signing key, referred to as the "backup signing key", used to
sign key backups using the ed25519 signature algorithm. The private key can be
shared/stored using [the Secrets
module](https://spec.matrix.org/unstable/client-server-api/#secrets) using the
name `m.key_backup.signing`.

The `AuthData` object for the [`m.megolm_backup.v1.curve25519-aes-sha2` key
backup
algorithm](https://spec.matrix.org/unstable/client-server-api/#backup-algorithm-mmegolm_backupv1curve25519-aes-sha2)
has a new optional property called `signing_public_key`, contains the public
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the rationale behind using a new key for backup signing instead of reusing the master signing key or device key? Is it to make it possible to revoke the backup signing key without affecting any other keys?

Copy link
Member

@BillCarsonFr BillCarsonFr Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In several MSC we are seeing introduction of new keys (tofu, constraint membership), looks like we are going to soon have tons of such keys. It's mainly annoying because adding a new key requires to update the exisiting 4S in order to update the account recovery backup, and this will require users to enter their passphrase on upgrade.

Could we try to go with scoped signatures?

As per:

Given a scope named my-scope, a signature of a content would mean to take the canonical json of content then append my-scope to that string then sign it with an existing key (e.g MSK).

scoped_signature = sign(canonical_json_content + "my-scope", alice_msk).

And the signature should be uploaded with the ed25519. scheme:

"signatures": {
    "@alice:example.com": {
        "ed25519.myscope:base64+master+signing+public+key": "base64+scoped+signature+of+content"
    }
},

The scope is added in the string to sign so that the home server cannot switch signature from another scope (or no scope) of the same content.

In this case I suppose that using the scoped signature by the SSK makes sense

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi there! GitHub likes to notify me whenever someone uses my name with an @ in front of it as an example. I'll untag myself from this, but just a heads up :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a comment in the "Alternatives" section

key of the backup signing key, encoded in unpadded base64. If the `AuthData`
is not signed by the user's master signing key or by a verified device
belonging to the same user, the backup signing key must be ignored, and all
keys in the backup must be treated as being unsigned.
davidegirardi marked this conversation as resolved.
Show resolved Hide resolved

The `SessionData` object for the `m.megolm_backup.v1.curve25519-aes-sha2` key
backup algorithm has two new optional properties:

- a `signatures` property: the `SessionData` is a [signed JSON
object](https://spec.matrix.org/unstable/appendices/#signing-json), signed
using the backup signing key, using the public key (encoded in unpadded
base64) as the key ID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that SessionData is the plaintext, it sounds like we would have to decrypt the backup in order to find out whether the signature is correct. Given that we are also removing the outer MAC, that would leave us operating on unauthenticated cryptographic data, which is a no-no.

As an aside, I think this MSC would benefit from a "Mechanics" section describing concrete steps in a "You take THIS to perform THAT" kind of manner rather than leaving it implicit from the description of the components.

- a boolean `authenticated` property, defaulting to `false`: indicates whether
the device that uploaded the key to the backup believes that the key belongs
to the given `sender_key`. This is true if: a) the key was received via an
Olm-encrypted `m.room_key` event from the `sender_key`, b) the key was
received via a trusted key forward
([MSC3879](https://github.com/matrix-org/matrix-spec-proposals/pull/3879)),
or c) the key was downloaded from the key backup, with the `authenticated`
property set to `true` and signed by a trusted key. If the `SessionData` is
not signed by the backup signing key, then this flag must be treated as being
`false`.

The `mac` property in the cleartext `session_data` property of the
`KeyBackupData` is deprecated. Clients should continue to produce it for
compatibility with older clients, but should no longer use it to verify the
contents of the backup if the `SessionData` object is signed.

## Potential issues

As the `AuthData` is changed, a new backup version will need to be created. A
client will need to download all existing keys and re-upload them.

In order to store a new secret in the Secret Storage, clients may need to
prompt the user for the Secret Storage key. Clients may need to do so already
to download all the current keys from the backup.

## Alternatives

As mentioned above, we could switch to using a symmetric encryption algorithm
for the key backup. However, this is not backwards-compatible, and does not
allow for clients that can write to the backup without reading.

## Security considerations

Being able to prove authenticity of keys may affect the deniability of
messages: if a user has a Megolm session in their key backup that is signed by their
backup signing key, and the session data indicates that it originated from one
of their devices, this could be used as evidence that the Megolm session did in
fact come from them.

This is somewhat mitigated by the fact that obtaining the Megolm session
requires the decryption key for the backup. In addition, the deniability
property is mainly refers to the fact that a recipient cannot prove the
uhoreg marked this conversation as resolved.
Show resolved Hide resolved
authenticity of the message to a third party, and usually is not concerned with
preventing self-incrimination. And in fact, a confiscated device may already
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Just because I created a megolm session doesn’t mean that I was the one who encrypted the messages in it, as megolm is symmetric? So proving I own the creation of a key doesn’t achieve much in terms of deniability aiui; a given message could have been fabricated by the other party? (at least until you try to send a msg with the same ratchet key - but i guess the same would be true if the megolm session was entirely fabricated, in terms of happening at the wrong place relative to other megolm sessions)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Megolm session has a signing key that only the creator knows the private part. So while anyone can encrypt a message with the Megolm session, they won't be able to produce a correct signature, so the message won't be validated.

have enough information to sufficiently prove that the device's owner sent a
message.

## Unstable prefix

Until this MSC is accepted, the property name
`org.matrix.msc4048.signing_public_key` should be used in place of
`signing_public_key`, and `org.matrix.msc4048.authenticated` should be used in
place of `authenticated`. No unstable prefix is used for the `signatures`
property since it uses the existing definition of JSON signing.

## Dependencies

None