Ktor 3.0.0 Help

SSL and certificates

In most cases, your Ktor services are placed behind a reverse proxy such as Nginx or Apache. This means that a reverse proxy server handles security concerns, including SSL.

If necessary, you can configure Ktor to serve SSL directly by providing a path to a certificate. Ktor uses Java KeyStore (JKS) as a storage facility for certificates. You can use keytool to convert and manage certificates stored in KeyStore. This might be useful if you need to convert a PEM certificate issued by a certificate authority to the JKS format supported by Ktor.

Generate a self-signed certificate

Generate a certificate in code

Ktor provides the ability to generate self-signed certificates for testing purposes by calling the buildKeyStore function, which returns a KeyStore instance. To use this function, you need to add the ktor-network-tls-certificates artifact in the build script:

implementation("io.ktor:ktor-network-tls-certificates:$ktor_version")
implementation "io.ktor:ktor-network-tls-certificates:$ktor_version"
<dependency> <groupId>io.ktor</groupId> <artifactId>ktor-network-tls-certificates-jvm</artifactId> <version>${ktor_version}</version> </dependency>

The code snippet below shows how to generate a certificate and save it to a keystore file:

import io.ktor.network.tls.certificates.* import java.io.* fun main() { val keyStoreFile = File("build/keystore.jks") val keyStore = buildKeyStore { certificate("sampleAlias") { password = "foobar" domains = listOf("127.0.0.1", "0.0.0.0", "localhost") } } keyStore.saveToFile(keyStoreFile, "123456") }

Since Ktor requires a certificate when it starts, you have to create a certificate before starting the server. You can find the full example here: ssl-embedded-server.

Generate a certificate using keytool

You can use keytool to generate a self-singed certificate:

keytool -keystore keystore.jks -alias sampleAlias -genkeypair -keyalg RSA -keysize 4096 -validity 3 -dname 'CN=localhost, OU=ktor, O=ktor, L=Unspecified, ST=Unspecified, C=US'

After executing this command, keytool suggests you specify a keystore password and then generates a JKS file.

Convert PEM certificates to JKS

If your certificate authority issues certificates in a PEM format, you need to convert it to the JKS format before configuring SSL in Ktor. You can use openssl and keytool utilities to do this. For example, if you have a private key in the key.pem file and a public certificate in cert.pem, a conversion process might look as follows:

  1. Convert PEM into the PKCS12 format using openssl by using the following command:

    openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 -name "sampleAlias"

    You will be prompted to enter a passphrase for key.pem and a new password for keystore.p12.

  2. Convert PKCS12 to the JKS format using keytool:

    keytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -destkeystore keystore.jks

    You will be prompted to enter a password for the keystore.p12 file and a new password for keystore.jks. The keystore.jks will be generated.

Configure SSL in Ktor

Specifying SSL settings in Ktor depends on the way used to configure a Ktor server: by using a configuration file or in code using the embeddedServer function.

Configuration file

If your server is configured in the application.conf or application.yaml configuration file, you can enable SSL using the following properties:

  1. Specify the SSL port using the ktor.deployment.sslPort property:

    ktor { deployment { sslPort = 8443 } }
    ktor: deployment: sslPort: 8443
  2. Provide keystore settings in a separate security group:

    ktor { security { ssl { keyStore = keystore.jks keyAlias = sampleAlias keyStorePassword = foobar privateKeyPassword = foobar } } }
    ktor: security: ssl: keyStore: keystore.jks keyAlias: sampleAlias keyStorePassword: foobar privateKeyPassword: foobar

You can find the full example here: ssl-engine-main.

embeddedServer

If you use the embeddedServer function to run your server, you need to pass a custom environment and provide SSL settings there using sslConnector:

import io.ktor.network.tls.certificates.* import io.ktor.server.application.* import io.ktor.server.engine.* import io.ktor.server.netty.* import io.ktor.server.response.* import io.ktor.server.routing.* import org.slf4j.* import java.io.* fun main() { val keyStoreFile = File("build/keystore.jks") val keyStore = buildKeyStore { certificate("sampleAlias") { password = "foobar" domains = listOf("127.0.0.1", "0.0.0.0", "localhost") } } keyStore.saveToFile(keyStoreFile, "123456") val environment = applicationEngineEnvironment { log = LoggerFactory.getLogger("ktor.application") connector { port = 8080 } sslConnector( keyStore = keyStore, keyAlias = "sampleAlias", keyStorePassword = { "123456".toCharArray() }, privateKeyPassword = { "foobar".toCharArray() }) { port = 8443 keyStorePath = keyStoreFile } module(Application::module) } embeddedServer(Netty, environment).start(wait = true) }

You can find the full example here: ssl-embedded-server.

Last modified: 14 December 2022