我在 Kotlin 中创建了这两个扩展来加密/解密字符串:

fun String.encrypt(seed : String): String {
    val keyGenerator = KeyGenerator.getInstance("AES")
    val secureRandom = SecureRandom.getInstance("SHA1PRNG")
    secureRandom.setSeed(seed.toByteArray())

    keyGenerator.init(128, secureRandom)
    val skey = keyGenerator.generateKey()
    val rawKey : ByteArray = skey.encoded

    val skeySpec = SecretKeySpec(rawKey, "AES")
    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec)
    val byteArray = cipher.doFinal(this.toByteArray())

    return byteArray.toString()
}

fun String.decrypt(seed : String): String {
    val keyGenerator = KeyGenerator.getInstance("AES")
    val secureRandom = SecureRandom.getInstance("SHA1PRNG")
    secureRandom.setSeed(seed.toByteArray())

    keyGenerator.init(128, secureRandom)
    val skey = keyGenerator.generateKey()
    val rawKey : ByteArray = skey.encoded

    val skeySpec = SecretKeySpec(rawKey, "AES")
    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    cipher.init(Cipher.DECRYPT_MODE, skeySpec)
    val byteArray = cipher.doFinal(this.toByteArray())

    return byteArray.toString()
}

出于某种原因,我收到以下异常:
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption

我做错了什么?

最佳答案

要对您的密文进行编码,请使用 base 64 或十六进制。 Java API 包含一个 Base64 类,因此您最好使用它。
byte[]#toString 没有做你期望它做的事情;它只是返回字节数组引用的表示,而不是字节数组的内容。

除此之外:

  • 不使用 SecureRandom 来派生 key ,尝试查找 PBKDF2;
  • 明确使用一种操作模式,例如 "AES/GCM/NoPadding"
  • 使用唯一的 IV,如果您决定使用 CBC(通常不安全),则使用随机的 IV;
  • 在没有为消息明确选择字符编码的情况下不要使用 toByteArray
  • 关于encryption - 加密/解密字符串 Kotlin,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49340005/

    10-13 06:22
    查看更多