Drew Crawford wrote: > Hey folks, I know this has been asked before, but it seems it’s been 7 > months, so maybe it’s time for a new one :) > <snip> > > Also, I have some encryption requirements. I’m no stranger to > implementing this, having designed something that worked “well enough for > me" for zeromq. As far as trying to move that work upstream goes, there > were two real problems. One was that everybody says “encryption” and > wants something different, and solving my problem (mostly securing and > authenticating 1:1 REQ/REP sockets) didn’t necessarily solve other > people’s problems. In my view there is no one-size-fits-all solution. > There are some better and worse ones, but nothing that works for > everybody, and if you hold out for that solution you get nothing, and thus > is the state of zeromq. Yeah, there really are a lot of different things 'encryption' can mean (and some things people think it means when it doesn't). First of all, we need to distinguish between the three purposes cryptography is used for: identity, confidentiality, and integrity. 'Encryption' is _properly_ only used to refer to things that provide confidentiality. Second, we need to distinguish _what_ we are trying to prove about ourselves(identification)/keep secret(confidentiality)/prevent tampering with(integrity), and who we are trying to prevent from interfering. For instance, if we want to make sure that node A is a valid participant of topology B and that communications within the topology cannot be eavesdropped by anything outside it, that's best solved by node-to-node/hop- to-hop security along the lines of TLS, or possibly tcpcrypt + authentication. (Have the topology name in the SubjectAltName of the per- node certificate or some similar approach). This is probably not _too_ hard to implement (warning: W.A.G. in progress), and can be used (with configuration) to ensure that only trusted nodes participate, and thus content is only seen in unencrypted form by trusted nodes. This would be implemented per-transport - inproc:// probably doesn't really need it, ipc:// can do it as long as we're using SOCK_STREAM because generally TLS APIs allow you to plug in another socket, tcp:// is obvious, etc - I'd actually suggest using a notation like tcp+tls:// instead of a new tls:// transport, to allow for the ipc+tls:// case (or if something replaces tls someday). I will also note that authentication and/or key exchange for multicast is a very hard problem indeed, and we'll want to think about that going forward if we ever want to implement a multicast transport like zmq had. On the other hand, if we want to make sure that data passing through untrusted nodes is still confidential and has not been tampered with (i.e. end-to-end security), we need to do something on a per-topology basis, and that way lies the risk of rolling our own crypto. That has real, large risks of doing it very very wrong. It's also going to be very difficult. For instance, REQ/REP is stateless - any such system that is implemented on _top_ of REQ/REP cannot require a round trip to handshake, it needs to be single-pass. You might be able to get away with something like OpenPGP for REQ/REP - it's one-pass stateless message sending, although you need to know the recipient's public key. However, that could come from the configuration service. If you bootstrap it via a pre-loaded key for the conf service, you'd have a well-rooted trust path (you would need to provide some id to look up your key by for the _return_ path though). However, that provides no forward secrecy - if someone managed to store all of your old REQs in encrypted form and then yoinked the node's private key, they could go back and decrypt them all at any later time. It's things like that which convince me that even if we _can_ do end-to-end, I think that at least _some_ users will need both hop-to-hop (which would prevent anyone other than a trusted node from participating in the topology/saving those old messages) and end-to-end (to guarantee that the node replying to you is the one you meant to ask). > The other issue is that there was no real obvious way to inject > authentication/decryption modules into the zeromq codebase. (That stuff > minimally requires a handshake before any packets are sent, for example, > so it’s not just as simple as running a function on packets as they enter > the queue). As a result I just did something at the application level, > which is impossible to upstream. My thinking is that in nanomsg I could > perhaps implement encryption as a protocol or transport…maybe… and get it > merged in. Thoughts? Eh, a handshake may not be necessary (depending on the layer, and possibly in the universal sense) - if the right parameters are known ahead of time, you can do some cool things with no handshake at all. (However, any suite providing perfect forward secrecy _does_ require a round trip to the best of my knowledge, which is certainly a possible issue). Also, if what you're doing at the application level expects a REQ/REP to keep state between requests, that's a violation of the spirit of REQ/REP IIUC. tl;dr: I think implementing something that is either an option to the lower- layer transport or another state machine between transport and the SP framing is a good thing to do in the near term, but doing anything end-to- end will require lots of very careful thought and consulting people considerably better at cryptography than myself.