From 2194c68599ed051f028507177b5350e979fae846 Mon Sep 17 00:00:00 2001 From: Cole Brown Date: Wed, 24 Oct 2018 17:35:24 -0400 Subject: [PATCH] Finish first pass of SECIO spec --- secio/README.md | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/secio/README.md b/secio/README.md index 2cd3ef5..d1f923d 100644 --- a/secio/README.md +++ b/secio/README.md @@ -53,3 +53,108 @@ required to implement SECIO. ## Protocol ### Proposal Generation + +SECIO channel negotiation begins with a proposal phase. Both sides generate a +proposal as follows: + +*Note: the public key should be serialized per the `Bytes` method from +[go-libp2p-crypto](https://godoc.org/github.com/libp2p/go-libp2p-crypto#Key).* + +``` +Propose{ + Rand: <16 secure random bytes>, + Pubkey: , + Exchanges: , + Ciphers: , + Hashes: , +} +``` + +Both peers serialize this message and send it over the wire. Upon deserializing +their peer's message, they verify that the pubkey matches that described by the +peer's peer ID (NOTE: this is sometimes only possible for the peer *initiating* +the connection.) If the key doesn't match the peer ID, the peer can close the +connection. If the peer doesn't know the remote peer's ID, they can compute and +store the remote peer ID for later use. + +### Determining Roles and Algorithms + +Next, the peers use a deterministic formula to compute their roles in the coming +exchanges. Each peer computes: + +``` +oh1 := sha256(concat(remotePeerPubKeyBytes, myNonce)) +oh2 := sha256(concat(myPubKeyBytes, remotePeerNonce)) +``` + +With these hashes, determine which peer's preferences to favor. This peer will +be referred to as the "preferred peer". If `oh1 == oh2`, then the peer is +communicating with itself and should return an error. If `oh1 < oh2`, use the +remote peer's preferences. If `oh1 > oh2`, prefer the local peer's preferences. + +Given our preference, we now sort through each of the `Exchanges`, `Ciphers`, +and `Hashes` provided by both peers, selecting the first item from our preferred +peer's set that is also shared by the other peer. + +### Key Exchange + +Now the peers prepare a key exchange. Both peers generate an ephemeral key based +on the agreed upon exchange (currently support is only available for elliptic +curve algorithms). Ephemeral keys are generated via +[go-libp2p-crypto](https://godoc.org/github.com/libp2p/go-libp2p-crypto#GenerateEKeyPair). + +With keys generated, both peers create a `Exchange` message. First, they start by +generating a "corpus" that they will sign. + +``` +corpus := concat(myProposalBytes, remotePeerProposalBytes, ephemeralPubKey) +``` + +Then, generate the `Exchange`: + +``` +Exchange{ + Epubkey: , + Signature: , +} +``` + +The peers serialize these and write them over the wire. Upon receiving the +remote peer's `Exchange`, validate the signature by computing the `corpus` you +expect them to have generated with their public key. Peers should close the +connection if the signature does not validate. + +### Key Stretching + +Peers now generate their shared secret based on the function generated by the +ephemeral key generation, passing it the remote peer's ephemeral key. With the +shared secret generated, both peers stretch the key using the algorithm +described by +[go-libp2p-crypto](https://godoc.org/github.com/libp2p/go-libp2p-crypto#KeyStretcher). + +``` +k1, k2 := KeyStretcher(sharedSecret) +``` + +With `k1` and `k2` computed, swap the two values if the remote peer is the +preferred peer. After swapping if necessary, `k1` becomes the local peer's key +and `k2` the remote peer's key. + +Each peer now generates a MAC key and cipher for the remote and local keys +generated in the previous step using the `MacKey` and `CipherKey` from the +generated +[`StretchedKeys`](https://godoc.org/github.com/libp2p/go-libp2p-crypto#StretchedKeys) +objects. + +### Initiate Secure Channel + +With the cipher and HMAC signer created, the secure channel is ready to be +opened. Each packet is of the form: + +``` +[uint32 length of packet | encrypted body | hmac signature of encrypted body] +``` + +The first packet transmitted by each peer must be the remote peer's nonce. Peers +validate that the remote peer sent them their nonce, closing if unsuccessful. +Otherwise, a secure channel has been successfully opened.