ptrd / kwik

A QUIC client, client library and server implementation in Java. Supports HTTP3 with "Flupke" add-on.
GNU General Public License v3.0
390 stars 57 forks source link

MissingKeysException: Missing keys for encryption level Handshake (keys not installed) #38

Closed tzaeschke closed 6 months ago

tzaeschke commented 6 months ago

I am trying to connect to an HTTP/3 website via FLUPKE over KWIK. It gives me the following result:

0.005 -> Packet I|0|L|1200|2  Token=[] CryptoFrame[0,248] Padding(905)
0.019 <- (1) Packet I|1|L|45|1  Token=[] ConnectionCloseFrame[TLS 120|0|]
0.032 Error: Discarding packet (44 bytes) that cannot be decrypted (net.luminis.quic.crypto.MissingKeysException: Missing keys for encryption level Handshake (keys not installed))
0.032 -> Packet I|1|L|1201|3  Token=[] ConnectionCloseFrame[0|0|] AckFrame[1|Δ0] Padding(1153)
0.019 <- (2) Packet I|0|L|1200|3  Token=[] AckFrame[0|Δ0] Padding(1028) CryptoFrame[0,123]
0.033 <- (3) Packet I|1|L|45|1  Token=[] ConnectionCloseFrame[TLS 120|0|]
0.034 Error: Discarding packet (44 bytes) that cannot be decrypted (net.luminis.quic.crypto.MissingKeysException: Missing keys for encryption level Handshake (keys not installed))
Request failed: Connection timed out after 3000 ms

Process finished with exit code 0

The test application is (mostly) based on net.luminis.http3.sample.Sample.

I debugged a little and it seems that ConnectionSecrets.serverSecrets has only one entry at position 0 (=EncryptionLevel.Initial), there is no entry for Handshake (position 2). It looks like ConnectionSecrets.computeApplicationSecrets() is never called. Why would that not be called?

Note: I am using a slightly modified version of KWIK 0.8.9 which is used by the latest FLUPKE. "Slightly modified" because I am using a custom DatagramSocket and DNS resolver. There is a chance that the problem is somehow caused by my own code, but currently I assume that this is somehow a configuration problem. Would you have any pointers why this exception occurs?

ptrd commented 6 months ago

Hi, Thanks for reaching out. I'm sorry about the confusing "Error", which actually is not (necessarily) an error, it can (and does) happen in normal succesful connection setups. In this case, the problem is that the server closes the connection before the handshake is really started (i.e. in response to the initial packet of the client). The reason the server closes the connection is TLS error 120, which (see https://datatracker.ietf.org/doc/html/rfc8446#autoid-64) is no_application_protocol. Could it be that your client does not include an ALPN? Or maybe with a value the server does not like? Hth Peter

tzaeschke commented 6 months ago

Thanks, that hit the spot :-)
Turns out the server uses https over QUIC, not HTTP3.

I have a related question: I needed to modify the KWIK library in order to provide a custom DNS resolver when the URL is resolved.

I currently added a method QuicClientConnectionImpl.BuilderImpl.addressResolver(Builder.AddressResolver resolver) with

        @FunctionalInterface
        interface AddressResolver {
            InetAddress resolve(String hostName) throws UnknownHostException;
        }

Background is that I work on an open-source library for the SCION project which provides an alternative for BGP routing. SCION currently requires an alternative way for looking up addresses that understand SCION.

I would be happy to propose (without expectations) a PR for alternative address resolution, would that be interesting for you (independent of whether you are interested in SCION or not)?

ptrd commented 6 months ago

Thanks for the follow up.

With respect to the custom resolver: wouldn't it be better to use https://bugs.openjdk.org/browse/JDK-8263693 or are you not able because of Java 18 prerequisite?

tzaeschke commented 6 months ago

Thanks a lot for pointing me to JEP 418. I wasn't aware of this and this is exactly what we would need. Unfortunately, we are currently aiming for Java 8, not 18. Aiming for Java 8 is admittedly quite conservative, but it seems like Java 8 is still widely used (good numbers are hard to come by). KWIK uses Java 11, but we also need to support other protocols.

I think I need to look into this a bit more and I may come back to you later.

Thanks again! Great library btw :-)

ptrd commented 6 months ago

Thanks for the praise. ;-) And if the Java 18 path doesn't work out for you, I have no problem with integrating your proposal. Making Kwik better customizable is a good thing anyways; did already add similar extension points in the past.