Kotlin PBKDF2 Secure Password Hashing

In this article, we will learn a bit more about Kotlin password hashing, PBKDF2, and how to write a Kotlin code with PBKDF2 in practice.

Introduction

Hello and welcome to the article about Kotlin password hashing with PBKDF2 (to be even more specific- with PBKDF2WithHmacSHA512).

In this hands-on guide, we will:

  • learn why password hashing is important,
  • discover a couple of definitions every programmer should be aware of,
  • and finally- how to hash a password with Kotlin and PBKDF2.

What Is Password Hashing and Is It Important?

Well, password hashing is the process of taking a password and applying a mathematical function (the hash function) to it to produce a fixed-size string of characters- the hash value (also known as digest).

 

Infographic presents example Kotlin password hashing function process.

It’s worth mentioning, that it is a one-way operation. We simply can’t reverse the process and obtain the key from a hash value. So even if attackers gain access to the hashed password in our database, obtaining the original password is difficult.

But difficult, doesn’t mean impossible. Although the process can’t be reversed, attackers can try to crack the password using different combinations of characters and computing the hash value for each combination. And because of that, password hashing algorithms are designed to be computationally expensive, meaning that it takes a long time to compute the hash value for a given password.

So, given these points, we can clearly see that password hashing is important not only when working with Kotlin.

What Does Salt Mean?

Before we dive into the Kotlin password hashing with pbkdf2, let’s learn more about salt.

Salt is a random value that is generated and added to the input data before it is hashed. Thanks to that, the resulting hash will be different even if the original passwords are the same, making it even harder to crack the hashed passwords using precomputed hash tables (also known as rainbow tables).

 

Infographic shows how password hashing function works with salt.

Kotlin / Java Password Hashing Algorithms

And as the last thing before the practice part, let’s take a look at a couple of password hashing algorithms, which we can use when working with Kotlin:

  • MD5 (Message Digest Algorithm 5), which produces a 128-bit hash value. Nevertheless, it’s vulnerable to collision attacks and should not be used for password hashing or other sensitive applications.
  • SHA-512 (Secure Hash Algorithm 512-bit), which produces a 512-bit hash value. Technically, it is considered a secure option, but we have better alternatives.
  • BCrypt– a password hashing function based on the Blowfish cipher and including salt to protect against dictionary attacks.
  • SCrypt– a key derivation function designed for GPU cracking attacks. It uses a large amount of memory, making it more expensive to crack.
  • PBKDF2 (Password-Based Key Derivation Function 2), which is also a key derivation function. It is designed to be resistant to dictionary attacks and uses salt and iterative hashing to increase the cost of attacks.

Image shows two ebooks people can get for free after joining newsletter

Kotlin With PBKDF2 (PBKDF2WithHmacSHA512) In Practice

So, with all of that being said, we can finally start the coding part. As I mentioned in the beginning, we will see how to hash passwords in Kotlin with PBKDF2WithHmacSHA512.

Don’t worry about this monster- it’s a name of an algorithm, which we will use when requesting an instance of SecretKeyFactory. Without going into much detail here, our little monster will generate a 512 bits hash value. (And if you’re interested in a more detailed answer, then check out this StackOverflow topic).

Random Salt

Firstly, let’s implement a function responsible for generating random salt:

fun generateRandomSalt(): ByteArray {
  val random = SecureRandom()
  val salt = ByteArray(16)
  random.nextBytes(salt)

  return salt
}

16-byte salt will be enough. Whatsoever, we create a SecureRandom instance using the default constructor.

But, if we would like to pick a specific algorithm, then we can use the getInstance method instead:

 SecureRandom.getInstance("PKCS11")

We can find the list of all supported algorithms right here.

Lastly, if we would like to convert the ByteArray to a hex String, we can use the formatHex:

private fun ByteArray.toHexString(): String =
  HexFormat.of().formatHex(this)

// so that later, we can simply run:
salt.toHexString()

Generate Hash

As the last thing in our Kotlin password hashing with PBKDF2, let’s implement the generateHash:

private const val ALGORITHM = "PBKDF2WithHmacSHA512"
private const val ITERATIONS = 120_000
private const val KEY_LENGTH = 256
private const val SECRET = "SomeRandomSecret"

fun generateHash(password: String, salt: String): String {
  val combinedSalt = "$salt$SECRET".toByteArray()

  val factory: SecretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM)
  val spec: KeySpec = PBEKeySpec(password.toCharArray(), combinedSalt, ITERATIONS, KEY_LENGTH)
  val key: SecretKey = factory.generateSecret(spec)
  val hash: ByteArray = key.encoded

  return hash.toHexString()
}

As we can see in the first line of our function, we combine the salt with an additional SECRET value. Oftentimes, the salt value is generated for each user in our system, which means that we have to persist it in the database, as well.  So, in case our database data are leaked, we can reduce the risk of password cracking through this additional step.

For simplicity, the secret value is stored as a constant, but in a real-life scenario, we’d rather pass it as an environment variable

In the following lines, we define a SecretKeyFactory instance and a KeySpec with the desired password, salt, iterations and key length values.

Recommended Iterations And Key Length

When it comes to the number of iterations, in 2021 OWASP recommended 120,000 iterations for PBKDF2-HMAC-SHA512. The key length is equivalent to the chance for a hash collision, so it’s good for it to be at least 128 bits.

Kotlin Password Hashing With PBKDF2 Summary

And that would be all for this article covering Kotlin password hashing with the PBKDF2 topic.

If you enjoyed this content, then you might also be interested in one of the following posts:

Let me know in the comments section about your thoughts! 🙂

2 Comments

Leave a Reply

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

  1. Let me first say that this tutorial is very detailed and educational.

    But I have one question. How do you use these functions in your project. In case you can’t tell, I am a newbie when it comes to writing and developing Android App.

    Thank you,

    • Hey hi hello David!

      In general, Android apps (like a web, or desktop apps) serve as the clients in a typical client-server communication.

      Which means, that typically, your Android app will not be responsible for password hashing, but rather server. And on Android side, you will be doing requests, like for example POST /login with some request body in JSON, like
      { “email”: “one@codersee.com”, “password”: “somePwd” }

      And then, the server will be responsible for the hashing etc
      If you would like to, then you will find a bunch of content on my blog, YT, or you can join my course https://codersee.com/courses/ktor-server-pro/ for the step-by-step approach 😉