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

libp2p TLS 1.3 Handshake #151

Merged
merged 7 commits into from
Apr 7, 2019
Merged

libp2p TLS 1.3 Handshake #151

merged 7 commits into from
Apr 7, 2019

Conversation

marten-seemann
Copy link
Contributor

@marten-seemann marten-seemann commented Feb 28, 2019

In the last couple of weeks I spent a lot of time designing a TLS 1.3 based handshake for libp2p. This document has come a long way, and I managed to remove a lot of the complexity, while at the same time preserving the future extensibility which I originally built into this version of the protocol.

This is a proposal how we can run the libp2p handshake using TLS 1.3 in the future. Since we're currently only using secio in production, we are completely free to design things the way we want, without having to worry about backwards compatibility. That means that now is the right time to criticize every single aspect of this protocol.

I already implemented a proof of concept in libp2p/go-libp2p-tls#20, feel free to play around with that code as well.

@anacrolix
Copy link

Could you include why we want TLS 1.3-like handshakes? Is it because of 0-RTT, or just keeping up with the times?

tls/tls.md Show resolved Hide resolved

## Peer Authentication

In order to be able use arbitrary key types, peers don’t use their host key to sign the x509 certificate they send during the handshake. Instead, the host key is encoded into the [libp2p Public Key Extension](#libp2p-public-key-extension), which is carried in a self-signed certificate. The key used to generate and sign this certificate SHOULD NOT be related to the host's key. Endpoints MAY generate a new key and certificate for every connection attempt, or they MAY reuse the same key and certificate for multiple connections. Endpoints MUST choose a key that will allow the peer to verify the certificate (i.e. choose a signature algorithm that the peer supports), and SHOULD use a key type which allows for efficient signature computation and which reduces the combined size of the certificate and the signature.
Copy link

@magik6k magik6k Feb 28, 2019

Choose a reason for hiding this comment

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

Do we do this only because Go doesn't support some protocols in it's TLS implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's one reason, the other is #111.

@marten-seemann
Copy link
Contributor Author

@anacrolix it’s in the design considerations. TLS 1.3 just takes a single round trip, older versions take two. And there’s little reason to roll out a new Handshake protocol on top of an old TLS version anyway.

tls/tls.md Outdated

The public key allows the peer to calculate the peer ID of the peer it is connecting to. Clients MUST verify that the peer ID derived from the certificate matches the peer ID they intended to connect to, and MUST abort the connection if it there is a mismatch.

The peer signs its public key using the its host key. This signature provides cryptographic proof that the peer was in possession of the private key at the time the certificate was signed. Peers MUST verify the signature, and abort the connection attempt if signature verification fails.
Copy link
Member

Choose a reason for hiding this comment

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

Q: Which public key is signed?
Q: I feel like it should somehow be bound to TLS session we are establishing. Otherwise, this proof could be "stolen" and reused by someone else.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's the public key used to generate the certificate. I'll update the PR to clarify that.
Why do you want to bind it to the session that we're establishing? What we're doing here is basically creating a certificate chain, with the host key at the root. Just that we're not using x509 certificates, due to the limitations described earlier.

Copy link
Contributor

Choose a reason for hiding this comment

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

I initially thought that the publicKey field of SignedKey was referring to the host key. I think it's this sentence which is a bit ambiguous:

The peer signs its public key using the its host key.

Since you were just talking about the public key for the peer ID in the prior paragraph, I assumed that's what "public key" referred to here.

It's clearer down below, where it says "The publicKey field of SignedKey contains the public key of the endpoint", although it wouldn't hurt to spell out that the endpoint key is the one used to generate the certificate.

Since it is the endpoint key being signed, if you wanted to have the proof be bound to the session as @Kubuxu suggests, you could just generate a new key and self-signed certificate for each session. Is that correct @marten-seemann?

Copy link
Member

Choose a reason for hiding this comment

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

I'm still not clear about which keys, public keys and certificates are being sent over and in which fields.

I don't see cleanly that the chain confirming ownership of key used in TLS handshake is bound to a PeerID.
I have few ideas regarding possible attacks, and possible reuse in case TLS key is leaked but first I need to understand this part fully.

Copy link
Member

Choose a reason for hiding this comment

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

I'm reading it again so bear with me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry for the confusion here. You sign the public key that was used to generate the certificate with your host private key.

The reason is that the key used to generate the certificate is used by TLS during the handshake to sign the CertificateVerify message. By signing the public key of the certificate we get a chain of verified signatures.

Using the host's public key would be a bad idea. An attacker could just copy the contents of the libp2p Public Key Extension and use that to impersonate this peer. We really need an operation that proves that the peer actually meant to use the key used by TLS.


### TLS 1.3 - What about older versions?

The handshake protocol requires TLS 1.3 support. This means that the handshake between to peers that have never communicated before will typically complete in just a single roundtrip. With older TLS versions, a handshake typically takes two roundtrips. By not specifying support for older TLS versions, we increase perfomance and simplify the protocol.
Copy link
Member

Choose a reason for hiding this comment

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

Most importantly, it would make us vulnerable to downgrade attacks.


### Versioning - How we could roll out a new version of this protocol in the future

An earlier version of this document included a version negotiation mechanism. While it is a desireable property to be able to change things in the future, it also adds a lot of complexity.
Copy link
Member

Choose a reason for hiding this comment

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

What about the protocol string in multistream-select? That's a version negotiation mechanism.

Copy link
Member

Choose a reason for hiding this comment

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

Yes but we may want to speak TLS before multistream. That is, we should allow peers to advertise /ip4/.../tcp/443/tls/ipfs/Qm... directly. This should help disguise IPFS traffic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That works for TCP, but not for QUIC. In QUIC, the first packet sent by the client already contains the ClientHello.

tls/tls.md Outdated
}
```

The publicKey field of SignedKey contains the public key of the endpoint, encoded using the following protobuf.
Copy link
Member

Choose a reason for hiding this comment

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

That seems redundant with #100

tls/tls.md Outdated
### libp2p Public Key Extension

In order to prove ownership of its host key, an endpoint sends two values:
- the public key corresponding to its host key
Copy link
Member

Choose a reason for hiding this comment

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

So my main issue is this sentence, I don't understand the difference between public key and host key.

@burdges
Copy link

burdges commented Feb 28, 2019

As Noise is more flexible than TLS 1.3, we might support specific Noise handshakes for specific nodes roles, but TLS 1.3 supports cipher suite agility and conceivably helps obfuscate traffic, but only if integrated with the web-like transports.

As a naive first approximation, we might consider (a) replacing secio with Noise in a way exploits Noise's flexibility, (b) integrate TLS 1.3 with the web-like transports in a way that really permits blending in with web traffic, and (c) correctly permit both Noise and TLS 1.3 to manage authentication using key provided by the application. In fact, there is an enormous nasty can of worms involved in doing traffic obfuscation like I suggest in doing (b), for which the Tor project recruits an army of young, idealistic, and talented developers to write pluggable transports, and for which U.S. State Dept pays them like $2 M per year. We should not compete with them here, so maybe the correct solution for obfuscation is actually TLS 1.3 or Noise running over Tor pluggable transports.

We're left with TLS 1.3 being the only secure protocol with cipher suite agility, and Noise providing more handshake flexibility. Increasingly, we view cipher suite agility as harmful, based in part on how hard doing it correctly proved for TLS, so modern protocols should dump cipher suite agility and simply version instead. IPFS appears rather committed to cipher suite agility though.

Copy link
Member

@raulk raulk left a comment

Choose a reason for hiding this comment

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

Looks like a good start! Thanks, @marten-seemann.

  1. I'd suggest adding a formal definition of the different keys and how they relate to each other.

  2. To my understanding, the peer generates an ephemeral per-session key, and produces a self-signed certificate without using the host key. This certificate then embeds (via certificate extensions) the host's permanent identity public key, and a signature of that public key with its pairing private key.

    Unless I'm mistaken, isn't this scheme subject to man-in-the-middle attacks, where one could replace the outer certificate by extracting the inner host key and injecting it into a new certificate produced with a key they control? I'm sure I'm missing something. It seems there is no cryptographic crosslink between the host key and the ephemeral session key.

P.S.: as per one of my comments, I think using ephemeral session keys oughts to be a MUST requirement, as otherwise we would not guarantee Perfect Forward Secrecy.


### Why we're not using the host key for the certificate

The current proposal uses a self-signed certificate to carry the host's public key in the libp2p Public Key Extension. The key used to generate the self-signed certificate has no relationship with the host key. This key can be generated for every single connection, or can be generated at boot time.
Copy link
Member

Choose a reason for hiding this comment

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

IMO another reason for not using the host key directly is to achieve Perfect Forward Secrecy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TLS 1.3 uses ephemeral Diffie-Hellman for the key exchange mechanism, so it's always PFS, no matter what kind of certificate you use.


## Peer Authentication

In order to be able use arbitrary key types, peers don’t use their host key to sign the x509 certificate they send during the handshake. Instead, the host key is encoded into the [libp2p Public Key Extension](#libp2p-public-key-extension), which is carried in a self-signed certificate. The key used to generate and sign this certificate SHOULD NOT be related to the host's key. Endpoints MAY generate a new key and certificate for every connection attempt, or they MAY reuse the same key and certificate for multiple connections. Endpoints MUST choose a key that will allow the peer to verify the certificate (i.e. choose a signature algorithm that the peer supports), and SHOULD use a key type which allows for efficient signature computation and which reduces the combined size of the certificate and the signature.
Copy link
Member

Choose a reason for hiding this comment

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

I think generating a new key per session should be a MUST, otherwise Perfect Forward Secrecy might be compromised.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let me expand on my earlier comment. In TLS 1.3, the client send a key_share extension in the ClientHello. This key share is the client's ephemeral DH key (i.e. it is a fresh value for every connection). The server sends its part of the ephemeral DH key share in the key_share extension in the ServerHello.
Since TLS 1.3 decouples key exchange mechanism from the signature algorithms, TLS 1.3 handshakes are always forward secure, no matter what kind of certificate you use.

By the way, you might have heard of eTLS 1.3. It's supposed to be used by businesses who want middleboxes to be able to decode their traffic (and who don't care about their customer's privacy). It removes PFS from the protocol by having the server send a static key share in the ServerHello. The sad thing is, there's no immediate way to detect a server that's misbehaving in that way, other than running heuristics over multiple connections.

@marten-seemann
Copy link
Contributor Author

@burdges

As Noise is more flexible than TLS 1.3, we might support specific Noise handshakes for specific nodes roles, but TLS 1.3 supports cipher suite agility and conceivably helps obfuscate traffic, but only if integrated with the web-like transports.

I'm a bit skeptical about obfuscation. As you note, obfuscation done right is really hard, and we even fail at the most basic aspects. The first one is that you'd have to run your node on port 443, a request to a non-standard HTTPS port will immediately stick out. Second, there's the ALPN extension which is sent unencrypted in the ClientHello, and I'd like to avoid putting a fake value into that field. And then there are hard parts like traffic patterns, which are very characteristic for HTTPS traffic, which will probably be impossible to replicate in libp2p.

As a naive first approximation, we might consider (a) replacing secio with Noise in a way exploits Noise's flexibility, (b) integrate TLS 1.3 with the web-like transports in a way that really permits blending in with web traffic, and (c) correctly permit both Noise and TLS 1.3 to manage authentication using key provided by the application.

The advantage of TLS 1.3 at this point is that we can use the same handshake logic on TCP and on QUIC. Noise looks really interesting and we might be able to use it on top of TCP, but it's not obvious how to integrate it into the QUIC handshake.

@marten-seemann
Copy link
Contributor Author

@Kubuxu I just pushed an update that (hopefully) makes it clear which key I'm referring to. Can you please have another look?

@Kubuxu
Copy link
Member

Kubuxu commented Mar 6, 2019

It is much clearer now.

One issue I see (and it is a small issue that depends on our threat model) is if ever the private key for the outside certificate was leaked, it gives the attacker an ability to impersonate owner of the host key forever.

What do you think about this?

@Kubuxu
Copy link
Member

Kubuxu commented Mar 6, 2019

I've created this diagram to make it easier to understand:
libp2p-tls

Source
@startuml
top to bottom direction
object "Cert Key" as certKey


package "x509 Certificate" {
object "Certificate" as cert {
  libp2p Public Key Extensions
}
certKey -[#blue]-> cert : signs

object "libp2p Public Key Extension" as pke {
    hostPubKey : PublicKey
    signature
}

object signature
}

cert --* pke
pke --* signature

object PeerID {
  hostKey
}
PeerID -[#blue]> signature : signs
pke .> PeerID : hostKey proves 
signature .> certKey :  prooves
certKey -[hidden]-> signature
certKey -[hidden]-> pke
certKey -[hidden]-> cert


@enduml

@marten-seemann
Copy link
Contributor Author

@Kubuxu: Thanks for the diagram!

One issue I see (and it is a small issue that depends on our threat model) is if ever the private key for the outside certificate was leaked, it gives the attacker an ability to impersonate owner of the host key forever.

That's true, but I'm wondering if this is a realistic threat. After all, losing your host key would also allow an attacker to impersonate you forever (obviously). If at all, the host key will be more vulnerable to be compromised, since it's typically written to disk (at least for IPFS) and loaded into memory, where as the key for the outer certificate only needs to exist in memory.
That being said, an easy mitigation for this would be to attach an expiration date to the signature, so an attacker could only impersonate the host until that signature expires. Not sure if the additional complexity is justified. What do you think?

tls/tls.md Outdated Show resolved Hide resolved

## Peer Authentication

In order to be able use arbitrary key types, peers don’t use their host key to sign the x509 certificate they send during the handshake. Instead, the host key is encoded into the [libp2p Public Key Extension](#libp2p-public-key-extension), which is carried in a self-signed certificate. The key used to generate and sign this certificate SHOULD NOT be related to the host's key. Endpoints MAY generate a new key and certificate for every connection attempt, or they MAY reuse the same key and certificate for multiple connections. Endpoints MUST choose a key that will allow the peer to verify the certificate (i.e. choose a signature algorithm that the peer supports), and SHOULD use a key type which allows for efficient signature computation and which reduces the combined size of the certificate and the signature.
Copy link
Member

Choose a reason for hiding this comment

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

The key used to generate and sign this certificate SHOULD NOT be related to the host's key.

This precludes the optimization we talked about where a peer MAY derive the certificate key from the host key and the verifier MAY skip verifying the signature in the extension if the key matches the certificate key.

I guess SHOULD allows implementations to do what they want, but we may want to say that implementations MUST NOT reject certificates that use the host key.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, SHOULD means that you're not supposed to do it, unless you think you have good reasons for it. I've described some measurements I did in the Design Considerations, section Why we're not using the host key for the certificate, which led me to conclude that this optimization is not worth it. Do you agree?

Copy link
Member

Choose a reason for hiding this comment

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

It probably isn't but there's no reason to preclude it. Basically, I just don't want some over-zealous dev to reject these keys.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, that's why it's a SHOULD. SHOULD implies that you can't rely on the peer following the recommendation, so I don't think any additional text is needed.

}
```

