首先,根据Cipher.doFinal(...)的文档:
CBC 模式下的 AES、DES、三重 DES 和韩语 SEED 算法重置
初始向量(IV)为0。初始向量(IV)可以重新初始化
使用init(Key, byte, byte[], short, short) 方法。
这意味着如果你使用非零IV的AES-CBC,你必须在每个doFinal之后调用init,所以没有选择,真的。
现在让我们看看我在 NXP 的 J2E145 卡上进行的一些实际测量。
ALG_AES_BLOCK_128_CBC_NOPAD 和 ALG_AES_BLOCK_128_ECB_NOPAD 每个对象实例都需要 34 字节的 RAM 和 32 字节的持久内存。
关于时间消耗,有4种可能的情况:
情况一:同一个瞬态键:
key1 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT,
KeyBuilder.LENGTH_AES_128, false);
...
cipher.init(key1, Cipher.MODE_DECRYPT);
cipher.init(key1, Cipher.MODE_ENCRYPT);
结果:每个init(...)11 毫秒
情况2:不同的瞬态键:
key1 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT,
KeyBuilder.LENGTH_AES_128, false);
key2 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT,
KeyBuilder.LENGTH_AES_128, false);
...
cipher.init(key1, Cipher.MODE_DECRYPT);
cipher.init(key2, Cipher.MODE_ENCRYPT);
结果:每个init(...)18 毫秒
情况3:相同的持久键:
key1 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_128, false);
...
cipher.init(key1, Cipher.MODE_DECRYPT);
cipher.init(key1, Cipher.MODE_ENCRYPT);
结果:每个init(...)12 毫秒
情况4:不同的持久键:
key1 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_128, false);
key2 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_128, false);
...
cipher.init(key1, Cipher.MODE_DECRYPT);
cipher.init(key2, Cipher.MODE_ENCRYPT);
结果:每个init(...)19 毫秒
结论: init 的速度非常快,与内存类型无关,因为 EEPROM 仅被读取并复制到 Cipher 实例的内部(瞬态)内存中。虽然我可以想象一些对时间消耗要求很高的情况,但 34 个 RAM 字节似乎太多了,无法支付 20ms。当然,您的平台上的确切结果可能会有所不同,但权衡效率或多或少会保持不变。