我在解密文本时遇到一些问题:
我的后端经常在解密过程中引发IllegalBlockSizeException:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
当我再次尝试(1-3次)后,它可以成功解密SAME文本并将响应发送给FE。
正如我注意到的那样,通常是在短时间内尝试解密许多(大约100个)字符串时发生的(2条来自FE的请求,15条来自db /请求的记录,2条加密的字段/记录)
我的服务器在具有Raspbian的Raspberry Pi B +上运行。 “普通” PC上不存在该问题。
加密类:
package bookmarks.common.encryption.base;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.net.util.Base64;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DefaultEncryptor {
private static final int SIZE = 16;
private static final String ALGORITHM = "AES";
private static final Base64 BASE_64 = new Base64();
private final Key key;
private final Cipher cipher;
public DefaultEncryptor(String password) {
byte[] key = createKey(password);
this.key = new SecretKeySpec(key, ALGORITHM);
try {
cipher = Cipher.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
log.error("Error creating encryptor.", e);
throw new RuntimeException(e);
}
}
private byte[] createKey(String password) {
if (password.length() < SIZE) {
int missingLength = SIZE - password.length();
StringBuilder passwordBuilder = new StringBuilder(password);
for (int i = 0; i < missingLength; i++) {
passwordBuilder.append(" ");
}
password = passwordBuilder.toString();
}
return password.substring(0, SIZE).getBytes(StandardCharsets.UTF_8);
}
public String encrypt(String text) {
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8));
byte[] base64 = BASE_64.encode(encrypted);
return new String(base64, StandardCharsets.UTF_8);
} catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
log.error("Error encryping value.", e);
throw new RuntimeException(e);
}
}
public String decrypt(String text) {
try {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] base64 = BASE_64.decode(text.getBytes(StandardCharsets.UTF_8));
byte[] decrypted = cipher.doFinal(base64);
return new String(decrypted, StandardCharsets.UTF_8);
} catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
log.error("Error decrypting value.", e);
throw new RuntimeException(e);
}
}
}
有什么想法可以引起问题吗?
答案 0 :(得分:0)
仅使用不带IV的AES
密码意味着使用AES/ECB/PKCS5Padding
。这种密码和模式要求输入解密的内容是块大小(128位)的倍数
Input length must be multiple of 16 when decrypting with padded cipher
密码抱怨输入不是16的倍数
正如我注意到的那样,通常是在短时间内尝试解密许多(约100个)字符串时发生的
我想到的是什么(正如James所说,这是我的有根据的猜测),密码对象不是线程安全的。我会很自信地说
答案 1 :(得分:0)
问题是静态常量BASE_64,不是线程安全的。当多个请求同时到达时,spring-boot对它们进行并行处理,并且base64解码返回损坏的结果,并且当然不能解密无效数据。