Exposed 1.5.0 Help

Hashing data

Exposed supports one-way hashing for sensitive data such as passwords through the exposed-crypt module.

Unlike encryption, hashing does not allow the original value to be recovered. Instead, you verify a plaintext value against the stored hash.

Add dependencies

To use hashing with Exposed, add the exposed-crypt module to your build script:

dependencies { implementation("org.jetbrains.exposed:exposed-crypt:1.5.0") }
<dependencies> <dependency> <groupId>org.jetbrains.exposed</groupId> <artifactId>exposed-crypt</artifactId> <version>1.5.0</version> </dependency> </dependencies>
dependencies { implementation "org.jetbrains.exposed:exposed-crypt:1.5.0" }

Optionally, to use scrypt and Argon2 hashing, add the Bouncy Castle library as a runtime dependency:

dependencies { runtimeOnly("org.bouncycastle:bcprov-jdk18on:1.85") }
<dependencies> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk18on</artifactId> <version>1.85</version> <scope>runtime</scope> </dependency> </dependencies>
dependencies { runtimeOnly "org.bouncycastle:bcprov-jdk18on:1.85" }

Basic usage

To create a hashed column, apply the .hashed() function to a character column:

object Users : IntIdTable() { val password = text("password").hashed() }

The .hashed() function changes the Kotlin type of the column from String to Hashed.

Supported algorithms

The .hashed() function uses BCryptHasher by default. You can change the default hasher by choosing one of the supported Hasher implementations:

Hasher

Algorithm

BCryptHasher

bcrypt

Argon2Hasher

Argon2

Pbkdf2Hasher

PBKDF2

SCryptHasher

scrypt

To use another hashing algorithm or customize its parameters, create a Hasher and pass it to the .hashed() function:

val hasher = BCryptHasher(strength = 12) object Users : IntIdTable() { val email = varchar("email", 320) val password = text("password").hashed(hasher) }

Configure a hasher

Each hasher provides parameters for configuring the amount of work required to generate and verify a hash. For example, you can configure the strength used by BCryptHasher:

val bCryptHasher = BCryptHasher(strength = 12)

For Argon2Hasher, you can configure parameters such as memory usage, iterations, and parallelism:

val argon2Hasher = Argon2Hasher( memory = 19_456, iterations = 2, parallelism = 1 )

Pbkdf2Hasher also lets you select the pseudorandom function:

val pbkdf2Hasher = Pbkdf2Hasher( algorithm = Pbkdf2PasswordEncoder.SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA256 )

Use a Spring Security password encoder

If your application already uses a Spring Security PasswordEncoder, wrap it with PasswordEncoderHasher to adapt it to the Hasher type:

val passwordEncoder = MyPasswordEncoder() val hasher = PasswordEncoderHasher(passwordEncoder) object Users : IntIdTable() { val password = text("password").hashed(hasher) }

PasswordEncoderHasher delegates hashing and verification to the supplied PasswordEncoder while exposing the standard Exposed Hasher API.

Hash and store a value

Use the configured Hasher to hash a plaintext value before storing it:

Users.insert { it[password] = hasher.hash("s3cret") }

The .hash() function returns a Hashed value containing the encoded hash.

Verify a value

To verify a plaintext value, use the .matches() function on the stored Hashed value:

val user = Users.selectAll().where { Users.email eq "john@mail.com" }.single() if (user[Users.password].matches("s3cret")) { println("Passwords match.") }

The .matches() function returns true if the plaintext value matches the stored hash.

18 September 2026