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

Transit Refactor (no changes in cryptography and framing) #80

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

piegamesde
Copy link
Collaborator

@piegamesde piegamesde commented Sep 12, 2022

OP#1896, OP#1895, OP#2246

Code Review Checklist (to be filled out by reviewer)

  • Description accurately reflects what changes are being made.
  • Description explains why the changes are being made (or references an issue containing one).
  • The PR appropriately sized.
  • New code has enough tests.
  • New code has enough documentation to answer "how do I use it?" and "what does it do?".
  • Existing documentation is up-to-date, if impacted.

@piegamesde piegamesde force-pushed the piegames/noise-transit branch 2 times, most recently from befefe7 to 9ca5fa6 Compare September 12, 2022 13:52
@piegamesde piegamesde marked this pull request as ready for review September 16, 2022 13:02
@piegamesde
Copy link
Collaborator Author

piegamesde commented Sep 16, 2022

Ready for review, but not for merging yet

@piegamesde
Copy link
Collaborator Author

piegamesde commented Sep 21, 2022

The latest commit now also fixes OP#2246. The new behavior is sufficiently compatible with the current relay server, so I think we can already merge this and do not depend on the relay server getting fixed too.

go.mod Outdated
@@ -9,6 +9,7 @@ require (
github.com/klauspost/compress v1.15.0
github.com/mdp/qrterminal/v3 v3.0.0
github.com/spf13/cobra v1.5.0
gitlab.com/yawning/nyquist.git v0.0.0-20211010104234-909e7e222b8f
Copy link

@donpui donpui Sep 23, 2022

Choose a reason for hiding this comment

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

I we confident to use this repo? Seems like this is on low usage / activity repo.
Also go.dev suggest another repo of the same person if I am correct: https://pkg.go.dev/search?q=nyquist&m=

Was this noise library analysed to use: flynn/noise ? Seems quit active and popular.

Copy link

Choose a reason for hiding this comment

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

In general it would be good to carefully assess and discuss new external libraries inclusion as it might raise certain security risks and can lead to compromising whole solution.

Copy link

Choose a reason for hiding this comment

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

Addition some comments from internal discussion:
flynn/noise

  • less code
  • less external dependencies
  • seems to be more popular and active (29 closed PRs from many contributors vs. one person project)

yawning/nyquist

  • better structure
  • slightly higher coverage (85.4% vs 83%, basically similar)
  • author is known for contribution to Tor and low-level cryptographic primitives

Alternative:
(wireguard-go case) mostly we use one of the protocol from the noise family, we could think of implementing that as a module within the project later and get rid of the library at some point later. This helps in keeping the dependencies low

Copy link

@vu3rdd vu3rdd left a comment

Choose a reason for hiding this comment

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

Looks very good. Very nice use of Go's interfaces.

Left some comments. But I suggest we get it in and then address anything else (if at all) as a separate task later.

readHandshakeMsg(expected []byte) error

Close() error
}
Copy link

Choose a reason for hiding this comment

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

Since we are refactoring this part, I am wondering if it makes sense to have it as close to Go's net.Conn interface. We only care about Read(), Write() and Close(). The handshake read/write need not be exposed as part of the interface because it is part of the code that establishes a connection and return a valid Conn. Perhaps a better example would be net/tls module in Go stdlib. The Dial() function encapsulates all the connection handshake etc and returns a Conn type that implements net.Conn interface.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, the handshake is done later on by the transitCryptor abstraction layer. I don't see a good way around this.

}

