使用Cipher.doFinal(byte [] b)在第一次解密后更快解密?

时间:2016-11-05 22:24:48

标签: java encryption

我有以下代码:

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey mSecretKey = keyGen.generateKey();

public byte[] encrypt(byte[] data) {
    try {
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        SecretKeySpec k = new SecretKeySpec(mSecretKey.getEncoded(), "AES");
        c.init(Cipher.ENCRYPT_MODE, k);
        byte[] encryptedData = c.doFinal(data);
        return Bytes.concat(c.getIV(), encryptedData);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

public byte[] decrypt(byte[] encryptedData) {
    try {
        byte[] iv = Arrays.copyOfRange(encryptedData, 0, 16);
        SecretKeySpec k = new SecretKeySpec(mSecretKey.getEncoded(), "AES");
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        c.init(Cipher.DECRYPT_MODE, k, new IvParameterSpec(iv));
        byte[] decrypted = c.doFinal(Arrays.copyOfRange(encryptedData, 16, encryptedData.length));
        return decrypted;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

出于某种原因,我发现如果我执行以下内容:

byte[] encrypted = encrypt(some_byte_array);

byte[] decrypt1 = decrypt(encrypted);
byte[] decrypt2 = decrypt(encrypted);
...
byte[] decryptN = decrypt(encrypted);

首次解密(有时是第一对)总是需要比以下解密更长的时间。然而,这不限于解密相同的加密。例如,如果我加密两个字节数组 a b ,如果我首先解密 a 的加密,那么解密 b 执行得更快。

所以基本上,解密的第一个(有时是几个)呼叫总是慢于 所有后续电话。我做了一些自己的基准测试,发现差异似乎在于我对 c.doFinal(Arrays.copyOfRange(encryptedData,16,encryptedData.length)的调用,这需要花费更长的时间(有时候)几次,而不是之后。

如果这是一个愚蠢的问题,我会提前道歉,并感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

第一次使用Java运行字节代码时,它通常通过JIT编译器(通过JVM)编译为本机代码。之后,它会保存本机代码并再次使用它。因此,我希望后续调用比第一次调用更快。另请参阅startup delay and optimizations