diff --git a/README.md b/README.md index bf98b9e..9a42ab6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Authorized Wire via Authenticated Key Exchange (AWAKE) Specification v0.3.0 +# Authorized Wire for Authenticated Key Exchange (AWAKE) Specification v0.3.0 @@ -32,7 +32,7 @@ TODOs # 0. Abstract -Authorized Wire via Authenticated Key Exchange (AWAKE) is an [AKE] built on top of [MLS] and [UCAN]. AWAKE is similar to other [mutual authentication] schemes (such as self-signed [mTLS]), but with a focus on authorization and proof. AWAKE leverages the UCAN capability chain to prove access to some resource, validating that the requestor is communicating with a party capable of performing certain actions. This is a helpful root of trust with a well defined context when establishing a secure communications channel. +Authorized Wire for Authenticated Key Exchange (AWAKE) is a [mutual authentication] [AKE] designed for P2P applications. To root authority of both parties, AWAKE leverages the [UCAN] capability chain to prove access to some resource(s), validating that the requestor is communicating with a party capable of performing certain actions. ## Language @@ -40,19 +40,40 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S # 1 Introduction - - ## 1.1 Motivation +Applications in the client/server model typically use a certificate authorty to root their trust. This presupposes that the client is able to dial the correct resource and ask for them to authenticate. The situation is somewhat more complex in P2P and local-first applications operating on open channels, where location is independent and eventual consistecy allows for unlimited forking of resource access. + +Authorization on its own is no longer sufficient for this situation: it is entirely possible validate _who_ a responder, but the more relevant information is _what they have access to._ For instance, are they a member of a group message, can read from a particular database, or send email from a certain address. + +## 1.2 Generality + + + + + +[UCAN] allows for the representation of authority both with and without delegation. + + + + + +## 1.3 Philosophy + +Off the shelf components + + + # 2 Encryption Encryption is core to securing a tunnel. Key material and secrets created for AWAKE MUST be considered ephemeral and MUST NOT be reused between sessions. +While [MLS] is extremely robust, it does not allow for bidirectional authorization in the core protocol. Luckily, it is possible to extract this phase out to an AWAKE handshake ahead of starting a MLS. + At a high-level, AWAKE uses a [X25519] envelope to handshake into an authorized [MLS] session to establish a secure message channel. ## 2.1 Asymmetric Keys @@ -67,41 +88,28 @@ All symmetric keys SHOULD be non-extractable where possible. All symmetric encryption in the pre-MLS AWAKE handshake MUST use [XChaCha-Poly1305]. These keys MUST be generated by the [KDF](#143-diffie-hellman-key-derivation), and SHOULD be non-extractable where possible. -Each encrypted payload MUST include a unique (freshly generated) 24-byte [initialization vector](https://en.wikipedia.org/wiki/Initialization_vector). +Each encrypted payload MUST include a unique 24-byte [initialization vector][IV]. ### 2.3.3 Diffie-Hellman Key Derivation -AWAKE uses [HKDF](https://datatracker.ietf.org/doc/html/rfc5869) to derive keys. Key derivation in AWAKE's double ratchet MUST use the following algorithms: +AWAKE MUST use [HKDF](https://datatracker.ietf.org/doc/html/rfc5869) to derive keys. Key derivation in the AWAKE handshake MUST use the following algorithms: + -## 2.4 ~~Double Ratchet~~ MLS -FIME! - -The Double Ratchet conceptually consists of three ratchets: a Diffie-Hellman (asymmetric) ratchet, and two chain ratchets: a Sending Chain (encryption) and a Receiving Chain (decryption). +FIXME -The Sending Chain of the Requestor MUST always match the Receiving Chain of the Responder, and vice versa. The Diffie-Hellman ratchet is used to start a new epoch for the chain ratchets, "resetting" them with fresh starting values. -### 2.4.1.2 ECDH Input -The [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman) secret MUST be generated using [NIST P-256 elliptic curve](https://neuromancer.sk/std/nist/P-256) curve (AKA `secp256r1`). Non-extractable P-256 keys SHOULD be used where available (e.g. via the [WebCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey)). The sender MUST rotate their public key on every send. This does mean that in the [message phase](#4-secure-session), multiple keys MAY be valid due to concurrency and out-of-order message delivery. -The updated secret MUST be generated from the first 256-bits of the HKDF output. This new secret MUST be used as the input secret for the next message. Note that due to out-of-order message delivery, this secret MAY be used in up to one sent and one received message. -# 3 Terminology -This document contains shorthand (especially in diagrams) and nuanced senses of some terms. Below is a dictionary of AWAKE-specific terms: -| Term | Meaning | -| --------- | ---------------------------------------------------------------- | -| Attacker | A malicious third party attempting to gain access to the channel | -| ECDH | Elliptic Curve Diffie-Hellman | -| PK | Public key | -| Receiver | The agent receiving a particular message | -| Requestor | The agent opening the session | -| Responder | The agent being contacted by the Requestor | -| Sender | The agent sending a particular message | -| SK | Secret (private) key | +The [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman) secret MUST be generated using [X25519]. Non-extractable keys SHOULD be used where available. The sender MUST rotate their public key on every send. -## 4 Sequence +## 2.4 Messagaging Layer Security + +After the AWAKE handshake, the protocol switches over to the Messaging Layer Security ([MLS]) protocol with UCAN credentials. MLS establishes an efficient post-comporimise security channel with group management. + +## 3 Sequence AWAKE proceeds in one connection step, four communication rounds, and an OPTIONAL disconnection: @@ -112,12 +120,10 @@ AWAKE proceeds in one connection step, four communication rounds, and an OPTIONA 3. Responder establishes point-to-point session * a. Responder securely proves that they have sufficient rights * b. Responder transmits a session key via asymmetric key exchange -4. Requestor authentication - * a. Requestor sends actual DID +4. Requestor authentication over MLS + * a. Requestor sends an MLS connection request with their actual DID * b. Requestor sends instance validation (e.g. UCAN or out-of-band PIN) -5. Responder sends an `ACK` -6. Secure session messages (zero or more rounds) -7. Either party disconnects +5. Secure session messages (zero or more rounds) via MLS ```mermaid sequenceDiagram @@ -145,21 +151,25 @@ sequenceDiagram Requestor -->> Group: msg ``` -# 5. Handshake +# 4. Protocol Steps + + - -## 5.2 Subscribe to Common Channel +## 4.1 Subscribe to Common Channel AWAKE begins by all parties listening on a common channel. AWAKE itself is channel and transport agnostic; it MAY be broadcast to all listeners, MAY be asynchronous, and MAY be over any transport. To reduce channel noise, it is RECOMMENDED that this channel be scoped to a specific topic. @@ -167,32 +177,35 @@ For instance, a WebSocket pubsub channel on the topic `awake:did:key:zStEZpzSMtT The AWAKE handshake MUST occur on a single channel. The underlying channel MAY be changed after the handshake is complete. -## 5.2 Requestor Broadcasts Intent +## 4.2 Requestor Broadcasts Intent **NOTE: This stage is completely in the clear.** -``` -Attacker Requestor Responder - │ │ │ - │ Temp ECDH DID │ Temp ECDH DID │ (1a) - │ & Auth Criteria │ & Auth Criteria │ (1b) - │◄────────────────────────┼─────────────────────────►│ - ⋮ ⋮ ⋮ -``` +``` mermaid +sequenceDiagram + participant Attacker + participant Requestor + participant Provider -In this step, the Requestor broadcasts a temporary DID, and some criteria that a Responder MUST provide in [§3.3](#33-responder-establishes-point-to-point-session). Both pieces of information are sent in a single message. This request payload MUST contain the `did` and `caps` fields. The `caps` field MAY be an empty array. + Note over Attacker, Provider : 1. Initial (public) broadcast + Requestor -->> Attacker: 1.1 Temp X25519 DID & Auth criterea + Requestor ->> Provider: 1.1 Temp X25519 DID & Auth criterea -The payload stage MUST be signalled by the message type `"awake/init"`. +``` ### 5.2.1 Temporary ECDH DID -Since this message is sent entirely in the clear, the Requestor MUST generate a fresh P-256 key pair per AWAKE initialization attempt. This key MUST be used as the first step in the ECDH Double Ratchet. In the payload, the public key MUST be formatted as a [did:key](https://w3c-ccg.github.io/did-method-key/#p-256). +Since this message is sent entirely in the clear, the Requestor MUST generate a fresh X25519 key pair per AWAKE initialization attempt. This key MUST be used as the first step in the ECDH Double Ratchet. In the payload, the public key MUST be formatted as a [`did:key`]. + +This temporary key MUST only be used for key exchange, and MUST NOT be used for signatures, and MUST NOT be persisted past this one session bootstrap (i.e. discard after [§3.3](#33-responder-establishes-point-to-point-session)). -This temporary key MUST only be used for key exchange, and MUST NOT be used for signatures, and MUST NOT be persisted past this one session bootstrap (i.e. discard after [§3.3](#33-responder-establishes-point-to-point-session)). It is RECOMMENDED that the private key be non-extractable when possible, such as via the [WebCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey). +Where possible, it is RECOMMENDED that the private key be non-extractable. ### 3.2.2 Authorization Criteria -The Requestor MAY also include validation criteria expected from the Responder. This MUST be passed as an array of [UCAN capabilities](https://github.com/ucan-wg/spec#23-capability). The Responder MUST be able to prove access to these capabilities in [§3.3](#33-responder-establishes-point-to-point-session). +The Requestor MAY also include validation criteria expected from the Responder. This MUST be passed as a map of [UCAN capabilities]. The Responder MUST be able to prove access to these capabilities in [§3.3](#33-responder-establishes-point-to-point-session). + +If no capabilties are required, the `caps` field MUST be set to an empty map (`{}`). ### 3.2.3 Payload @@ -248,21 +261,20 @@ The payload contains two encryption layers and a signature: the ECDH components, NB this is the first step of the double ratchet / KDF, as explained in [§1.5.1.1](#double-ratchet-initialization). +FIXME derive IV or use random? + ``` mermaid flowchart TD - XCC["HKDF(X25519) = ChaCha Key 🔑"] - - subgraph Clear Payload - IV["Random IV"] - subgraph Env [Encrypted XChaCha-Poly1305 Envelope] - ucan["UCAN - iss: ResponderDID - aud:ReqECDH       - att: []                  - fct: [challenge]    - prf: ...                 - "] - end + XCC["HKDF(X25519 Shared Secret) = (IV, ChaCha Key)"] + + subgraph Env [Encrypted XChaCha-Poly1305 Envelope] + ucan["UCAN + iss: ResponderDID + aud:ReqECDH       + att: []                  + fct: [challenge]    + prf: ...                 + "] end XCC -.-> Env @@ -461,25 +473,27 @@ Many thanks to [Brian Ginsburg] for his exploration of AWAKE and suggestion to r [AKE]: https://en.wikipedia.org/wiki/Authenticated_Key_Exchange +[Base64]: https://datatracker.ietf.org/doc/html/rfc4648 +[Bluesky]: https://blueskyweb.xyz [Brian Ginsburg]: https://github.com/bgins +[Brooklyn Zelenka]: https://github.com/expede +[Daniel Holmgren]: https://github.com/dholms +[Double Ratchet]: https://signal.org/docs/specifications/doubleratchet/) to secure messages +[Elliptic Curve Diffie-Hellman]: https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman +[Fission]: https://fission.codes [MLS]: https://messaginglayersecurity.rocks/ +[Quinn Wilton]: https://github.com/QuinnWilton +[RFC 2119]: https://datatracker.ietf.org/doc/html/rfc2119 [Signal Protocol]: https://github.com/signalapp/libsignal +[UCAN capabilities]: https://github.com/ucan-wg/spec/#25-capability [UCAN]: https://github.com/ucan-wg/spec [WireGuard]: https://www.wireguard.com/ -[mutual authentication]: https://en.wikipedia.org/wiki/Mutual_authentication -[mTLS]: https://datatracker.ietf.org/doc/html/rfc8705 -[RFC 2119]: https://datatracker.ietf.org/doc/html/rfc2119 -[Fission]: https://fission.codes -[Quinn Wilton]: https://github.com/QuinnWilton -[Brooklyn Zelenka]: https://github.com/expede -[Daniel Holmgren]: https://github.com/dholms -[Bluesky]: https://blueskyweb.xyz -[Base64]: https://datatracker.ietf.org/doc/html/rfc4648 -[Elliptic Curve Diffie-Hellman]: https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman -[Double Ratchet]: https://signal.org/docs/specifications/doubleratchet/) to secure messages [X25519]: https://cryptography.io/en/latest/hazmat/primitives/asymmetric/x25519/ [XChaCha-Poly1305]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha - +[`did:key`]: https://w3c-ccg.github.io/did-method-key/#ed25519-x25519 +[IV]: https://en.wikipedia.org/wiki/Initialization_vector +[mTLS]: https://datatracker.ietf.org/doc/html/rfc8705 +[mutual authentication]: https://en.wikipedia.org/wiki/Mutual_authentication [ECDH Input]: #1431-ecdh-input