1. Context + I am connecting from a client with Kt...
# ktor
i
1. Context + I am connecting from a client with Ktor version 1.2.3 raw socket with TLS to the TCP Input Plugin Version v6.0.3 with Logstash 7.3. 2. Issue + TLS/SSL negotiation fails and I am getting a
TLSException
with error message +
Copy code
Unknown hash algorithm: 8
3. Analysis: - The accuracy of all key and certificate files confirmed with successful openssl: +
Copy code
openssl s_client -connect IP:PORT -CAfile cacert.pem -cert client_crt.pem -key client_key.pem
- The output of
openssl
gives a hint at what might be wrong: + [source,subs="quotes"] .Requested Signature Algorithms:
Copy code
ECDSA+SHA256:**0x04+0x08**:RSA+SHA256:ECDSA+SHA384:**0x05+0x08**:RSA+SHA384:**0x06+0x08**:RSA+SHA512:RSA+SHA1
+ .Shared Requested Signature Algorithms: ---- ECDSA+SHA256RSA+SHA256ECDSA+SHA384RSA+SHA384RSA+SHA512:RSA+SHA1 ---- - I assume that the requested signature algorithms come from the server and include hash code 0x08 (as in
0x04+0x08
) - I also assume that the
0x08
hash code comes from the new "Intrinsic" hash hash code introduced in RFC 8442 and registered by IANA [https://www.iana.org/assignments/tls-parameters/tls-parameters.txt] - Looking into the source code of the TLS handshake routines of ktor-network-tls I find in
io/ktor/network/tls/extensions/SignatureAlgorithm.kt
the following snippet: +
Copy code
kotlin
enum class HashAlgorithm(val code: Byte, val openSSLName: String, val macName: String) {
    NONE(0, "", ""),
    MD5(1, "MD5", "HmacMD5"),
    SHA1(2, "SHA-1", "HmacSHA1"),
    SHA224(3, "SHA-224", "HmacSHA224"),
    SHA256(4, "SHA-256", "HmacSHA256"),
    SHA384(5, "SHA-384", "HmacSHA384"),
    SHA512(6, "SHA-512", "HmacSHA512");

    companion object {
        /**
         * Find hash algorithm instance by it's numeric [code]
         * @throws TLSExtension if no hash algorithm found by code
         */
        fun byCode(code: Byte): HashAlgorithm = values().find { it.code == code }
            ?: throw TLSException("Unknown hash algorithm: $code")
    }
}
- It seems to me that throwing an exception when encountering an unknown hash algorithm is not necessary. The algorithm would be ignored anyway when the list of mutually supported algorithms is build. Questions: . Is my analysis correct? . Should I file an issue for ktor on Github and propose the following change options: .. Add
INTRINSIC(8, "INTRINIC", "Intrinsic")
to the
HashAlgorithm
enum class .. Change the return type of
byCode()
to a nullable and ignore null when building the list of requested hash algorithms . Is there a way to prevent a ruby.openssl based server (not ktor) from sending the new hash code value 8? (Please ignore this question if it does not belong to ktor|kotlinlang)
e
Hi, @Ingo Noka. Thanks for the deep investigation 🙂. It looks like working solution, let’s start from creating an issue here: https://github.com/ktorio/ktor/issues
i
Just saw the commit for this. And I thought you may have the same problem with the list of Encryption algorithms in SignatureAlgorithm.byCiode(...). Is there any way for me to get the updated library to test?
I have tested your fix and it is as I expected. The
byCode()
routine in
enum class SignatureAlgorithm
also fails. This my temporary fix.
The client is now negotiating a common signature/hash algorithm. However, the next problem is in
TLSClientHandshake.handleCertificatesAndKeys(...)
. Look at line 5. I added
+2
, because by adding just size to position we don't take into account that two bytes have already been read for the length/size of the
authority
bit.
packet.readBytes(size)
will therefore fail with something like "... trying to read 2 bytes from empty packet ...".
Finally I ran into another issue here, because KTOR fails to find the CA (which I provided in the
TLSConfig
) in
info.authorities
(which is coming from the server). This seems to be because the DN of my certificate contains an e-mail address element, which KTOR does not parse. KTOR includes the unknown e-mail element as OID/RawData in the DN, so that the comparison between the principal from my CA keystore returns false.
I forced the routine to find my certificate, but now I do not get any reaction from either the server nor the client. I think I will admit defeat for now and move back to good old SSLContext and friends. Thanks for your help so far.