TODO: PublicKey.Data looks underspecified. Define precisely how to marshal the key.
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a bunch of specs that only live in PRs now, but don't seem to be blocked by anything major. We should get them merged some time, so we can properly refer to them.

Copy link
Member

Choose a reason for hiding this comment

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

Mostly blocked on reviews, IIRC. But yeah, we should just get MVPs merged and mark them as drafts.

tls/tls.md Show resolved Hide resolved

An earlier version of this document included a version negotiation mechanism. While it is a desireable property to be able to change things in the future, it also adds a lot of complexity.

To keep things simple, the current proposal does not include a version negotiation mechanism. A future version of this protocol might:
Copy link
Contributor

Choose a reason for hiding this comment

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

that's a bit of a hole here, let's at least make it compatible with negotiation in the future.

Copy link
Member

Choose a reason for hiding this comment

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

Ideally, that's what (2) below provides. We can use the SNI field as it's sent in the first packet.

Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

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

(LGTM)


An earlier version of this document included a version negotiation mechanism. While it is a desireable property to be able to change things in the future, it also adds a lot of complexity.

To keep things simple, the current proposal does not include a version negotiation mechanism. A future version of this protocol might:
Copy link
Member

Choose a reason for hiding this comment

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

Ideally, that's what (2) below provides. We can use the SNI field as it's sent in the first packet.

