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

Consider using WebRTC as transport for signing protocol messages #366

Closed
ameba23 opened this issue Jul 5, 2023 · 4 comments
Closed

Consider using WebRTC as transport for signing protocol messages #366

ameba23 opened this issue Jul 5, 2023 · 4 comments

Comments

@ameba23
Copy link
Contributor

ameba23 commented Jul 5, 2023

This was proposed by Jake.

We discussed using websockets for protocol messages and they have two limitations:

  • We can't create TLS over Websocket (wss) connections from the browser without having a certificate from a certificate authority.
  • We can make browser-to-server connections but not browser-to-browser connections. So the only way two users can communicate with each other would be by relaying messages through a server.

WebRTC enables direct browser-to-browser connections.

Libp2p has a 'webRTC Direct' protocol which specifically aims to address the issue of needing trusted TLS certificates. This uses TLS as well as noise, so everything is encrypted twice. The reasoning for this is that 'TLS provides confidentiality and integrity but not authenticity'.

The rust implementation of Libp2p does include WebRTC but the docs are not great.

webrtc-rs, which libp2p uses internally has this example showing making communication with a browser using data-channels - which i recommend trying out as it make it easy to see how the signalling needed to set up a connection works.

To initiate a WebRTC connection from the browser to a threshold server:

  • We get our public IP from a public STUN server such as stun.l.google.com and use it to make a Session Description Protocol (SDP) 'offer' message. This all done by the JS RTCPeerConnection API.
  • We could send the SDP 'offer' message in an HTTP request to the threshold server.
  • The threshold server could respond with an SDP 'answer' message with its own connection details (by calling RTCPeerConnection::create_answer).
  • The browser client calls RTCPeerConnection.setRemoteDescription with the answer message, and a data connection is initiated.
  • Data channels are named, so we could have one data channel per protocol session, and give them a unique name (eg: based on the message hash).

snow, the NOISE implementation used by Libp2p is also very well documented.

I don't know whether it would be easier to use libp2p, or to implement noise over webrtc ourselves.

@jakehemmerle
Copy link
Contributor

Nice contextualization and writeup.


Double encryption?

everything is encrypted twice.

I don't think everything gets encrypted twice.

Number 3 under Connection Security seems to indicate Noise is just used to authenticate the user, not encrypt data:

On success of the authentication handshake, the used datachannel is closed and the plain WebRTC connection is used with its multiplexing capabilities via datachannels. See Multiplexing.

Another indicator and important note for implementation (also under Connection Security):

Implementations MAY open streams before completion of the Noise handshake. Applications MUST take special care what application data they send, since at this point the peer is not yet authenticated. Similarly, the receiving side MAY accept streams before completion of the handshake.

@ameba23
Copy link
Contributor Author

ameba23 commented Jul 6, 2023

On success of the authentication handshake, the used datachannel is closed and the plain WebRTC connection is used with its multiplexing capabilities via datachannels. See Multiplexing.

Ah good catch. Thats good. And noise is perfect since we already have X25519 keys.

Also, the 'not very good' docs for libp2p-webrtc i was looking at were for the last stable release (0.3.0). The stuff with certificates is in the more recent 0.6.0-alpha.

Looking at the WebRTC-direct spec again, if i have understood right, the user (browser) never actually needs to send an SDP offer to the server, and the server never send an answer - the user just fills in the details of these messages based on the certificate and other info from the server's multiaddress.

Im still a little bit unclear on why we need to do this meddling with certificates and SDP messages, which diverges from the WebRTC spec. When i follow the data connection example for webrtc-rs linked above, both offer and answer messages contain a certificate fingerprint used for TLS. It seems like we are just packing the same information into the multiaddress format and then unpacking it again.

The noise handshake is a great idea, but i don't understand why not send SDP offer and answer messages.

@jakehemmerle
Copy link
Contributor

jakehemmerle commented Jul 6, 2023

The Noise handshake is only used when we're using WebRTC as the transport for libp2p. Since libp2p's identity system uses Ed25519, the peers can be easily authenticated via the Noise handshake at the WebRTC level. The self-signed certs can quire literally be generated on the fly, and are simply used for confidentiality and integrity.

If we don't use use libp2p, I think we can just use WebRTC and auth nodes via DTLS by importing signing server self-signed certs (maybe stored on-chain and imported via browser light client). This rust-libp2p webrtc transport doc comment explains how WebRTC auth should happen reasonably clearly, and it is not specific to libp2p, nor does it even mention the Noise protocol.

@HCastano
Copy link
Collaborator

HCastano commented Sep 9, 2024

We're not looking into this anymore, can re-open if this becomes relevant again.

@HCastano HCastano closed this as completed Sep 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

3 participants