簡體   English   中英

無法使用Java / Kotlin加密/解密字符串

[英]Cannot encrypt/decrypt string using Java/Kotlin

我需要在Java上加密字符串,然后在Kotlin上解密它。 我做以下事情:

像這樣加密字符串

private static String encrypt(String value, String password) throws NoSuchPaddingException, ... {
        final SecretKeySpec secretKeySpec = new SecretKeySpec(password.getBytes(Charset.forName("UTF-8")), "AES");
        final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        final byte[] encryptedValue = cipher.doFinal(value.getBytes(Charset.forName("UTF-8")));
        return DatatypeConverter.printBase64Binary(encryptedValue);
    }

為了在Kotlin中解密,我使用以下方法:

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)

(1) val decryptedByteValue = cipher.doFinal(Base64.decode(this, Base64.DEFAULT))
    return String(decryptedByteValue)
}

在這種情況下,第(1)行會收到AEADBadTagException:GCM中的mac檢查失敗

所以,我做了一點改變

fun String.decrypt(password: String): String {
    val secretKeySpec = SecretKeySpec(password.toByteArray(), "AES")
    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
(2) cipher.init(Cipher.DECRYPT_MODE, secretKeySpec)

    val decryptedByteValue = cipher.doFinal(Base64.decode(this, Base64.DEFAULT))
    return String(decryptedByteValue)
}

在那種情況下,在第(2)行中,我收到RuntimeException:java.security.InvalidAlgorithmParameterException:必須在GCM模式下指定IV

所以之后,我改變了加密方式

private static String encrypt(String value, String password) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
        final SecretKeySpec secretKeySpec = new SecretKeySpec(password.getBytes(Charset.forName("UTF-8")), "AES");
        final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        final byte[] iv = new byte[16];
        for (int i = 0; i < password.length(); i++) {
            iv[i] = (byte) password.toCharArray()[0];
        }
        final IvParameterSpec ivSpec = new IvParameterSpec(iv);

    (3) cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
        final byte[] encryptedValue = cipher.doFinal(value.getBytes(Charset.forName("UTF-8")));
        return DatatypeConverter.printBase64Binary(encryptedValue);
    }

但在第(3)行中,我收到java.security.InvalidAlgorithmParameterException:不支持的參數:javax.crypto.spec.IvParameterSpec@6d311334

請幫助我解決這個難題

執行SecretKeySpec(password.toByteArray(), "AES")顯然是功能性和安全性問題。 AES需要16/24/32字節的密鑰,但是您的密碼長度可變。 切勿使用密碼作為密鑰。 請改用PBKDF2之類的密鑰派生算法。

關於您的錯誤:

您使用的是IvParameterSpec,但是GCM不使用IV,而是使用Nonce,它需要指定身份驗證標簽的長度。 因此,您必須提供GCMParameterSpec

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM