Cryptography in Kotlin: Encryption and Hashing

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Cryptography in Kotlin: Encryption and Hashing

Kotlin, running on top of the JVM, provides full access to powerful Java cryptographic libraries such as Java Cryptography Extension (JCE) and Bouncy Castle. In this article, we will look at how to implement symmetric (AES), asymmetric (RSA) encryption, as well as hashing (SHA-256) in Kotlin. All code examples are ready to run — you can copy them into your project.



Project Setup

To begin, add the Bouncy Castle dependency (a recommended provider for modern algorithms) to your build.gradle.kts:

dependencies {    implementation("org.bouncycastle:bcprov-jdk15on:1.70")}

After syncing Gradle, import the provider in your code:

import org.bouncycastle.jce.provider.BouncyCastleProviderimport java.security.Security

fun initCrypto() { Security.addProvider(BouncyCastleProvider())}


1. SHA-256 Hashing

Hashing is an irreversible transformation of data. It is most often used for verifying file integrity and storing passwords.

import java.security.MessageDigest

fun sha256(input: String): String { val digest = MessageDigest.getInstance("SHA-256") val hashBytes = digest.digest(input.toByteArray()) return hashBytes.joinToString("") { "%02x".format(it) }}

fun main() { val password = "mySecret123" val hash = sha256(password) println("SHA-256 hash: $hash") // Output: SHA-256 hash: a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3}

Important: For passwords, use bcrypt or scrypt — SHA-256 is too fast and vulnerable to brute-force attacks.



2. Symmetric AES Encryption

AES (Advanced Encryption Standard) is the most popular algorithm for data encryption. We use GCM mode (which guarantees authenticity) and a random IV.

import javax.crypto.Cipherimport javax.crypto.KeyGeneratorimport javax.crypto.SecretKeyimport javax.crypto.spec.GCMParameterSpecimport java.util.Base64

class AesGcmEncryption { companion object { private const val AES_KEY_SIZE = 256 private const val GCM_IV_LENGTH = 12 private const val GCM_TAG_LENGTH = 128 }

fun generateKey(): SecretKey { val keyGen = KeyGenerator.getInstance("AES") keyGen.init(AES_KEY_SIZE) return keyGen.generateKey() }

fun encrypt(plainText: String, secretKey: SecretKey): String { val cipher = Cipher.getInstance("AES/GCM/NoPadding") val iv = ByteArray(GCM_IV_LENGTH).apply { java.security.SecureRandom().nextBytes(this) } cipher.init(Cipher.ENCRYPT_MODE, secretKey, GCMParameterSpec(GCM_TAG_LENGTH, iv)) val cipherText = cipher.doFinal(plainText.toByteArray()) // Combine IV and ciphertext val combined = iv + cipherText return Base64.getEncoder().encodeToString(combined) }

fun decrypt(encryptedData: String, secretKey: SecretKey): String { val combined = Base64.getDecoder().decode(encryptedData) val iv = combined.copyOfRange(0, GCM_IV_LENGTH) val cipherText = combined.copyOfRange(GCM_IV_LENGTH, combined.size) val cipher = Cipher.getInstance("AES/GCM/NoPadding") cipher.init(Cipher.DECRYPT_MODE, secretKey, GCMParameterSpec(GCM_TAG_LENGTH, iv)) return String(cipher.doFinal(cipherText)) }}

fun main() { val aes = AesGcmEncryption() val key = aes.generateKey() val original = "Secret message" val encrypted = aes.encrypt(original, key) val decrypted = aes.decrypt(encrypted, key) println("Original: $original") println("Encrypted: $encrypted") println("Decrypted: $decrypted")}


3. Asymmetric

Recommendations