[英]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.