Skip to content
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

noise: introduce an extension registry #453

Merged
merged 5 commits into from
Sep 23, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 43 additions & 16 deletions noise/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

| Lifecycle Stage | Maturity | Status | Latest Revision |
|-----------------|----------------|--------|-----------------|
| 3A | Recommendation | Active | r3, 2022-09-20 |
| 3A | Recommendation | Active | r4, 2022-09-22 |

Authors: [@yusefnapora]

Expand Down Expand Up @@ -201,28 +201,31 @@ messages. We leverage this construct to transmit:

1. the libp2p identity key along with a signature, to authenticate each party to
the other.
2. arbitrary data private to the libp2p stack. This facility is not exposed to
userland. Examples of usage include streamlining muxer selection.

These payloads MUST be inserted into the first message of the handshake pattern
marten-seemann marked this conversation as resolved.
Show resolved Hide resolved
**that guarantees secrecy**. In practice, this means that the initiator must not
send a payload in their first message. Instead, the initiator will send its
payload in message 3 (closing message), whereas the responder will send theirs
in message 2 (their only message). It should be stressed, that the second
message of the handshake pattern has forward secrecy, however the sender has not
authenticated the responder, so this payload might be sent to any party,
including an active attacker.
2. extensions used by the libp2p stack.

The extensions are inserted into the first message of the handshake pattern
**that guarantees secrecy**. Specifically, this means that the initiator MUST NOT
send extensions in their first message.
The initiator sends its extensions in message 3 (closing message), and the
responder sends theirs in message 2 (their only message). It should be stressed,
that while the second message of the handshake pattern has forward secrecy,
the sender has not authenticated the responder yet, so this payload might be
sent to any party, including an active attacker.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a security precaution is it helpful to specify that the "early data" should not be processed before the handshake is fully finished? thus gives us more confidence on the data, what are your thoughts on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In WebTransport, we process it immediately, and fail the handshake if the certificate hash doesn't match.
Maybe we should point out that consumers of early data need to be careful, and that delaying the processing / acting upon the early data can be one strategy to deal with this.

Copy link
Contributor

@julian88110 julian88110 Sep 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, document that is a good point.
Processing early data before authentication runs the risk of opening an attack surface for flooding / DOS attack.


When decrypted, the payload contains a serialized [protobuf][protobuf]
`NoiseHandshakePayload` message with the following schema:

``` protobuf
syntax = "proto2";

message NoiseExtensions {
julian88110 marked this conversation as resolved.
Show resolved Hide resolved
repeated bytes webtransport_certhashes = 1;
}

message NoiseHandshakePayload {
optional bytes identity_key = 1;
optional bytes identity_sig = 2;
optional bytes data = 3;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, rust-libp2p does not make use of data. @marten-seemann do any of the other implementations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go-libp2p doesn't, and js-libp2p doesn't either (as far as I know).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about nim-libp2p cpp-libp2p jvm-libp2p @marten-seemann?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not familiar with their code bases. This PR was open for more than a week, that should’ve been plenty of time to chime in. Also note that this is backwards-compatible change since we didn’t reuse field 3 in the protobuf.

optional NoiseExtensions extensions = 4;
}
```

Expand All @@ -235,9 +238,8 @@ spec][peer-id-spec-signing-rules]. The data to be signed is the UTF-8 string
`noise-libp2p-static-key:`, followed by the Noise static public key, encoded
according to the rules defined in [section 5 of RFC 7748][rfc-7748-sec-5].

The `data` field contains the "early data" provided to the Noise module when
initiating the handshake, if any. The structure of this data is opaque to
noise-libp2p and is defined in the connection establishment specs.
The `extensions` field contains Noise extensions and is described in
[Noise Extensions](#noise-extensions).

Upon receiving the handshake payload, peers MUST decode the public key from the
`identity_key` field into a usable form. The key MUST then be used to validate
Expand Down Expand Up @@ -283,6 +285,23 @@ internal libp2p data.

The XX handshake MUST be supported by noise-libp2p implementations.

### Noise Extensions

Since the Noise handshake pattern itself doesn't define any extensibility
mechanism, this specification defines an extension registry, modeled after
[RFC 6066](https://www.rfc-editor.org/rfc/rfc6066) (for TLS) and
[RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000#section-19.21)
(for QUIC).

Note that this document only defines the `NoiseExtensions` code points, and
leaves it up to the protocol using that code point to define semantics
associated with these code point.

Code points above 1024 MAY be used for experimentation. Code points up to
this value MUST be registered in this document before deployment.
Comment on lines +300 to +301
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand we tried to use multicodec for all magic numbers in the libp2p ecosystem thus far. If I understand this proposal correctly, it runs somewhat against this convention.

I am not opposed to that, I just think it is worth pointing out in the specification. E.g. a short paragraph of why we are not using multicodec for this.

What do you think @marten-seemann?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'm not super familiar with the design philosophy behind multicoded. @Stebalien and @lidel, could you help us out here?




## Cryptographic Primitives

The Noise framework allows protocol designers to choose from a small set of
Expand Down Expand Up @@ -433,6 +452,14 @@ unsupported types like RSA.
- Removed Noise Pipes and related handshake patterns
- Removed padding within encrypted payloads

### r3 - 2022-09-20

- Change Protobuf definition to proto2 (due to the layout of the protobuf used, this is backwards-compatible change)

### r4 - 2022-09-22

- Add Noise extension registry


[peer-id-spec]: ../peer-ids/peer-ids.md
[peer-id-spec-signing-rules]: ../peer-ids/peer-ids.md#how-keys-are-encoded-and-messages-signed
Expand Down