Open Stebalien opened 5 years ago
Implement the proposed TLS1.3 PSK extension: https://tools.ietf.org/html/draft-ietf-tls-tls13-cert-with-extern-psk-00. This allows mixing the pre-shared key with the result from the handshake.
We're in the unfortunate situation where the Go team effectively froze crypto/tls
(with the exception of security-related bugfixes). It doesn't seem like they are planning to implement any new features.
quic-go already uses a fork of crypto/tls
, however, I'd feel more confident in the security properties if we don't mess too much with the key schedule.
Add the ability to layer on some kind of trivial packet-based encryption protocol. We can use the same crypto as the current private network library as long as we use a new nonce per packet.
This is something we could do outside of quic-go. Effectively, we'd encrypt every QUIC packet that's being sent out. We'd either have to define a header that specifies the nonce of the packet, or use part of the QUIC packet payload as a nonce (for example the last 16 bytes of the packet, and leave those unencrypted). Aside from the obvious downside of double encryption, this would run against our efforts to make our traffic resemble commonly used internet protocols though.
I'm leaning towards just encrypting each packet with a format: <nonce><enc-message><hmac>
. That's what we do in go-libp2p-pnet (well, minus the MAC; we're relying on the actual transport for authentication in that case...).
Having some form of private network (symmetric key) support in QUIC is needed before we can switch over to it by default. What's the status here? Can we mix in a symmetric key or are we going to have to introduce a packet-based pnet implementation?
There's not been any progress in Go's standard library TLS implementation, which we'd need to mix in symmetric keys.
Is there a third option here? Can we do the encryption on a stream level?
Is there a third option here? Can we do the encryption on a stream level?
Not really. We'd leak the peer IDs at that point. We can probably find some kind of dead-simple symmetric-key encrypted packet transport. I'll ask on #libp2p to see if someone knows of a good one.
This might be a crazy idea. What about only encrypting the certificate (or the libp2p extension in the certificate)?
That would definitely hide the peers. However:
Thoughts @Kubuxu? You implemented the original version.
Another option would be to only encrypt Handshake packets. Let me explain: QUIC uses different packet types during the Handshake:
All packet types are identifiable from the wire image, i.e. no knowledge of the keys is necessary. Every packet type starts with a header, which, depending on the packet type, includes information like connection ID(s), QUIC version etc.
If we encrypt the payload (i.e. everything that comes after the QUIC header) of Handshake packets, we get the following properties:
However, an active attacker would notice that something's going on when trying to dial such a peer, since it would receive undecryptable Handshake packets. That might allow him to conclude that the node might be using a private network. This applies to most of the other solutions as well though.
I'm not sure if I prefer this solution. Encrypting the libp2p extension still seems a bit cleaner to me than modifying already encrypted packets, if we can live with exposing the fact that a node is (probably) running in private network mode.
@Stebalien, @Kubuxu How can we move forward with this issue? Looks like we have a few different options, each with its pros and cons, and we need to make a decide which one we'll go with.
Copying from Slack. @raulk raised the following point:
The problem with encrypting only the certificate is that if I happen to get access to a node’s private TLS key (single-use or not, as per libp2p-tls spec), and I record the certificate sent in a handshake, I could replay the encrypted certificate as-is on a new connection, and I would’ve bypassed the PSK security entirely, and I’d be able to interact with any node in the pnet using only the private key I obtained.
(without ever knowing the PSK)
Hey, I missed this. I will review in next few days.
@Kubuxu Nothing new here. I just moved the issue to go-libp2p because we've moved go-libp2p-quic-transport into go-libp2p. No idea why GitHub is sending out notifications for that :(
Currently, the QUIC transport is incompatible with private networks as it doesn't use the pre-shared key in any way.
We have a couple of options: