Kotlin 中的密码学:加密与哈希
现代 Kotlin 开发(尤其是 Android 和后端)经常需要实现密码学功能。本文将介绍使用 Kotlin 以及 Java Cryptography Extension (JCE) 和 Bouncy Castle 标准库进行数据加密和哈希的主要方法。
基本概念
Kotlin 中的密码学依赖于 JVM 的能力。您可以使用:
- 对称加密(AES、DES)——使用同一密钥进行加密和解密。
- 非对称加密(RSA)——使用一对密钥:公钥和私钥。
- 哈希(SHA-256、MD5)——数据的不可逆转换。
- HMAC——使用密钥进行哈希以验证完整性。
项目配置
大多数示例只需使用 Java 标准库。对于高级算法(例如带 GCM 的 AES),请在 build.gradle.kts 中添加依赖:
dependencies { implementation("org.bouncycastle:bcprov-jdk15on:1.70")}1. 对称加密(AES)
AES 是最流行的算法。字符串加密和解密示例:
import javax.crypto.Cipherimport javax.crypto.KeyGeneratorimport javax.crypto.SecretKeyimport javax.crypto.spec.IvParameterSpecimport java.util.Base64
fun aesEncrypt(plainText: String, secretKey: SecretKey): String { val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") val iv = ByteArray(16) // 生成 IV java.security.SecureRandom().nextBytes(iv) cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(iv)) val encrypted = cipher.doFinal(plainText.toByteArray()) // 合并 IV 和密文 val combined = iv + encrypted return Base64.getEncoder().encodeToString(combined)}
fun aesDecrypt(encryptedBase64: String, secretKey: SecretKey): String { val combined = Base64.getDecoder().decode(encryptedBase64) val iv = combined.copyOfRange(0, 16) val encrypted = combined.copyOfRange(16, combined.size) val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(iv)) return String(cipher.doFinal(encrypted))}
// 使用示例fun main() { val keyGen = KeyGenerator.getInstance("AES") keyGen.init(256) val secretKey = keyGen.generateKey()
val original = "Hello, Kotlin Crypto!" val encrypted = aesEncrypt(original, secretKey) println("已加密: $encrypted")
val decrypted = aesDecrypt(encrypted, secretKey) println("已解密: $decrypted")}2. 非对称加密(RSA)
RSA 用于安全数据传输。示例:
import java.security.KeyPairGeneratorimport java.security.PrivateKeyimport java.security.PublicKeyimport javax.crypto.Cipherimport java.util.Base64
fun generateRSAKeyPair(): Pair<PublicKey, PrivateKey> { val generator = KeyPairGenerator.getInstance("RSA") generator.initialize(2048) val keyPair = generator.generateKeyPair() return Pair(keyPair.public, keyPair.private)}
fun rsaEncrypt(plainText: String, publicKey: PublicKey): String { val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding") cipher.init(Cipher.ENCRYPT_MODE, publicKey) return Base64.getEncoder().encodeToString(cipher.doFinal(plainText.toByteArray()))}
fun rsaDecrypt(encryptedBase64: String, privateKey: PrivateKey): String { val cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding") cipher.init(Cipher.DECRYPT_MODE, privateKey) return String(cipher.doFinal(Base64.getDecoder().decode(encryptedBase64)))}
fun main() { val (publicKey, privateKey) = generateRSAKeyPair() val message = "秘密消息" val encryp