首页 文章

加密/解密字符串Kotlin

提问于
浏览
0

我在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

我做错了什么?

2 回答

  • 2

    要对密文进行编码,请使用base 64或hexadecimals . Java API包含Base64类,因此您可能最好使用它 .

    byte[]#toString 没有做你期望它做的事情;它只返回字节数组引用的表示,而不是字节数组的内容 .


    除此之外:

    • 不要使用SecureRandom派生密钥,尝试查找PBKDF2;

    • 明确使用一种操作模式,如 "AES/GCM/NoPadding" ;
      如果您决定使用CBC(通常不安全),

    • 使用独特的IV和随机IV;

    • 如果没有明确选择邮件的字符编码,请不要使用 toByteArray .

  • 2

    按照Maarten Bodews指南,我将问题解决为:

    fun String.encrypt(password: String): String {
        val secretKeySpec = SecretKeySpec(password.toByteArray(), "AES")
        val iv = ByteArray(16)
        val charArray = password.toCharArray()
        for (i in 0 until charArray.size){
            iv[i] = charArray[i].toByte()
        }
        val ivParameterSpec = IvParameterSpec(iv)
    
        val cipher = Cipher.getInstance("AES/GCM/NoPadding")
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
    
        val encryptedValue = cipher.doFinal(this.toByteArray())
        return Base64.encodeToString(encryptedValue, Base64.DEFAULT)
    }
    
    fun String.decrypt(password: String): String {
        val secretKeySpec = SecretKeySpec(password.toByteArray(), "AES")
        val iv = ByteArray(16)
        val charArray = password.toCharArray()
        for (i in 0 until charArray.size){
            iv[i] = charArray[i].toByte()
        }
        val ivParameterSpec = IvParameterSpec(iv)
    
        val cipher = Cipher.getInstance("AES/GCM/NoPadding")
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
    
        val decryptedByteValue = cipher.doFinal(Base64.decode(this, Base64.DEFAULT))
        return String(decryptedByteValue)
    }
    

相关问题