Firstly, according to the documentation of Cipher.doFinal(...) :
AES, DES, triple DES and Korean SEED algorithms in CBC mode reset the initial vector (IV) to 0. The initial vector (IV) can be reinitialized using the init(Key, byte, byte[], short, short) method init(Key, byte, byte[], short, short) .
This means that if you use AES-CBC with a non-zero IV, you need to call init after each doFinal , so there really is no choice.
Now let's look at some real-world measurements that I made on my NXP J2E145 cards.
Both ALG_AES_BLOCK_128_CBC_NOPAD and ALG_AES_BLOCK_128_ECB_NOPAD require 34 bytes of RAM and 32 bytes of read-only memory for each instance of the object.
As for the consumption of time, 4 situations are possible:
Situation 1: the same transition key:
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);
Result: 11 ms for each init(...)
Situation 2: different transition keys:
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);
Result: 18 ms for each init(...)
Case 3: The same permanent key:
key1 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); ... cipher.init(key1, Cipher.MODE_DECRYPT); cipher.init(key1, Cipher.MODE_ENCRYPT);
Result: 12 ms for each init(...)
Case 4: different constant keys:
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);
Result: 19 ms for each init(...)
Conclusion: init really fast regardless of the type of memory, since the EEPROM is only read and copied to the internal (temporary) memory of the Cipher instance. Although I can imagine some cases with high demand for time, 34 bytes of RAM seem too large to pay for 20 ms. Of course, the exact results may be different on your platform, but the effectiveness of the compromise will remain more or less the same.