secret's identifier. The keys that secrets are encrypted with are
described by data that is also stored in the user's account-data. Users
can have multiple keys, allowing them to control what sets of secrets
clients can access, depending on what keys are given to them.
##### Key storage
Each key has an ID, and the description of the key is stored in the
user's account\_data using the event type
`m.secret_storage.key.[key ID]`. The contents of the account data for
the key will include an `algorithm` property, which indicates the
encryption algorithm used, as well as a `name` property, which is a
human-readable name. Key descriptions may also have a `passphrase`
property for generating the key from a user-entered passphrase, as
described in [deriving keys from
passphrases](#deriving-keys-from-passphrases).
`KeyDescription`
<table>
<thead>
<trclass="header">
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td>name</td>
<td>string</td>
<td><strong>Required.</strong> The name of the key.</td>
</tr>
<trclass="even">
<td><p>algorithm</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> The encryption algorithm to be used for this key. Currently, only <code>m.secret_storage.v1.aes-hmac-sha2</code> is supported.</p></td>
</tr>
<trclass="odd">
<td><p>passphrase</p></td>
<td><p>string</p></td>
<td><p>See <ahref="#deriving-keys-from-passphrases">deriving keys from passphrases</a> section for a description of this property.</p></td>
</tr>
</tbody>
</table>
Other properties depend on the encryption algorithm, and are described
below.
A key can be marked as the "default" key by setting the user's
account\_data with event type `m.secret_storage.default_key` to an
object that has the ID of the key as its `key` property. The default key
will be used to encrypt all secrets that the user would expect to be
available on all their clients. Unless the user specifies otherwise,
clients will try to use the default key to decrypt secrets.
##### Secret storage
Encrypted data is stored in the user's account\_data using the event
type defined by the feature that uses the data. The account\_data will
have an `encrypted` property that is a map from key ID to an object. The
algorithm from the `m.secret_storage.key.[key ID]` data for the given
key defines how the other properties are interpreted, though it's
expected that most encryption schemes would have `ciphertext` and `mac`
properties, where the `ciphertext` property is the unpadded
base64-encoded ciphertext, and the `mac` is used to ensure the integrity
<td><p><strong>Required.</strong> Map from key ID the encrypted data. The exact format for the encrypted data is dependent on the key algorithm. See the definition of <code>AesHmacSha2EncryptedData</code> in the <ahref="#msecret_storagev1aes-hmac-sha2">m.secret_storage.v1.aes-hmac-sha2</a> section.</p></td>
Secrets encrypted using the `m.secret_storage.v1.aes-hmac-sha2`
algorithm are encrypted using AES-CTR-256, and authenticated using
HMAC-SHA-256. The secret is encrypted as follows:
1. Given the secret storage key, generate 64 bytes by performing an
HKDF with SHA-256 as the hash, a salt of 32 bytes of 0, and with the
secret name as the info. The first 32 bytes are used as the AES key,
and the next 32 bytes are used as the MAC key
2. Generate 16 random bytes, set bit 63 to 0 (in order to work around
differences in AES-CTR implementations), and use this as the AES
initialization vector. This becomes the `iv` property, encoded using
base64.
3. Encrypt the data using AES-CTR-256 using the AES key generated
above. This encrypted data, encoded using base64, becomes the
`ciphertext` property.
4. Pass the raw encrypted data (prior to base64 encoding) through
HMAC-SHA-256 using the MAC key generated above. The resulting MAC is
base64-encoded and becomes the `mac` property.
`AesHmacSha2EncryptedData`
<table>
<thead>
<trclass="header">
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td><p>iv</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> The 16-byte initialization vector, encoded as base64.</p></td>
</tr>
<trclass="even">
<td><p>ciphertext</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> The AES-CTR-encrypted data, encoded as base64.</p></td>
</tr>
<trclass="odd">
<td>mac</td>
<td>string</td>
<td><strong>Required.</strong> The MAC, encoded as base64.</td>
</tr>
</tbody>
</table>
For the purposes of allowing clients to check whether a user has
correctly entered the key, clients should:
1. encrypt and MAC a message consisting of 32 bytes of 0 as described
above, using the empty string as the info parameter to the HKDF in
step 1.
2. store the `iv` and `mac` in the `m.secret_storage.key.[key ID]`
account-data.
`AesHmacSha2KeyDescription`
<table>
<thead>
<trclass="header">
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td>name</td>
<td>string</td>
<td><strong>Required.</strong> The name of the key.</td>
</tr>
<trclass="even">
<td><p>algorithm</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> The encryption algorithm to be used for this key. Currently, only <code>m.secret_storage.v1.aes-hmac-sha2</code> is supported.</p></td>
</tr>
<trclass="odd">
<td><p>passphrase</p></td>
<td><p>object</p></td>
<td><p>See <ahref="#deriving-keys-from-passphrases">deriving keys from passphrases</a> section for a description of this property.</p></td>
</tr>
<trclass="even">
<td>iv</td>
<td>string</td>
<td>The 16-byte initialization vector, encoded as base64.</td>
</tr>
<trclass="odd">
<td><p>mac</p></td>
<td><p>string</p></td>
<td><p>The MAC of the result of encrypting 32 bytes of 0, encoded as base64.</p></td>
</tr>
</tbody>
</table>
For example, the `m.secret_storage.key.key_id` for a key using this
To request a secret from other devices, a client sends an
`m.secret.requests` device event with `action` set to `request` and
`name` set to the identifier of the secret. A device that wishes to
share the secret will reply with an `m.secret.send` event, encrypted
using olm. When the original client obtains the secret, it sends an
`m.secret.request` event with `action` set to `request_cancellation` to
all devices other than the one that it received the secret from. Clients
should ignore `m.secret.send` events received from devices that it did
not send an `m.secret.request` event to.
Clients must ensure that they only share secrets with other devices that
are allowed to see them. For example, clients should only share secrets
with the user’s own devices that are verified and may prompt the user to
confirm sharing the secret.
##### Event definitions
###### `m.secret.request`
Sent by a client to request a secret from another device or to cancel a
previous request. It is sent as an unencrypted to-device event.
<table>
<thead>
<trclass="header">
<th>Parameter</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td><p>name</p></td>
<td><p>string</p></td>
<td><p>Required if <code>action</code> is <code>request</code>. The name of the secret that is being requested.</p></td>
</tr>
<trclass="even">
<td>action</td>
<td>enum</td>
<td><strong>Required.</strong> One of ["request", "request_cancellation"].</td>
</tr>
<trclass="odd">
<td>requesting_device_id</td>
<td>string</td>
<td><strong>Required.</strong> The ID of the device requesting the secret.</td>
</tr>
<trclass="even">
<td><p>request_id</p></td>
<td><p>string</p></td>
<td><p><strong>Required.</strong> A random string uniquely identifying (with respect to the requester and the target) the target for a secret. If the secret is requested from multiple devices at the same time, the same ID may be used for every target. The same ID is also used in order to cancel a previous request.</p></td>