Copy link
Contributor

@jacobheun jacobheun left a comment

Choose a reason for hiding this comment

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

Added some minor copy corrections. Overall I think this looks good to mark as Draft and merge.

tls/design considerations.md Outdated Show resolved Hide resolved
tls/design considerations.md Outdated Show resolved Hide resolved
tls/tls.md Outdated Show resolved Hide resolved
tls/tls.md Outdated Show resolved Hide resolved
tls/tls.md Outdated Show resolved Hide resolved
Co-Authored-By: marten-seemann <martenseemann@gmail.com>
@tomaka
Copy link
Member

tomaka commented Mar 23, 2019

For what it's worth, the rustls library (Rust-TLS), which is used by quinn, the only viable QUIC implementation in Rust at the moment, seems to always reject self-signed certificates on purpose (rustls/rustls#143).

If I were to implement this on a short time frame, I'd generate a CA certificate, embed it in the source code as a trusted source, and sign the ephemeral certificates from this CA. But that means we wouldn't be compatible.




### libp2p Public Key Extension
Copy link
Member

Choose a reason for hiding this comment

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

What's the exact string name of the extension to use when generating the certificate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure I understand the question. You can find the OID further down in the document.

@marten-seemann
Copy link
Contributor Author

For what it's worth, the rustls library (Rust-TLS), which is used by quinn, the only viable QUIC implementation in Rust at the moment, seems to always reject self-signed certificates on purpose (rustls/rustls#143).

