New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SECIO spec #106

Open
wants to merge 2 commits into
base: master
from

Conversation

@bigs
Copy link
Contributor

bigs commented Oct 24, 2018

Introduces a spec for SECIO. Various crypto algorithms living in *-libp2p-crypto have been omitted for the time being.

@bigs bigs requested review from Stebalien and raulk Oct 24, 2018

@wafflebot wafflebot bot assigned bigs Oct 24, 2018

@wafflebot wafflebot bot added the in progress label Oct 24, 2018

@Stebalien
Copy link
Contributor

Stebalien left a comment

General comment: this reads more like a walk though the go-libp2p secio implementation and less like a spec. It would be nice if this were a bit more declarative (list out the message types, explain how they are composed, then explain how to use them) and less "run this, then this, then this".

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).*

This comment has been minimized.

@Stebalien

Stebalien Oct 24, 2018

Contributor

Let's point at #100 (once it's merged)

Pubkey: <public key bytes>,
Exchanges: <comma separated string of supported key exchanges>,
Ciphers: <comma separated string of supported ciphers>,
Hashes: <comma separated string of supported hashes>,

This comment has been minimized.

@Stebalien

Stebalien Oct 24, 2018

Contributor

Let's put the actual protobuf here (and say that it's a protobuf).


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*

This comment has been minimized.

@Stebalien

Stebalien Oct 24, 2018

Contributor

Given that this is just the spec, I'd just say:

At this point, each peer should check that the public key matches the expected peer ID, if known.

Or something like that. We don't need to explicitly tell the programmer how to implement the protocol step-by-step (i.e., "calculate the peer ID and store it for later").

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).

This comment has been minimized.

@Stebalien

Stebalien Oct 24, 2018

Contributor

We should actually spec this.

This comment has been minimized.

@tomaka

tomaka Oct 25, 2018

Member

That's standard ECDHE if I'm not mistaken.

Epubkey: <ephemeral pubkey>,
Signature: <sign corpus with local private key>,
}
```

This comment has been minimized.

@Stebalien

Stebalien Oct 24, 2018

Contributor

Again, let's just use the protobuf definition.

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).

This comment has been minimized.

@Stebalien

Stebalien Oct 24, 2018

Contributor

Again, we need to spec this.

opened. Each packet is of the form:

```
[uint32 length of packet | encrypted body | hmac signature of encrypted body]

This comment has been minimized.

@Stebalien

Stebalien Oct 24, 2018

Contributor
  • We encode the lengths as big-endian (network-order).
  • Need to specify what "encrypt" means.
  • Need to specify how we mac.

This comment has been minimized.

@richardschneider

richardschneider Nov 9, 2018

Contributor

Does the padding style for encrypt need to be specified?

This comment has been minimized.

@Stebalien

Stebalien Nov 9, 2018

Contributor

Really, we should specify everything. Ideally, we'd point to an RFC. However, we should optimize for merging something that's correct rather than waiting for something that's perfect.

This comment has been minimized.

@richardschneider

richardschneider Nov 13, 2018

Contributor

I'm assuming that the length includes the encrypted body and the hmac signature.

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

This comment has been minimized.

@tomaka

tomaka Oct 25, 2018

Member

Need to specify the order within the result of the stretching.


The SECIO wire protocol features two message types defined in the
[protobuf description language](https://github.com/libp2p/go-libp2p-secio/blob/master/pb/spipe.proto).
These two messages, `Propose` and `Exchange` are the only serialized types

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

Let's dump the current state of the protobufs here. Relying on a reference that can mutate can render the spec incoherent at a later time. Also, we're seeking to version specs in general, so capturing the current state and versioning the spec as it evolves is fair play.

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

Nevermind, I see this feedback is recurrent below.


### Proposal Generation

SECIO channel negotiation begins with a proposal phase. Both sides generate a

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

As a prerequisite for SECIO, we need a dedicated channel where both parties have agreed to proceed with SECIO handshake by means of a multiplexer or else.


### Key Stretching

Peers now generate their shared secret based on the function generated by the

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

IIRC, that function is referred to in literature as the KDF (key derivation function), and the overall process is called ECDH key agreement. Let's use these terms to evoke familiar concepts.

This comment has been minimized.

@richardschneider

richardschneider Nov 12, 2018

Contributor

I think its official name is ECSVDP-DH

- P-384
- P-521

### Ciphers

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

Ciphers used for key stretching and for message encryption once SECIO channel is established.

SECIO allows participating peers to support a subset of the following
algorithms.

### Exhchanges

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

Elliptic curves used for ephemeral key generation.

- AES-128
- Blowfish

### Hashes

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

Hashes used for key stretching, and for HMACs once SECIO channel is established.

This comment has been minimized.

@richardschneider

richardschneider Nov 13, 2018

Contributor

What mode and padding is AES-* using? Are there any parameters for Blowfish?

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

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

These are not generated here. The MAC key is already generated during key stretching above. The cipher was selected above when comparing Propose messages.

What the Go implementation does at this point is prepare the constructs for HMAC and encryption/decryption. I think that's what needs to be stated, i.e. the implementation now has the required parameters to initialise the cryptographic constructs.

```

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.

This comment has been minimized.

@raulk

raulk Oct 25, 2018

Contributor

The target of validation is actually the (d)encryption and HMAC'ing logic. We use a known value (nonce) to send a predictable message so we can validate that both parties have set up the encrypted channels correctly.


## Table of Contents

- [Algorithm Support](#algorithm-support)

This comment has been minimized.

@raulk

raulk Nov 7, 2018

Contributor

ToC is missing entries.

### Hashes

- SHA-256
- SHA-512

This comment has been minimized.

@richardschneider

richardschneider Nov 10, 2018

Contributor

Current go implementation does not use dashes in the hash name; see al.go.

@whyrusleeping

This comment has been minimized.

Copy link
Contributor

whyrusleeping commented Nov 11, 2018

@bigs status on this? Are you planning on continuing this work in the near future?

@bigs

This comment has been minimized.

Copy link
Contributor Author

bigs commented Nov 12, 2018

yep @whyrusleeping just lower priority than testbed work at the moment. lotta good feedback re: shaping this into a more formal spec

@mgoelzer mgoelzer referenced this pull request Nov 19, 2018

Open

Specs 2.0 & libp2p book #110

1 of 16 tasks complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment