我们正在将一些加密纳入 URL 生成器中,在测试过程中我注意到以下步骤会使程序挂起相当长的一段时间。
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8")));
这是调用它的函数的一部分,一旦到达该行,它就会挂起,并且可能需要 2 分钟以上才能最终通过。想知道有没有人知道原因或者解决办法。
public static String encrypt(String toEncrypt) throws Exception
{
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes("UTF-8")));
byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
byte[] encryptedValue = Base64.encodeBase64(encrypted);
return new String(encryptedValue);
}
谢谢
最佳答案
Security.addProvider(new BouncyCastleProvider());
因此,对于每个要加密的字符串,您需要创建一个新的安全提供程序。您会为每个 Web 请求启动一个新的 Web 服务器吗?当您想要编辑文件时,您会购买一台新计算机吗?
我并不是说这一行就是罪魁祸首,但每次都进行所有初始化是不可能的。
删除静态(*),使用单例,最好来自 Guice 或类似的,初始化一次。您的加密应该类似于
根据 @apangin 和 @IlmariKaronen 的评论修复。
static {
// This really should be done just once.
// Moreover, you most probably don't need it.
Security.addProvider(new BouncyCastleProvider());
}
Encryptor() {
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IVBytes));
}
public synchronized String encrypt(String toEncrypt) throws Exception {
byte[] encrypted = cipher.doFinal(toEncrypt.getBytes("UTF-8"));
byte[] encryptedValue = Base64.encodeBase64(encrypted);
return new String(encryptedValue);
}
由于加密本身非常快,并且您只加密短字符串,因此使用 synchronized
应该可以很好地工作。或者,选择线程本地密码
或类似的。
请注意,重复使用 IV
会使其不安全。但那是另一个故事了。
(*) 这与性能无关,但却是一件好事。
关于java - 密码加密速度明显慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39798728/