-
Notifications
You must be signed in to change notification settings - Fork 280
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
Standardise Noise handshake for libp2p #195
Comments
(cc'ing @romanb) To sum things up, there are two possibilities:
In other words, it's a choice to make: do we stop being generic over the format of the node's public key, or do we go against the design of the Noise protocol? I'm personally in favour of option 1.
In rust-libp2p, the suite is in the protocol name. |
rust-libp2p does not do that and it does not currently support KK, but XX. If and when a new static DH key is generated, as well as its lifetime, is left to the application. It just supports either to reuse an ed25519 signing keypair or to authenticate a separate static DH keypair via any libp2p identity keypair. I think in substrate, the static DH key is generated and signed with the node's (persistent) identity keypair when the node starts and persists in-memory for the lifetime of the process.
The implementation in rust-libp2p should indeed currently support that, since the public identity keys are sent along as noise handshake payloads in addition to the static DH keys and the type of identity keys used is not part of the (static) handshake pattern name. |
You make it sound like using Noise with an Ed25519 keypair is a triviality, but I don't think that is true. Ed25519 keypairs and Curve25519 keypairs for use with X25519 are not in one-to-one correspondence. An ed25519 keypair can be converted to a Curve25519 keypair but that cannot be reversed, hence the need to transmit the public identity key (in the handshake payloads) even when reusing an ed25519 keypair for x25519 in rust-libp2p.
I think this is misleading and to my knowledge is neither what rust-libp2p does nor what substrate does. The static key is not replaced by an ephemeral key. Static DH keys in Noise are by definition the keys that are reused across multiple Noise handshake executions whereas ephemeral keys are by definition used in a single handshake. rust-libp2p-noise indeed only supports handshake patterns also involving static DH keys. The fact that a static DH keypair only persists for e.g. the lifetime of a process does not make it an ephemeral keypair as far as the Noise protocol is concerned. As I mentioned in libp2p/rust-libp2p#1027 I don't agree that signing the static public DH keys with separate long-lived signature keys is "against the design of Noise", but a legitimate extension making use of the handshake payloads.
Personally, I think it very desirable to have a Noise integration that works with any libp2p identity keypair. As I mentioned in libp2p/rust-libp2p#1027, using handshakes from the Noise Signatures Extension Spec may be preferable to the current implementation in rust-libp2p in order to remove the indirection over static DH keys, though I think that it would preclude handshakes between nodes with different types of signature keypairs, as these types seem to be fixed for a particular such handshake pattern. |
Thanks for clarifying all those points @romanb. Also, as a side note, the PR notes on libp2p/rust-libp2p#1027 are excellent, so thanks for that. It does look like embedding a certificate in the handshake payload is suggested by the spec as a means of authenticating the static public key. It’s also very similar to what we’re doing for TLS 1.3 - we embed the identity key and a signature over the TLS session key into a certificate and send it in the handshake. Also, it may not be desireable to use the identity key as the Noise static key, even if it is of a compatible key type. The security considerations section of the spec (linked above) says
Which suggests that if the identity key is used as the Noise static key, it would be difficult to prove that it’s safe to also use for e.g secio. |
Thanks a lot @tomaka @romanb @yusefnapora for contributing to the discussion here.
|
I agree that we shouldn't try to use libp2p identity keys as Noise static keys. It seems simplest to just always use the libp2p identity key to sign the Noise static key, regardless of key type. Regarding the Noise Signatures spec, it does look like basically what we want, but as @romanb mentions, the signature algorithm is fixed in the handshake type. So two peers with different identity key types would not be able to perform the handshake with each other. Below is a rough outline that assumes that we're essentially codifying the rust-libp2p behavior, except that there's no special treatment of ed25519 keys. I can start writing it up next week, if there's no major objections, or retool it if there are. Intro & ContextWhat is Noise, why do we want it, etc. Supported ciphers & hashesrust-libp2p always uses ChaChaPoly and SHA2-265. Is there a good reason to also support AESGCM (hardware support, maybe)? Supported Handshake Patternsrust-libp2p currently supports IK, IX, and XX. Noise Pipes describes a "compound protocol" using XX, IK, and XX+fallback to I propose we spec out support for XX, IK, and XX+fallback to enable the Noise Pipes 0-RTT Should we also support IX? Authenticating Noise static keys using libp2p identitiesDescribe and specify the transmission of the libp2p identity key and signature
Note that the lifetime of the Noise static keys is application-specific. Protocol / Handshake negotiationHow do we negotiate which supported handshake to use? To play nice with the rest Message FramingNoise messages have a maximum size of 65535 bytes, which makes it simple to QUIC supportWe should think about this some more :) nQUIC seems to only support the IK |
There have been isolated initiatives to implement a Noise handshake for libp2p, and it's time to standardise on a common approach for interoperability 🎉
Prior art
Noise_{IK/IX/KK}_25519_ChaChaPoly_SHA256
.Some questions to answer
Which handshake patterns we'll support? These are valid ones:
libp2p key support. Noise relies on ECDH operations and does not support RSA keys.
rust-libp2p does the above, but they use IX, IK, XX, and generates a Curve25519 key on the spot to fill in for the static key.(see Standardise Noise handshake for libp2p #195 (comment) for correction)Noise protocol instantiations. Do we support a single suite (e.g.
Noise_*_25519_ChaChaPoly_SHA256
) or multiple? How do we select a suite?Multiaddr support. A few of us have debated enhancing multiaddrs to announce the secure channels supported by the peer.
noise
, noise handshakenoise/ix
, the full suitenoise/ix/25519/chachapoly/sha256
), and how that choice will impact negotiation.Integration with QUIC (which presumes TLS 1.3). See nQUIC for Noise+QUIC.
Editor note. I found the 25519 nomenclature a tad confusing. This clarifies the difference between X25519, Ed25519, Curve25519; excerpt:
The text was updated successfully, but these errors were encountered: