-
Notifications
You must be signed in to change notification settings - Fork 279
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 Pipes fallback issues #246
Comments
Just to clarify, above when I say that doing In short, if I'm going to try writing up all the Noise Pipes scenarios to see if it's possible to determine what to use based on message size (option 1 from above). No one supports Noise Pipes
This one is easy, since there's no fallback involved or decisions to make. Alice and Bob both support Pipes
This works, since an initial Alice does not support Pipes, but Bob does
This one works fine, since Bob can tell whether to send Alice supports Pipes, but Bob does not
This is the problematic case. If
There doesn't seem to be way for Alice to distinguish the latter two cases from each other based on the message content. So now I'm thinking that option 1 isn't viable, and if we want to use the correct protocol naming rules we need to go with option 2 (always do I've actually already implemented this option in Go using the I'll plan to clean that branch up and make sure all the cases are tested, then I'll make a PR to go-libp2p-noise and link it back here. |
The fact that we made Noise Pipes optional is, IMO, what creates the ambiguity. If we only supported Noise Pipes, we could follow the recommendations in 10.5. Handshake indistinguishability. But given that we need to juggle both XX and IK/XXfallback, is what makes it difficult. Not just for the reasons laid out above, but because an IK-supporting Alice has no way of knowing if Bob supports IK to begin with. Therefore, it is never safe to use IK even if you support it. If we're willing to stick with Noise Pipes (which is in dispute in #249), we'll need to make it compulsory and remove the separate/lone-standing XX pathway entirely. Re: the protocol name passed at Alice initiates a full handshake (i.e. XX equivalent)
Alice initiates a succeeding IK handshake
Alice initiates a failing IK handshake
@yusefnapora -- does this answer clarify how we'd eventually resolve this discrepancy, if we decided to stick with Noise Pipes (discussing in #249)? |
@raulk that's exactly right, yes. If we did keep noise pipes, the full handshake has to be |
Based on the fallback modified and how the handshake patterns are defined I don't think this is quite correct. I believe this should be:
|
With the removal of IK handshake (#249), is XXFallback to be removed as well? |
Yup, it's removed already in go and js afaik |
Yep, it's not even in rust afaik |
I am closing here since #260 updated the specification to settle on the XX handshake pattern only. Please comment or re-open in case I am missing something. |
The way the Noise Pipes compound handshake protocol is currently spec'd out and implemented has an issue that is causing me to chase my tail a bit.
For a quick recap of terms, our Noise transport uses two main handshake patterns,
XX
andIK
. TheXX
handshake takes 1.5 roundtrips and 3 handshake messages, whileIK
takes only one roundtrip and 2 messages.IK
can fail, either because the other peer doesn't support it, or because their static key has rotated.When
IK
fails, we "fallback" to using what is essentially theXX
pattern. The Noise framework spec fallback modifier section describes theXXfallback
variation onXX
that can be used to recover from a failedIK
attempt.When I was writing the noise-libp2p spec, I misunderstood how the fallback process is supposed to work. In the bit on Noise Pipes flow, I wrote:
The thing is,
XX
andXXfallback
aren't actually directly compatible with each other. Since they're defined in the Noise framework spec as separate handshake patterns, they are supposed to have different Noise protocol names -Noise_XX_25519_ChaChaPoly_SHA256
vsNoise_XXfallback_25519_ChaChaPoly_SHA256
. The hash of the protocol name is used to initialize both parties handshake states, so they have to match to complete the handshake.The go implementation does (mostly) work though, because we're not setting the correct protocol name for
XXfallback
. The Noise Explorer generated code doesn't directly supportXXfallback
, so it was "spliced in" by ChainSafe when they kicked off the implementation, but the protocol name is alwaysXX
. I'm pretty sure JS is doing the same. So things work at the moment, but only because we're not quite correctly following the Noise framework spec.Well, I say "things work" now, but there is one scenario that's broken in Go (and possibly JS, need to test). If the initiating peer (Alice) supports Noise Pipes, but responder Bob doesn't, the handshake fails. I think the failure is caused by our not-quite
XXfallback
implementation leading to Alice and Bob not agreeing on the contents of the first message in the sequence.I came up with a way to "make it work" with the current approach, but it's super awkward. I would prefer to just do
XXfallback
correctly, which would actually be pretty easy in Go, since it's supported by https://github.com/flynn/noise, which I've discovered is much nicer to work with than the Noise Explorer code.There is a new complication introduced by doing
XXfallback
correctly though. When Bob is responding to an incoming handshake, he needs to determine whether it's anIK
orXX
attempt. Right now, we always tryIK
, then fallback if that fails. However, ifXX
andXXfallback
aren't directly compatible, that won't work. Alice will send anXX
message, but get anXXfallback
response.There are two ways that I can think to deal with that.
The initial
IK
message is larger than the minimum size of an initialXX
message, so we could distinguish between them based on size, instead of
always trying to decrypt as
IK
. Then Alice would never receive anXXfallback
response to anXX
message.We always use
XXfallback
, even for full 1.5 RTT "XX-style" handshakes.For the full handshake, Alice generates a new ephemeral key and sends it over
the wire, but doesn't incorporate the outgoing message into her handshake
state. Bob reads the key and initiates an
XXfallback
handshake to Alice,using the key he read as pre-message knowledge. Alice initiates her handshake
as an
XXfallback
responder, using the key she generated as her localephemeral key. This
XXfallback
all the time pattern is described in thehandshake indistinguishability section of the Noise framework
spec.
If we don't care about handshake indistinguishability (whether outside observers
can guess whether we're doing
XX
orIK
), then option 1 is easy. It's alsonice because not all Noise libraries support fallback patterns. If we
distinguish based on message size, we could still use those libraries and just
not implement Noise Pipes, and we'd still be compatible with peers that do
support Pipes.
With option 2, everyone has to support
XXfallback
whether they support NoisePipes or not.
cc the noise spec interest group: @raulk, @tomaka, @romanb, @shahankhatch, @Mikerah, @djrtwo, @dryajov, @mpetrunic, @AgeManning, @morrigan, @araskachoi, @mhchia
The text was updated successfully, but these errors were encountered: