Blog Infos

A few weeks ago I started with a simple question — how to work with file uploads in Ktor server application? I just set up a sample project for having a playground for experiments. That was the plan, but because I read an article about secure file transfer before, I’ve got the idea to combine both topics. So the project “ktor-encryption-server” was born. The first and only requirement I tried to solve, was to provide a secure way to transfer a file form one user to an other. There was nothing more at the beginning.

Now some weeks later out of the playground project, which even had no automated tests, because there was never the intention to make this public, surprisingly a more serious project has grown and I write this article to describe, what I have done until today.

As already mentioned, the main use-case the ktor-encryption-server should solve, is the secure transfer of files from one user to an other. There are 2 different methods available for encryption of files, using symmetric encryption algorithms or asymmetric ones. It’s not part of this article to compare both in a scientific way. You can find a lot of information regarding this topic (e.g. Symmetric-vs-Asymmetric-Encryotion) googling for it.

For the ktor-encryption-server project I used the symmetric AES algorithm (see for additional information) with a key length of 256 bytes. The Advanced Encryption Standard (AES) is a specific subset of a block cipher called Rijndael. AES only includes three flavors of Rijndael: AES-128, AES-192, and AES-256. The difference between these flavors is the size of the key and the number of rounds used, but–and this is often overlooked–not the block size.

Today this algorithm is treated as secure, even if super computers are used for breaking it. There are multiples modes available for the AES algorithm:

  • ECB mode: Electronic Code Book mode.
  • CBC mode: Cipher Block Chaining mode.
  • CFB mode: Cipher FeedBack mode.
  • OFB mode: Output FeedBack mode.
  • CTR mode: Counter mode.

I choosed GCM which is a counter mode and has a high throughput.

This is all regarding the encryption mechanism theory I will explain in this article.

The AES encryption is used for 2 use-cases of the application:

  • User password (for storing to database)
  • Upload file content (for local storage of the file)

In the next part I will give an overview about the functionality which is provided by the ktor-encryption-server until today (the development is still under progress but the base functionality is available).


To be able to upload files it is necessary to register an user which is specified by an username (which must be unique across the server) and a password, which has to fulfill requirements. There is no coupling of a user to a mail address.

The password requirements are fix at the moment, that means every password has to fulfill the following:

  • Has a length of at minimum 16 characters/digits
  • Contains at minimum one digit
  • Contains at minimum one uppercase character
  • Contains at minimum one lowercase character
  • Contains at minimum one special character.

I use the functionality of org.passay for this.

The concrete endpoint definitions can be found as postman collection inside the repository. It’s also planed to provide an OpenAPI specification in future.

The following use-cases need a basic authentication of an existing user.

Changing Password

The user is able to change the initial password. For the new password the same requirements are active as for the initial creation

Changing Settings

The user is able to change user related settings, at the moment this is just the amount of days, until when an uploaded file expires and is removed from the server.

Upload File (s)

The user can upload one or more files to the server. For every file, an encrypted filename and a random generated password (with the same requirements as for the user password) is returned. These information is necessary for downloading the file.

Get Uploaded Files

The user can get an overview about all the currently active files, which are uploaded by him. Expired (and removed files) are not part of this information.

Get Upload File History

The user can get an overview about the operations which are done with every single uploaded file. Currently the upload and every download are part of the history. The history is removed as soon as the uploaded file expires.

Delete Uploaded Files

The user can delete an uploaded file. It’s only possible to delete a single file at once.

Delete User

The user can delete the account, what will also removes all active uploaded files, with the corresponding history.

Download file

There is one operation, which is not bound to an user, the download of an uploaded file, by specifying the encrypted filename and the password. It’s not possible to download multiple files at once.

Server Configuration

There are several settings available which have defaults set in the application.conf file, but can be customized by overriding them.


By default ktor-encryption-server is using a h2 file database. This is no solution for productive use, but enough for the current demo.

database { 
         driverClass = "org.h2.Driver" 
         url = "jdbc:h2:file:./db" 
         user = "root" 
         password = "password" 
         maxPoolSize = 10 


Job Offers

Job Offers

There are currently no vacancies.



Encryption Parameter

The parameters for the encryption process can also be customized by change the defaults shipped with the application

security { 
         fileIntegrityCheckHashingAlgorithm = "SHA-512" 
         defaultPasswordKeySize = 256 
         defaultNonceLength = 32 
         defaultSaltLength = 64 
         defaultIterationCount = 10000 
         defaultGcmParameterSpecLength = 128 

Keep in mind that the parameters are not validated on server startup. That means if they are not valid unexpected results during encryption will occur.

Upload Location

The uploads are saved by default in a upload directory relative to the working directory of the application. This can be changed to every path, as long as the application has write access to it.

    directoryPath = "./uploads"
Server Tasks

There are tasks running on the server which are triggered in fixed period. Until now it is not possible to customize the task execution period.

Cleanup Task

The cleanup task is daily scanning the configured upload directory for files which have no related entry in the database. This so called “orphaned” files cannot be decrypted because the encryption information is no longer available, even the password is still there. Therefore the files are removed. Normally this should not occur, because deleting upload file entry in database also deletes related file in upload directory. But by mistake or error it is possible (e.g. file locked because of access). The cleanup is for this cases.

Expiration Task

The user has a expiration period for upload files specified in the settings. The expiration task is regularly checking if this period is gone and the upload file needs to be removed. The process of removing is doing the following steps:

  • Remove the upload file in database.
  • Remove the history in database related to this upload file.
  • Remove the file in the upload directory.
Running the application

The ktor-encryption-server application can be executed as docker image thanks to a ktor plugin. Using the following commands can start the server on port 8080 by default:

gradle buildImage
gradle runDocker

In the last part I will give an overview about planed features, that will be implemented soon:

  • Make password settings configurable
  • Make maximum upload size configurable
  • Move default expiration period to application.conf
  • Add OpenAPI specificatoin
  • Optimize serving download content (not storing decrypted version on server temporarily, but directly streaming to consumer)
  • Add client for better usability

Current version of ktor-encryption-server is 0.0.1 and can be found on Github repository:

You can find additional information about the application in the Readme file of the repository

This article was originally published on on October 25, 2022



This tutorial is the second part of the series. It’ll be focussed on developing…
We recently faced a problem with our application getting updated and reaching slowly to…
If you seek to unlock the potential of a powerful trifecta — Ktor, PostgreSQL,…
One of the main functions of a mobile phone was to store contacts information.…

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.