Earlier quoted context omitted.
Can you express this with Noise framework tokens? I don't think you can. Noise is fiddlier than it looks! It's not just an ordering of DH exchanges; it's transcript hashes, cipher state tracking (and reinitializing), key derivation, the whole 9. The temptation (at least for me) is to just skip to the table of handshakes and skim, but the actual protocol framework is in Section 5, where they define precisely what each…
Gotta say that I generally like the Noise framework (or rather the protocols that result), but it is one of the most impenetrable specifications I've ever read I don't remember what it is specifically about it, I just remember the document being a pain to read; a bit like the original Paxos paper in that regard.
Whisper: Wraps any Go io.ReadWriter in a secure tunnel using Ed25519/X25519
21–27 of 27 posts
Re: Whisper: Wraps any Go io.ReadWriter in a secure tunnel using Ed25519/X25519
#22Earlier quoted context omitted.
Yeah, I don't mean to be coy. You can't end up with this protocol using Noise. :)
ECIES is quite fine though for most asynchronous applications, where having a signing key also makes sense as you often want to publish long-lived, signed data and build a trust chain (e.g. generate and sign session keys from a master key). I built several real-world systems based on that (e.g. [1]) and they all made it through the audits fine. I was exploring Noise-based protocols but I find it's best to rely on pri…
Re: Whisper: Wraps any Go io.ReadWriter in a secure tunnel using Ed25519/X25519
#23There is no description of the protocol or of its security goals, so I am making some guesses based on a cursory look at the source and what I imagine this might be for. A single symmetric key is derived for both directions, and there is no checking of nonces, so as far as I can tell any message can be dropped, reordered, or replayed in both directions. (Including replaying message from A to B as if they were from B…
Re: Whisper: Wraps any Go io.ReadWriter in a secure tunnel using Ed25519/X25519
#24Earlier quoted context omitted.
You're kinda looking at the interface issue backwards. Being an io.ReadWriter is a promise that the tunnel code won't do anything other than read or write. The tunnel code shouldn't be getting local and remote addresses or setting deadlines of its own, or most of the rest of what net.Conn can do. https://pkg.go.dev/net#Conn It is good that it doesn't take more than it needs. That bytes.Buffer happens to implement io.…
Sure, in general you want to use the narrowest possible interface. But in this particular case, I think `net.Conn` communicates intent better than `io.ReadWriter` -- the former implies that two distinct parties are involved, whereas `io.ReadWriter` is usually for (single-user) buffers or files. Sometimes it's sensible to use a larger interface than necessary; e.g. if you have a helper function that only calls `SetDea…
If you're worried about someone using bytes.Buffer as their transport layer, net.Conn doesn't fix that; there is net.Pipe. (It's not buffered, though.)
Re: Whisper: Wraps any Go io.ReadWriter in a secure tunnel using Ed25519/X25519
#25Don't put a mutex in your io.Reader. It is assumed that, unless mentioned in the documentation, it is not safe to use anything in Go from multiple goroutines. If someone wants to make the reader synchronous for use among multiple goroutines, they can do so themselves. But it's so rare that it's unlikely anyone would want this.
read/write mutexes typically perform worse than a plain mutex. You pay a performance cost to prevent readers and writers from starving each other; if you don't care (and this code doesn't), use a Mutex. https://zephyrtronium.github.io/articles/rwmutex.html
Finally, it's fine to embed the mutex value directly in your struct if your methods take pointer receivers. &MyThing{Mutex: new(sync.Mutex)} is pretty weird to see. If the mutex were included as its value, then the zero value of MyThing is ready to use; &MyThing{} has a new mutex in it. (You can't copy the value of &MyThing either way; a correct copy requires holding the mutex. The reason to embed a *sync.Mutex instead of a sync.Mutex is so that you can copy the containing type, but that is actually unsafe. You grab a pointer to the wrong Mutex in your copy, and you also copy data protected by the mutex without holding it. So your methods MUST have a pointer receiver either way, and thus the indirection to *sync.Mutex is unnecessary.)
Re: Whisper: Wraps any Go io.ReadWriter in a secure tunnel using Ed25519/X25519
#26https://github.com/sillystack/api/blob/main/transport/transp...
The code is very fresh and hasn't yet gone through a audit so please don't use it for anything where security actually matters.
Re: Whisper: Wraps any Go io.ReadWriter in a secure tunnel using Ed25519/X25519
#27There is no description of the protocol or of its security goals, so I am making some guesses based on a cursory look at the source and what I imagine this might be for. A single symmetric key is derived for both directions, and there is no checking of nonces, so as far as I can tell any message can be dropped, reordered, or replayed in both directions. (Including replaying message from A to B as if they were from B…
https://github.com/sillystack/api/blob/main/transport/transp...
I'm not going to make any security claims as of now (it's almost certainly broken) but it uses the Noise IK handshake.
Long term I think NoiseSocket would be a good way to go https://noisesocket.org/post/1/ but perhaps in service-to-service use cases ciphersuite negotiation can be simplified.