func (self *wsConnection) writeMsg(msg []byte) error {
return self.conn.Write(self.ctx, websocket.MessageBinary, msg)
Copy link

Choose a reason for hiding this comment

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

So, here, no extra length field added into the record and instead the websocket framing takes care of the length, right?

wormhole/transit.go Outdated Show resolved Hide resolved
@donpui
Copy link

donpui commented Sep 26, 2022

Wasm module is not building up:

➜  wormhole-william git:(piegames/noise-transit) GOOS=js GOARCH=wasm go build -o ../../dist/wormhole.wasm ./wasm/module
# gitlab.com/yawning/x448.git/internal/toolchain
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/toolchain/constraints.go:45:6: undefined: __SOFTWARE_REQUIRES_GOARCH_NOT_WASM__
# gitlab.com/yawning/x448.git/internal/field
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:26:22: undefined: TightFieldElement
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:33:22: undefined: TightFieldElement
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:33:42: undefined: LooseFieldElement
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:37:30: undefined: LooseFieldElement
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:37:50: undefined: TightFieldElement
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:41:27: undefined: TightFieldElement
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:41:51: undefined: LimbUint
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:52:25: undefined: TightFieldElement
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:52:50: undefined: LooseFieldElement
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:52:74: undefined: LimbUint
../../../../../go/pkg/mod/gitlab.com/yawning/x448.git@v0.0.0-20211010103852-8630503de309/internal/field/field.go:52:74: too many errors
# github.com/oasisprotocol/curve25519-voi/internal/field
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:69:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:75:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:84:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:93:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:102:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:108:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:120:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:132:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:174:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:180:11: undefined: Element
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/internal/field/field.go:180:11: too many errors
# github.com/oasisprotocol/curve25519-voi/curve/scalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar.go:551:28: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar.go:555:27: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:35:27: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:40:10: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:48:10: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:57:10: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:64:10: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:71:10: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:76:10: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:127:10: undefined: unpackedScalar
../../../../../go/pkg/mod/github.com/oasisprotocol/curve25519-voi@v0.0.0-20210831082354-38e59a871ca9/curve/scalar/scalar_unpacked.go:127:10: too many errors

@meejah
Copy link
Collaborator

meejah commented Sep 26, 2022

Why are we changing the Transit protocol?

This won't be compatible with anything else...

meejah
meejah previously requested changes Sep 26, 2022
Copy link
Collaborator

@meejah meejah left a comment

Choose a reason for hiding this comment

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

If I understand this correctly, this will make Transit incompatible with all other implementations and completely changes the cryptography.

Why would we do this? What's the motivation here? What's wrong with the extremely standard NaCl cryptography?

@piegamesde
Copy link
Collaborator Author

piegamesde commented Sep 26, 2022

This is currently not active in the Transit layer, but was still added there in order to profit from as many synergies between Transit and Dilation as possible. Also, it allowed me to test the code without having the initial Dilation setup.

But in the end, I'd like to see it officially used in Transit, see magic-wormhole/magic-wormhole-protocols#25 for brainstorming.

Why would we do this? What's the motivation here? What's wrong with the extremely standard NaCl cryptography?

The same questions also apply to why the cryptography was changed for Dilation, since NaCl could have been reused there as well. The only advantage I see is that it takes over the nonce handling, making implementing it securely even more idiot-proof than NaCl's secretbox. Also, we could use authenticated data for the unencrypted length field more or less for free, although I haven't spend a lot of time thinking about this (I don't think this easily works when relay servers are involved)

@meejah
Copy link
Collaborator

meejah commented Sep 26, 2022

So we're not going to deploy this, ever?
Or, what do you mean by "not active in the Transit layer"?

(I don't see the point of changing the existing Transit protocol, when there's Dilation. New protocols should use that. Having two incompatible Transit protocols just means more work for all implementations.)

There's nothing "wrong" with NaCl but when designing a completely new protocol (Dilation) it made sense to use the work Noise had done. However, it doesn't necessarily follow that transit needs to immediately change too.

@piegamesde
Copy link
Collaborator Author

Unless Noise for Transit becomes a thing in the spec, the code path that enables it in Wormhole William will never go live, no.

@meejah
Copy link
Collaborator

meejah commented Sep 27, 2022

All the secretbox code appears to be deleted, though; how can we use a version with this code but still be a secretbox-based transit connection?

(i.e. we want the proper framing, but existing Transit protocol using NaCl)

@vu3rdd
Copy link

vu3rdd commented Sep 27, 2022

The latest commit now also fixes OP#2246. The new behavior is sufficiently compatible with the current relay server, so I think we can already merge this and do not depend on the relay server getting fixed too.

I just wanted to add that, it would be better to handle each tickets in its own PR.

@piegamesde
Copy link
Collaborator Author

The secretbox code was not deleted, it was moved as part of the refactoring: https://github.com/LeastAuthority/wormhole-william/pull/80/files#diff-12b6490102104ebe1fbeb8c4bb576802a73d7466d5913c05dcf92195086e0694R156

it would be better to handle each tickets in its own PR

I think we can all agree on that, but unfortunately there are hard interdependencies between the commits due to the refactoring I had to do in order to properly implement the features. I can split off the last commit in its own PR, but that wouldn't change the fact that it strongly depends on the previous commits.

@piegamesde
Copy link
Collaborator Author

Okay, I've squashed all changes and then committed everything except for the transportCryptorNoise struct. Let's see if it compiles …

@piegamesde piegamesde force-pushed the piegames/noise-transit branch 2 times, most recently from 8169621 to 79b127c Compare September 27, 2022 11:00
@donpui
Copy link

donpui commented Sep 27, 2022

Now wasm is building up

@piegamesde piegamesde changed the title Transit: add noise cryptography Transit: don't add noise cryptography yet Sep 27, 2022
@meejah meejah dismissed their stale review September 27, 2022 17:27

i'm fine as long as we dont deploy non-standard transit

@meejah
Copy link
Collaborator

meejah commented Sep 28, 2022

It would be a lot better to land just the framing fixes without all the re-factoring.

IIUC, the point of the refactoring is to try out Noise -- but landing that on master here means that bringing in future updates from upstream (or pushing changes there) becomes harder, forever. If the intent is different, please describe that :)

I don't anticipate ever wanting to support two different (but nearly identical) Transit protocols -- but that discussion can stay on the protocols repository.

@piegamesde
Copy link
Collaborator Author

Apart from an unnecessary interface indirection (since the interface has only one implementor and one could directly use the implementing struct instead), I think this refactoring is still a net improvement for the code. I wouldn't have done it if not my noise cryptography experiments but now that it is there I would not like to go back.

@meejah
Copy link
Collaborator

meejah commented Sep 29, 2022

I'm not making a value judgement on the refactoring, but given that we still lack a plan at all for dealing with this forked code, any extensive changes to existing code will make synchronizing with upstream harder (whether that's pulling code or pushing code).

