Java 由于速度缓慢,缓存SecretKeySpec

Java 由于速度缓慢,缓存SecretKeySpec,java,encryption,Java,Encryption,加密/解密中最慢的部分之一是上面的代码。生成SecretKey需要大约95%的解密时间。我想知道是否可以将SecretKey存储在像Guava这样的缓存中进行优化 有什么想法吗?这是故意的,目的是让字典攻击更难。如果每次都使用相同的salt,攻击者可以执行相同的操作并预计算密钥。PBKDF2函数的速度慢是一个质量特性。正如@Henry所说,运行缓慢的函数使攻击者更难通过暴力攻击找到正确的密码 速度受内部运行以获得输出值的迭代次数(“循环”)的影响-在您的示例中,“65546”是迭代次数。选择一个

加密/解密中最慢的部分之一是上面的代码。生成SecretKey需要大约95%的解密时间。我想知道是否可以将SecretKey存储在像Guava这样的缓存中进行优化


有什么想法吗?

这是故意的,目的是让字典攻击更难。如果每次都使用相同的salt,攻击者可以执行相同的操作并预计算密钥。

PBKDF2函数的速度慢是一个质量特性。正如@Henry所说,运行缓慢的函数使攻击者更难通过暴力攻击找到正确的密码

速度受内部运行以获得输出值的迭代次数(“循环”)的影响-在您的示例中,“65546”是迭代次数。选择一个更大的数字会减慢计算速度,选择一个更小的数字会使计算速度更快。这取决于您找到一个值,该值对于慢速设备上的用户来说可以计算密码散列

因此,作为对您问题的回答:请不要试图缩短或缓存数据以使其更快-这会降低安全性

下面您可以找到一个小的测试例程,它显示迭代次数和时间(毫秒)之间的上下文。注意,没有“预热”运行,因此第一个结果似乎太高。还有一些“失控”是由设备内部例程引起的

以下是结果和源代码:

            KeySpec keySpec = new PBEKeySpec(key.toCharArray(), salt.getBytes(UTF_8), 65546, 256);
            SecretKey secret = factory.generateSecret(keySpec);
代码:

导入javax.crypto.SecretKeyFactory;
导入javax.crypto.spec.PBEKeySpec;
导入java.security.NoSuchAlgorithmException;
导入java.security.SecureRandom;
导入java.security.spec.InvalidKeySpecException;
公共类时间度量{
公共静态void main(字符串[]args)抛出NoSuchAlgorithmException、InvalidKeySpecException{
System.out.println(“https://stackoverflow.com/questions/62749930/cache-secretkeyspec-due-to-slowness/62750840#62750840");
char[]passwordChar=“secretPassword.tocharray();
//pbkdf2的变量
int PBKDF2_迭代次数;//迭代次数
final int SALT\u SIZE\u BYTE=128/8;//SALT的大小
final int HASH_SIZE_BIT=256;//输出大小
byte[]passwordHashByte;//输出数组
//随机盐
SecureRandom SecureRandom=新的SecureRandom();
字节密码saltbyte[]=新字节[SALT_SIZE_byte];
secureRandom.nextBytes(密码saltbyte);
//时间测量
长startMilli=0;
长finishMilli=0;
长pbkdf2Milli=0;
System.out.println(“Nr迭代毫秒”);
对于(int i=1;i<15;i++){
PBKDF2_迭代次数=i*10000;
secureRandom.nextBytes(密码saltbyte);
startMilli=System.currentTimeMillis();
PBEKeySpec spec=新的PBEKeySpec(passwordChar、passwordSaltByte、PBKDF2_迭代、散列大小_位);
SecretKeyFactory SecretKeyFactory=SecretKeyFactory.getInstance(“PBKDF2WithHmacSHA512”);
passwordHashByte=secretKeyFactory.GenerateCret(spec).getEncoded();
finishMilli=System.currentTimeMillis();
pbkdf2Milli=finishMilli-startMilli;
System.out.format(“%-15d%7d%n”,PBKDF2_迭代,pbkdf2Milli);
}
}
}

问题是,在这种情况下是否真的需要慢度。@Codo是的,但我们不知道上下文。我不担心慢度。如果我删除它,我想知道是否可以缓存
https://stackoverflow.com/questions/62749930/cache-secretkeyspec-due-to-slowness/62750840#62750840
Nr iterations  Milliseconds
   10000              374
   20000              206
   30000              262
   40000              285
   50000              337
   60000             1144
   70000              417
   80000              463
   90000              555
   100000             566
   110000             601
   120000             586
   130000             632
   140000             671
   import javax.crypto.SecretKeyFactory;
   import javax.crypto.spec.PBEKeySpec;
   import java.security.NoSuchAlgorithmException;
   import java.security.SecureRandom;
   import java.security.spec.InvalidKeySpecException;
   
   public class TimeMeasure {
       public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {
           System.out.println("https://stackoverflow.com/questions/62749930/cache-secretkeyspec-due-to-slowness/62750840#62750840");
           char[] passwordChar = "secretPassword".toCharArray();
   
           // variables for pbkdf2
           int PBKDF2_ITERATIONS; // number of iterations
           final int SALT_SIZE_BYTE = 128 / 8; // size of salt
           final int HASH_SIZE_BIT = 256; // output size
           byte[] passwordHashByte; // output array
   
           // random salt salt
           SecureRandom secureRandom = new SecureRandom();
           byte passwordSaltByte[] = new byte[SALT_SIZE_BYTE];
           secureRandom.nextBytes(passwordSaltByte);
   
           // time measurement
           long startMilli = 0;
           long finishMilli = 0;
           long pbkdf2Milli = 0;
   
           System.out.println("Nr iterations  Milliseconds");
           for (int i = 1; i < 15; i++) {
               PBKDF2_ITERATIONS = i * 10000;
               secureRandom.nextBytes(passwordSaltByte);
               startMilli = System.currentTimeMillis();
               PBEKeySpec spec = new PBEKeySpec(passwordChar, passwordSaltByte, PBKDF2_ITERATIONS, HASH_SIZE_BIT);
               SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
               passwordHashByte = secretKeyFactory.generateSecret(spec).getEncoded();
               finishMilli = System.currentTimeMillis();
               pbkdf2Milli = finishMilli - startMilli;
               System.out.format("   %-15d%7d%n", PBKDF2_ITERATIONS, pbkdf2Milli);
           }
       }
   }