diff --git a/components/client-side-key-management.md b/components/client-side-key-management.md index 0d4b27c..c3c123e 100644 --- a/components/client-side-key-management.md +++ b/components/client-side-key-management.md @@ -206,25 +206,25 @@ cryptographic algorithms used in whatever protocols we design. ## High-Level Design -* Client-Side Keys will consist of a 256-bit random key, which will be used as the IKM input to HKDF for deriving - multiple keys, including: +* Client-Side Keys will consist of a 256-bit random key, called the **main key** for an account, which will be used as + the IKM input to HKDF for deriving multiple keys, including: * An Ed25519 identity key. The public key will be used for the [Federated PKI](federated-pki.md). * A symmetric key for wrapping one-time secret keys (for multi-device support). -* Users **SHOULD** generate their key on a mobile device, but are not strictly required to. +* Users **SHOULD** generate their main key on a mobile device, but are not strictly required to. * For users that do not have a mobile device, the Browser Extension is recommended. -* Keys will be exportable. For example: +* Main Keys will be exportable. For example: * Export to another mobile device, for multi-device support. * Export to a Browser Extension for use with Fediverse websites. * Export to a desktop app (if applicable). -* Users will be able to encrypt their key with a passphrase. +* Users will be able to encrypt their main key with a passphrase. * This passphrase-protected key **MAY** be stored in the Mastodon server. * This is beneficial to user profiles: **Alice**, **Bob**, **Chloe**. * Users will be able to use a threshold scheme to share their key with a group of their most trusted friends. * This is beneficial to user profiles: **Bob**, **Chloe**, **Duncan**. * Users like **Alice** generally won't want this feature. * Threats like **Ollie** make this an unattractive option for many users. -* Users can, at any time, generate a new key. - * If they still have their previous key, they may maintain continuity of key control. +* Users can, at any time, generate a new main key. + * If they still have their previous main key, they may maintain continuity of key control. * If they do not, they can still re-enroll their new key, but will not have access to old messages. All existing one-time keypairs will be invalidated. Additionally, their Direct Message partners will be informed of the rotation when they send another message. diff --git a/components/secret-keys/key-export.md b/components/secret-keys/key-export.md index 25f8a3c..db575a3 100644 --- a/components/secret-keys/key-export.md +++ b/components/secret-keys/key-export.md @@ -1,3 +1,216 @@ # Exporting Keys to Multiple Devices +## Overview +This document describes the protocols used to export keys generated on one device onto another device. + +At a high level overview, there are three underlying technologies used to perform this task. + +1. QR codes for encoding data in a visual format that mobile devices can easily scan +2. An encrypted token format ([PASETO](https://github.com/paseto-standard/paseto-spec)) +3. An asymmetric key-wrapping format ([PASERK](https://github.com/paseto-standard/paserk)) + +Three distinct workflows will be possible with these components: + +1. Copying a cryptographic secret from a mobile device to a browser extension +2. Copying a cryptographic secret from a browser extension to a mobile device +3. Copying a cryptographic secret from one mobile device to another + +Of these three workflows, the first is the riskiest, because the data must transfer from the device to the browser +extension; which, for usability, calls for passing an encrypted secret to the server and decrypting it in the browser. +This is because calling the web browser on a particular computer from the mobile device may be difficult in many +networking environments. + +Workflows 2 and 3 can be facilitated with only a QR code; no server needed. + +## Workflows + +### Workflow 1 + +This is exclusively used for devices that do not possess a camera (i.e. browser extensions for desktop computers). + +1. **Receiver**: Generate an Ephemeral Ed25519 keypair: `ed25519_sk`, `ed25519_pk` +2. **Receiver**: Call [`CreateQRCodeForImport(ed25519_pk)`](#createqrcodeforimport) +3. **Receiver**: Display QR code, begin polling server for message from Sender +4. **Sender**: Scan QR code (from step 3) +5. **Sender**: Call [`ExportMainKey(main_key, ed25519_pk, device_name = "")`](#exportmainkey) +6. **Sender**: Send the exported key to the server to relay to Receiver +7. **Receiver**: Call [`ImportMainKey(paseto, ed25519_sk, device_name = "")`](#unsealmainkey) + +### Workflows 2 and 3 + +This is the preferred workflow, since the server isn't involved. + +1. **Sender**: Prompt user for a password or PIN for the transfer +2. **Sender**: Call [`GenerateQRCodeForExport(main_key, password, device_name = """)`](#createqrcodeforexport) +3. **Sender**: Display QR code +4. **Receiver**: Scan QR code (from step 3) +5. **Receiver**: Call [`UnwrapMainKeyFromQRCode(paseto, password, device_name = "")](#unwrapmainkeyfromqrcode) + +## Operations + +### CreateQRCodeForImport + +This is used for [Workflow 1](#workflow-1). This will run on the device that receives the key. + +**Inputs**: + +1. `ed25519_pk`: An ephemeral Ed25519 public key + +**Algorithm**: + +1. Encode the public key `ed25519_pk` using the + [PASERK `public`](https://github.com/paseto-standard/paserk/blob/master/types/public.md) type. + +### ExportMainKey + +This is used for [Workflow 1](#workflow-1). This will run on the device that sends the key. + +**Inputs**: + +1. `main_key` - The key being exported for a given account + * This **MUST** be base64url-encoded (as per RFC 4648). It **SHOULD NOT** be padded with `=` characters. +2. `ed25519_pk` - From `CreateQRCodeForImport()` +3. `device_key` - The nickname of the device (optional, defaults to empty string) + +**Algorithm**: + +1. Generate a one-time 256-bit transfer key `transfer_key`. +2. Use PASERK's [`seal`](https://github.com/paseto-standard/paserk/blob/master/types/seal.md) type to encrypt + `transfer_key` with `ed25519_pk` (Input 2) to yield `sealed_transfer_key`. +3. Generate a Local PASETO token using `transfer_key` with the following parameters: +* `payload`: + * `main_key`: Input 1 +* `footer`: + * `wpk`: `sealed_transfer_key` +* `implicit_assertion`: + * `device`: Input 3 +4. Encode the PASETO token (output of step 3) as a QR code image to be scanned with a mobile device. + +The permitted algorithms for this operation (as of the time of this writing) are: + +* PASETO `v3.local` +* PASETO `v4.local` (default token format) +* PASERK `k3.seal` +* PASERK `k4.seal` (default public-key encryption for key-wrapping format) + +### UnsealMainKey + +This is used for [Workflow 1](#workflow-1). This runs on the device that receives the key. + +**Inputs**: + +1. `paseto` - Local PASETO with a wrapped key in the footer +2. `ed25519_sk` - Ephemeral Ed25519 secret key (64 bytes; the latter half is the public key) +3. `device_name` - The nickname of the device (optional, defaults to empty string) + +**Algorithm**: + +1. Extract `footer` from `paseto`. +2. Extract the `sealed_transfer_key` from the footer's `wpk` parameter. (Footers are cleartext.) +3. Use PASERK's `seal` type to decrypt `sealed_transfer_key` with `ed25519_sk` to yield `transfer_key`. +4. Decrypt `paseto` yielding `transfer_key`, using `device_name` as the value for `implicit_assertion`. +5. Decode the `main_key` claim (base64url from RFC 4648). Return this. + +**Output**: A 256-bit `main_key`. + +### CreateQRCodeForExport + +This is used for [Workflows 2 and 3](#workflows-2-and-3). This runs on the device that sends the key. + +**Inputs**: +1. `main_key` - The key being exported for a given account + * This **MUST** be base64url-encoded (as per RFC 4648). It **SHOULD NOT** be padded with `=` characters. +2. `password` - Used to encrypt the secret key across devices +3. `device_name` - The nickname of the device (optional, defaults to empty string) + +**Algorithm**: + +1. Generate a one-time 256-bit transfer key `transfer_key`. +2. Use PASERK's [`local-pw`](https://github.com/paseto-standard/paserk/blob/master/types/local.md) type to encrypt + `transfer_key` with the `password` (Input 2) to yield `wrapped_transfer_key`. +3. Generate a Local PASETO token using `transfer_key` with the following parameters: + * `payload`: + * `main_key`: Input 1 + * `footer`: + * `wpk`: `wrapped_transfer_key` + * `implicit_assertion`: + * `device`: Input 3 +4. Encode the PASETO token (output of step 3) as a QR code image to be scanned with a mobile device. + +The permitted algorithms for this operation (as of the time of this writing) are: + +* PASETO `v3.local` +* PASETO `v4.local` (default token format) +* PASERK `k3.local-pw` +* PASERK `k4.local-pw` (default password-based key-wrapping format) + +### UnwrapMainKeyFromQRCode + +This is used for [Workflows 2 and 3](#workflows-2-and-3). This will run on the device that receives the key. + +**Inputs**: + +1. `paseto` - Local PASETO with a wrapped key in the footer +2. `password` - One-time password or PIN provided by the user for this transfer +3. `device_name` - The nickname of the device (optional, defaults to empty string) + +**Algorithm**: + +1. Extract `footer` from `paseto`. +2. Extract the `wrapped_transfer_key` from the footer's `wpk` parameter. (Footers are cleartext.) +3. Use PASERK's `local-pw` type to decrypt `wrapped_transfer_key` with `password` to yield `transfer_key`. +4. Decrypt `paseto` yielding `transfer_key`, using `device_name` as the value for `implicit_assertion`. +5. Decode the `main_key` claim (base64url from RFC 4648). Return this. + +**Output**: A 256-bit `main_key`. + +## Questions and Answers + +### Why PASETO/PASERK Instead of JWT? + +As far as cryptographic token designs go, PASETO was designed to be misuse-resistant. JWT was not. + +* PASETO doesn't give you an `{"alg":"none"}` bullet to fire into your foot. JWT does. +* PASETO doesn't let you use an asymmetric public key as a symmetric key. JWT does. +* PASETO doesn't let you use weak keys for symmetric authentication. JWT does. +* Many JWT implementations let you bypass their security hardening against algorithm confusion if you change the key ID + header. PASETO prohibits this attack and provides [test vectors that **MUST** fail](https://github.com/paseto-standard/test-vectors). +* PASETO is simple for users. You don't have to reason about block cipher modes and their security implications. Your + choices are simply: + 1. Do I need to use NIST-approved algorithms (i.e. my OS is in FIPS mode)? + * YES: `v3` + * NO: `v4` (default) + 2. Do I need a separation of capabilities between token creators and token verifiers? + * YES: `public` + * NO: `local` +* PASETO publishes a [clear rationale for its design decisions with new protocol versions](https://github.com/paseto-standard/paseto-spec/blob/master/docs/Rationale-V3-V4.md). + JWT is an "Everything But the Kitchen Sink" standard whose rationale is unclear. + +For balance, the advantages of JWT are: + +1. There's an IETF RFC for JWT, and not for PASETO; which matters to some organizations +2. You can find more JWT implementations in more languages than PASETO + +PASERK is a PASETO extension that provides a lot of features that were excluded from PASETO. PASERK support is, for most +PASETO-supporting applications, completely optional. This lets PASETO users minimize their attack surface. + +To support the features we need, we're including these Types from the PASERK design too: + +1. [Password-based key-wrapping](https://github.com/paseto-standard/paserk/blob/master/types/local-pw.md) +2. [Asymmetric (public-key) key-wrapping](https://github.com/paseto-standard/paserk/blob/master/types/seal.md) + +This saves us from having to design a new key-encryption scheme. + +### Why Use Asymmetric (Public-Key) Encryption for Workflow 1? + +Without a QR code, we need to use the Fediverse server as a data mule for the import workflow. We assumed in +[our threat model](../client-side-key-management.md#threat-model) that server administrators are curious. +Therefore, we encrypt this data with a one-time Ed25519 keypair to ensure their curiosity remains unsated. + +### Why Use Password-Based Key Wrapping for Workflows 2 and 3? + +If someone shoulder-surfs your QR code, this shouldn't immediately give them access to your main key. + +This is a defense-in-depth risk mitigation. Do not rely entirely on the security of this password. If you +suspect someone copied your QR code for the device transfer, main key rotation is highly recommended.