Since Transit is a stable protocol (i.e. I don't anticipate any changes to it) and thus unlikely to need future development except for security or bug fixes, those are more great reasons to keep the repositories closer together. That is, a future security fix can be easily pushed to upstream or pulled in from upstream.

@Yawning
Copy link

Yawning commented Sep 30, 2022

Oh neat. I'm biased but I think nyquist is pretty great. I haven't really promoted it much, nor have I worked on it since the Noise spec hasn't changed since I wrote it.

As far as builds failing when targeting WASM. My more recent crypto packages explicitly do not support WASM, as it is impossible to guarantee that things that should be constant time, are in fact constant time.

@Yawning
Copy link

Yawning commented Oct 3, 2022

Although this branch doesn't use it, I went and fixed nyquist so that it works on WASM, under the rationale that "well, everyone else under the sun is ignoring the specification's lack of timing characteristics".

Sorry for the inconvenience.

@meejah
Copy link
Collaborator

meejah commented Oct 3, 2022

Although this branch doesn't use it, I went and fixed nyquist [..]

The next-generation "Dilation" protocol for magic-wormhole does specify Noise-based encryption for the subchannels (and we do have plans to implement that). See e.g. https://github.com/magic-wormhole/magic-wormhole/blob/master/docs/dilation-protocol.md#l2-protocol

Copy link
Collaborator

@meejah meejah left a comment

Choose a reason for hiding this comment

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

I would like to first figure out what our plans are with the upstream Go repository.

Given that we've decided the "redundant" framing is actually the way to go, what's in this branch that's useful is the refactoring.

But, depending on our plans with upstream, this could make it far harder to pull in changes -- and given that Transit isn't going to change or grow a second specified encryption method we really need to understand the implications of even more divergence.

Do we have a ticket anywhere for the fork handling?

@donpui
Copy link

donpui commented Nov 17, 2022

I would like to first figure out what our plans are with the upstream Go repository.

Given that we've decided the "redundant" framing is actually the way to go, what's in this branch that's useful is the refactoring.

But, depending on our plans with upstream, this could make it far harder to pull in changes -- and given that Transit isn't going to change or grow a second specified encryption method we really need to understand the implications of even more divergence.

Do we have a ticket anywhere for the fork handling?

We should not wait for what will happen with upstream for this PR. Upstreaming questions is going separately and we have equally the same risk with any other already merged changes. Additionally this PR cannot go to upstream anyway without other changes included.

As we dropped initial cryptography change and framing fix, so this PR left only as code refactor.
I think it is good code refactor and makes code clean, should help us further while implementing dilation.

As for initial websocket library trouble, seems we are now clear what was the problem at it very much related with Go specific about values, pointer usage. Good article describe why we need to be careful: https://eli.thegreenplace.net/2018/beware-of-copying-mutexes-in-go/

Before merging, I will verify changes once more if they work with Winden and Destiny app.

@donpui donpui changed the title Transit: don't add noise cryptography yet Transit Refactor (no changes in cryptography and framing) Nov 17, 2022
@donpui donpui self-requested a review November 17, 2022 09:40
@meejah
Copy link
Collaborator

meejah commented Nov 21, 2022

We should not wait for what will happen with upstream for this PR.

Yes we should wait; this PR just diverges further.

I'm not convinced any changes in Transit help with Dilation in any way -- can you please describe how?

I'm still -1 on merging this (until the upstream questions are answered).

Or, consider answering: what problem do these 500 lines of changes solve? (i.e. what ticket is fixed or issue solved?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants