Криптография в Kotlin: шифрование и хеширование

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Криптография в Kotlin: шифрование и хеширование

Kotlin, работающий поверх JVM, предоставляет полный доступ к мощным криптографическим библиотекам Java, таким как Java Cryptography Extension (JCE) и Bouncy Castle. В этой статье мы рассмотрим, как реализовать симметричное (AES), асимметричное (RSA) шифрование, а также хеширование (SHA-256) на Kotlin. Все примеры кода готовы к запуску — вы можете скопировать их в свой проект.

Подготовка проекта

Для начала добавьте в build.gradle.kts зависимость от Bouncy Castle (рекомендуемый провайдер для современных алгоритмов):

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

После синхронизации Gradle импортируйте провайдер в коде:

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

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

1. Хеширование SHA-256

Хеширование — это необратимое преобразование данных. Чаще всего используется для проверки целостности файлов и хранения паролей.

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")
    // Вывод: SHA-256 хеш: a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
}

Важно: Для паролей используйте bcrypt или scrypt — SHA-256 слишком быстрый и уязвим к атакам перебором.

2. Симметричное шифрование AES

AES (Advanced Encryption Standard) — самый популярный алгоритм для шифрования данных. Используем режим GCM (гарантирует аутентичность) и случайный IV.

import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.GCMParameterSpec
import 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())
        // Объединяем IV и шифротекст
        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 = "Секретное сообщение"
    val encrypted = aes.encrypt(original, key)
    val decrypted = aes.decrypt(encrypted, key)
    println("Оригинал: $original")
    println("Зашифровано: $encrypted")
    println("Расшифровано: $decrypted")
}

3. Асимметричное шифрование RSA

RSA использует пару ключей: открытый (для шифрования) и закрытый (для расшифровки). Идеально подходит для передачи симметричных ключей.

import java.security.KeyPairGenerator
import java.security.PrivateKey
import java.security.PublicKey
import javax.crypto.Cipher
import java.util.Base64

class RsaEncryption {
    fun generateKeyPair(): Pair<PublicKey, PrivateKey> {
        val generator = KeyPairGenerator.getInstance("RSA")
        generator.initialize(2048) // 2048 бит — безопасный минимум
        val keyPair = generator.generateKeyPair()
        return Pair(keyPair.public, keyPair.private)
    }

    fun encrypt(plainText: String, publicKey: Public                    

Рекомендаций