This sounds like something that should be fixed in rustls. Accepting self-signed certificate should be a basic feature of any TLS library. I really don't want to increase the length of the certificate chain to work around that shortcoming (thereby increasing the number of signature verifications to be performed during each handshake as well as significantly increase the number of bytes transmitted). Any estimate how long would it take to get this fixed in rustls?

@tomaka
Copy link
Member

tomaka commented Mar 23, 2019

Accepting self-signed certificate should be a basic feature of any TLS library.

That's debatable. I'm pretty sure the authors of rustls would disagree.

@Stebalien
Copy link
Member

They probably don't want to blindly trust self-signed certificates but I doubt they'd object to a custom certificate validator if cleanly implemented.

@marten-seemann
Copy link
Contributor Author

@tomaka I'd like to merge this PR very soon. What do you think is the best way forward here?

1. We want to use different key types: RSA, ECDSA, and Ed25519, Secp256k1 (and maybe more in the future?).
2. We want to be able to send the key type along with the key (see https://github.com/libp2p/specs/issues/111).

The first point is problematic in practice, because Go currently only supports RSA and ECDSA certificates. Support for Ed25519 was planned for Go 1.12, but was deferred recently, and the Go team is now evaluating interest in this in order to prioritze their work, so this might or might not happen in Go 1.13. I'm not aware of any plans for Secp256k1 at the moment.
Copy link

@burdges burdges Mar 28, 2019

Choose a reason for hiding this comment

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

You should fork the required library and use Ed25519 using agl's libraries.

ECDSA kinda works but.. secp256k1 should be avoided anyways, due to side channel concerns. RSA should not even be considered for any current use cases, although supporting it for whatever strange future scenarios sounds harmless..

Copy link
Member

Choose a reason for hiding this comment

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

Really, we might wan to rephrase this in terms of ecosystem support. That is, TLS is a rather complicated protocol and we don't want to force libp2p implementations to add support for new key types.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You should fork the required library and use Ed25519 using agl's libraries.

I considered that, but concluded that's it's not a good solution. It would mean pulling in a forked x509 package, and in order to use that one, we'd also have to fork tls just to change the import path.

Copy link
Member

Choose a reason for hiding this comment

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

As a general remark, in my opinion whether or not a library exists in the ecosystem should only be a very minor consideration when writing specs. You want your specs to do the right thing, not the thing that can be implemented the most easily.

Copy link
Member

Choose a reason for hiding this comment

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

Which is why I didn't answer your question "Any estimate how long would it take to get this fixed in rustls?" (#151 (comment))
To me how long something takes to implement is not relevant when discussing specs.

Copy link

Choose a reason for hiding this comment

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

Filo has a branch at golang/go#25355 I'm surprised this takes google so long given agl's role in Ed25519 being accepted by standards bodies.

@marten-seemann
Copy link
Contributor Author

@tomaka: Is there any way to define a custom certificate verifier in rustls. Or if that’s not possible, could you temporarily add the certificate to the root CAs until it is verified?
Would using a different TLS library be an option? I saw that there are multiple TLS 1.3 implementations in Rust.

@tomaka
Copy link
Member

tomaka commented Apr 3, 2019

Is there any way to define a custom certificate verifier in rustls. Or if that’s not possible, could you temporarily add the certificate to the root CAs until it is verified?

It is possible to have a custom verifier, but once a connection is established it is not possible to know which certificate it corresponded to (cc libp2p/rust-libp2p#211 (comment)).
However that can probably be fixed by tweaking rustls.

Again, the specs shouldn't be based on whether they are easy to implement.

@marten-seemann
Copy link
Contributor Author

@tomaka Are you ok with merging the specs as they are now, or do you think we need to change anything?

@tomaka
Copy link
Member

tomaka commented Apr 4, 2019

I'm fine with merging that!

My "regret" is that the libp2p handshake will still be distinguishable from an HTTP handshake, but there's no way to fix that as far as I know.

@Kubuxu
Copy link
Member

Kubuxu commented Apr 4, 2019

@tomaka I'm not sure if it will be distinguishable, TLS1.3 establishes encrypted (not authenticated) channel after ClientHello and ServerHello. Certificate, CertificateRequest are sent in a separate message: EncryptedExtensions.

I think this should make libp2p handshake and https handshake roughly the same.

@marten-seemann
Copy link
Contributor Author

@tomaka: The cleartext messages of the handshake will be identical to an HTTP handshake if we use the same ALPN (the spec doesn't say anything about which ALPN to use, so we're free to specify that later). However, as long as people don't run their nodes on port 443, and connect from random port numbers, libp2p traffic can be easily distinguished from genuine HTTP traffic just by looking at the IP header.

@marten-seemann marten-seemann merged commit adce976 into master Apr 7, 2019
@ghost ghost removed the in progress label Apr 7, 2019
@tomaka tomaka deleted the tls branch April 7, 2019 14:32
@tomaka tomaka restored the tls branch April 7, 2019 14:32
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.