From eb17e5d826008a82ca197866a03761ddb6fe9480 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Fri, 14 Feb 2020 16:20:10 -0500 Subject: [PATCH 1/6] switch to symmetric algorithm --- proposals/1946-secure_server-side_storage.md | 60 ++++++++++---------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/proposals/1946-secure_server-side_storage.md b/proposals/1946-secure_server-side_storage.md index fd907e53..59f02d8b 100644 --- a/proposals/1946-secure_server-side_storage.md +++ b/proposals/1946-secure_server-side_storage.md @@ -123,38 +123,33 @@ and the key descriptions for the keys would be: #### Encryption algorithms -##### `m.secret_storage.v1.curve25519-aes-sha2` - -The public key is stored in the `pubkey` property of the `m.secret_storage.key.[key -ID]` account_data as a base64-encoded string. - -The data is encrypted and MACed as follows: - -1. Generate an ephemeral curve25519 key, and perform an ECDH with the ephemeral - key and the public key to generate a shared secret. The public half of the - ephemeral key, encoded using base64, becomes the `ephemeral` property. -2. Using the shared secret, generate 80 bytes by performing an HKDF using - SHA-256 as the hash, with a salt of 32 bytes of 0, and with the empty string - as the info. The first 32 bytes are used as the AES key, the next 32 bytes - are used as the MAC key, and the last 16 bytes are used as the AES - initialization vector. -4. Encrypt the data using AES-CBC-256 with PKCS#7 padding. This encrypted - data, encoded using base64, becomes the `ciphertext` property. -5. Pass the raw encrypted data (prior to base64 encoding) through HMAC-SHA-256 - using the MAC key generated above. The first 8 bytes of the resulting MAC - are base64-encoded, and become the `mac` property. - -(The key HKDF, AES, and HMAC steps are the same as what are used for encryption -in olm and megolm.) - -For example, the `m.secret_storage.key.[key ID]` for a key using this algorithm +##### `m.secret_storage.v1.aes-hmac-sha2` + +Secrets are encrypted using AES-CTR-256 and MACed using HMAC-SHA-256. The data +is encrypted and MACed 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. + +(We use AES-CTR to match file encryption and key exports.) + +For example, the `m.secret_storage.key.key_id` for a key using this algorithm could look like: ```json { "name": "m.default", - "algorithm": "m.secret_storage.v1.curve25519-aes-sha2", - "pubkey": "base64+public+key" + "algorithm": "m.secret_storage.v1.aes-hmac-sha2" } ``` @@ -164,8 +159,8 @@ and data encrypted using this algorithm could look like this: { "encrypted": { "key_id": { + "iv": "16+bytes+base64", "ciphertext": "base64+encoded+encrypted+data", - "ephemeral": "base64+ephemeral+key", "mac": "base64+encoded+mac" } } @@ -174,7 +169,7 @@ and data encrypted using this algorithm could look like this: ###### Keys -When a user is given a raw key for `m.secret_storage.v1.curve25519-aes-sha2`, +When a user is given a raw key for `m.secret_storage.v1.aes-hmac-sha2`, it will be encoded as follows (this is the same as what is proposed in MSC1703): * prepend the two bytes 0x8b and 0x01 to the key @@ -200,7 +195,8 @@ ID]` account-data: "passphrase": { "algorithm": "m.pbkdf2", "salt": "MmMsAlty", - "iterations": 100000 + "iterations": 100000, + "bits": 256 }, ... } @@ -209,7 +205,9 @@ ID]` account-data: **`m.pbkdf2`** The key is generated using PBKDF2 using the salt given in the `salt` parameter, -and the number of iterations given in the `iterations` parameter. +and the number of iterations given in the `iterations` parameter. The key size +that is generated is given by the `bits` parameter, or 256 bits if no `bits` +parameter is given. ### Sharing From f7ebda040e4c9d476da81cd6bd48e56b3affa805 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 24 Mar 2020 15:35:32 -0400 Subject: [PATCH 2/6] update some examples to use new algorithm name --- proposals/1946-secure_server-side_storage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proposals/1946-secure_server-side_storage.md b/proposals/1946-secure_server-side_storage.md index 59f02d8b..61950b5f 100644 --- a/proposals/1946-secure_server-side_storage.md +++ b/proposals/1946-secure_server-side_storage.md @@ -43,7 +43,7 @@ A key with ID `abcdefg` is stored in `m.secret_storage.key.abcdefg` ```json { "name": "Some key", - "algorithm": "m.secret_storage.v1.curve25519-aes-sha2", + "algorithm": "m.secret_storage.v1.aes-hmac-sha2", // ... other properties according to algorithm } ``` @@ -106,7 +106,7 @@ and the key descriptions for the keys would be: ```json { "name": "Some key", - "algorithm": "m.secret_storage.v1.curve25519-aes-sha2", + "algorithm": "m.secret_storage.v1.aes-hmac-sha2", // ... other properties according to algorithm } ``` @@ -116,7 +116,7 @@ and the key descriptions for the keys would be: ```json { "name": "Some other key", - "algorithm": "m.secret_storage.v1.curve25519-aes-sha2", + "algorithm": "m.secret_storage.v1.aes-hmac-sha2", // ... other properties according to algorithm } ``` From 76dd16b854b8b0d94fcced863fa0751d2fff4bcd Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 24 Mar 2020 16:18:44 -0400 Subject: [PATCH 3/6] add proposal to switch to symmetric crypto --- proposals/1946-secure_server-side_storage.md | 6 ++ proposals/xxxx-symmetric-ssss.md | 76 ++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 proposals/xxxx-symmetric-ssss.md diff --git a/proposals/1946-secure_server-side_storage.md b/proposals/1946-secure_server-side_storage.md index 61950b5f..5263e8c7 100644 --- a/proposals/1946-secure_server-side_storage.md +++ b/proposals/1946-secure_server-side_storage.md @@ -8,6 +8,12 @@ decryption key for the backups on the server, or cross-signing ([MSC1756](https://github.com/matrix-org/matrix-doc/pull/1756)) can store the signing keys. This proposal presents a standardized way of storing such data. +## Changes + +- [MSCxxxx](https://github.com/matrix-org/matrix-doc/pull/xxxx) changed the + encryption algorithm used from an asymmetric algorithm (Curve25519) to a + symmetric algorithm (AES). + ## Proposal Secrets are data that clients need to use and that are sent through or stored diff --git a/proposals/xxxx-symmetric-ssss.md b/proposals/xxxx-symmetric-ssss.md new file mode 100644 index 00000000..bde9fa95 --- /dev/null +++ b/proposals/xxxx-symmetric-ssss.md @@ -0,0 +1,76 @@ +# Symmetric SSSS + +[MSC1946 (Secure Secret Storage and +Sharing)](https://github.com/matrix-org/matrix-doc/pull/1946) proposed a way of +storing encrypted secrets on the server. In the proposal, secrets were +encrypted using a Curve25519 key, which was chosen to allow easier migration +from key backups that we created before the backup key was stored using it. + +However this does not provide any guarantees that data stored using the +proposal came from a trusted source. To remedy this, we propose to change the +encryption to use AES with a MAC to ensure that only someone who knows the key +is able to store data. + +## Proposal + +* The `m.secret_storage.v1.curve25519-aes-sha2` method proposed in MSC1946 is + removed. + +* A new method, `m.secret_storage.v1.aes-hmac-sha2`, is added. With this + method, the Secret Storage key may be any size (though 256 bits is + recommended), and data 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. + + (We use AES-CTR to match file encryption and key exports.) + + If the key Secret Storage key is generated from a passphrase, information + about how to generate the key is stored in the `passphrase` property of the + key's account-data in a similar manner to what was done with the original + `m.secret_storage.v1.curve25519-aes-sha2` method, except that there is an + optional `bits` parameter that defaults to 256, and indicates the number of + bits that should be generated from PBKDF2 (in other words, the size of the + key). + +* The `passthrough` property specified in the "Enconding the recovery key for + server-side storage via MSC1946" section of MSC1219 is removed. The primary + purpose of that property was to allow easy migration of pre-MSC1946 backups, + so that users could reuse the backup recovery key as the Secret Storage key + without needing to re-enter the recovery key. However, since we are now + using a symmetric encryption algorithm, the client needs to know the key that + is used to encrypt, so the purpose of the field cannot be fulfilled. + + +## Potential issues + +Users who have data stored using the old encryption algorithm will need their +data migrated. Clients that support the old algorithm but not the new +algorithm will not be able to use the migrated secrets until they are updated +with the new algorithms. This should not be a major problem because the only +clients that are known to have implemented the old algorithm are Riot +Web/Android/iOS, and they have been upgraded to implement the new algorithm. + + +## Alternatives + +Rather than switching to a symmetric encryption algorithm, we could stay with +an asymmetric encryption algorithm, and add on a method to authenticate the +data. However, it is much safer to use well-known cryptographic methods rather +than trying to invent something new. Since the main reason for using an +asymmetric scheme was to ease migration from older key backups without +requiring the user to re-enter the key, but this is no longer possible due to +the need to authenticate the data using the Secret Storage key, there is no +reason to stay with an asymmetric algorithm. It is also better to use +cryptographic methods already used in Matrix where possible, rather than +introducing something new. From 4b21e44e5f1f4dd52afa9555ba509f4755e7de37 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 24 Mar 2020 16:24:09 -0400 Subject: [PATCH 4/6] use the MSC number --- proposals/1946-secure_server-side_storage.md | 2 +- proposals/{xxxx-symmetric-ssss.md => 2472-symmetric-ssss.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename proposals/{xxxx-symmetric-ssss.md => 2472-symmetric-ssss.md} (100%) diff --git a/proposals/1946-secure_server-side_storage.md b/proposals/1946-secure_server-side_storage.md index 5263e8c7..a73fee4c 100644 --- a/proposals/1946-secure_server-side_storage.md +++ b/proposals/1946-secure_server-side_storage.md @@ -10,7 +10,7 @@ signing keys. This proposal presents a standardized way of storing such data. ## Changes -- [MSCxxxx](https://github.com/matrix-org/matrix-doc/pull/xxxx) changed the +- [MSC2472](https://github.com/matrix-org/matrix-doc/pull/2472) changed the encryption algorithm used from an asymmetric algorithm (Curve25519) to a symmetric algorithm (AES). diff --git a/proposals/xxxx-symmetric-ssss.md b/proposals/2472-symmetric-ssss.md similarity index 100% rename from proposals/xxxx-symmetric-ssss.md rename to proposals/2472-symmetric-ssss.md From 943d9386bb3d7e87e439eed10b5fd5c0057e360b Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Mon, 30 Mar 2020 17:43:46 -0400 Subject: [PATCH 5/6] remove requirement to sign the key, since it is no longer used to trust it --- proposals/1946-secure_server-side_storage.md | 12 ++---------- proposals/2472-symmetric-ssss.md | 4 ++++ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/proposals/1946-secure_server-side_storage.md b/proposals/1946-secure_server-side_storage.md index a73fee4c..ca4230de 100644 --- a/proposals/1946-secure_server-side_storage.md +++ b/proposals/1946-secure_server-side_storage.md @@ -38,9 +38,8 @@ 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. The contents will be signed as signed JSON using the -user's master cross-signing key. Other properties depend on the encryption -algorithm, and are described below. +a human-readable name. Other properties depend on the encryption algorithm, +and are described below. Example: @@ -61,13 +60,6 @@ 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. -Clients MUST ensure that the key is trusted before using it to encrypt secrets. -One way to do that is to have the client that creates the key sign the key -description (as signed JSON) using the user's master cross-signing key. -Another way to do that is to prompt the user to enter the passphrase used to -generate the encryption key and ensure that the generated private key -corresponds to the public key. - #### Secret storage Encrypted data is stored in the user's account_data using the event type diff --git a/proposals/2472-symmetric-ssss.md b/proposals/2472-symmetric-ssss.md index bde9fa95..4827e2cd 100644 --- a/proposals/2472-symmetric-ssss.md +++ b/proposals/2472-symmetric-ssss.md @@ -51,6 +51,10 @@ is able to store data. using a symmetric encryption algorithm, the client needs to know the key that is used to encrypt, so the purpose of the field cannot be fulfilled. +* Signing the Secret Storage key with the user's master cross-signing key is no + longer required. The key is trusted on the basis of the user entering the + key/passphrase. + ## Potential issues From 4a3f9ec63ade930eaafad5b62d9ccb912893ba9a Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Mon, 30 Mar 2020 17:44:06 -0400 Subject: [PATCH 6/6] add information to check the key --- proposals/1946-secure_server-side_storage.md | 12 +++++++++++- proposals/2472-symmetric-ssss.md | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/proposals/1946-secure_server-side_storage.md b/proposals/1946-secure_server-side_storage.md index ca4230de..5e24b3ae 100644 --- a/proposals/1946-secure_server-side_storage.md +++ b/proposals/1946-secure_server-side_storage.md @@ -141,13 +141,23 @@ is encrypted and MACed as follows: (We use AES-CTR to match file encryption and key exports.) +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. + For example, the `m.secret_storage.key.key_id` for a key using this algorithm could look like: ```json { "name": "m.default", - "algorithm": "m.secret_storage.v1.aes-hmac-sha2" + "algorithm": "m.secret_storage.v1.aes-hmac-sha2", + "iv": "random+data", + "mac": "mac+of+encrypted+zeros" } ``` diff --git a/proposals/2472-symmetric-ssss.md b/proposals/2472-symmetric-ssss.md index 4827e2cd..7fe9f179 100644 --- a/proposals/2472-symmetric-ssss.md +++ b/proposals/2472-symmetric-ssss.md @@ -43,6 +43,14 @@ is able to store data. bits that should be generated from PBKDF2 (in other words, the size of the key). +* 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. + * The `passthrough` property specified in the "Enconding the recovery key for server-side storage via MSC1946" section of MSC1219 is removed. The primary purpose of that property was to allow easy migration of pre-MSC1946 backups,