如您所知,当我们想要使用Java卡进行加密操作时,我们必须使用Cipher
个对象。我的问题实际上与效率有关。假设我想使用AES密钥执行一些加密和解密操作。
以下哪种策略更好?
Cipher
个对象,并使用单个键初始化它们,但不同的模式(MODE_ENCRYPT
和MODE_DECRYPT
)。然后,对于每个操作,我只需要在适当的对象上调用doFinal()
方法。Cipher
对象,每次调用doFinal()
方法之前,使用正确模式对对象执行init()
方法调用。 答案 0 :(得分:4)
首先,根据Cipher.doFinal(...)
的文件:
在CBC模式下,AES,DES,三重DES和韩国SEED算法重置了
初始矢量(IV)为0.初始矢量(IV)可以重新初始化
使用init(Key, byte, byte[], short, short)
方法。
这意味着如果你使用非零IV的AES-CBC,你必须在每个init
之后调用doFinal
,所以没有选择,真的。
现在让我们看看我在恩智浦的J2E145卡上做过的一些实际测量。
ALG_AES_BLOCK_128_CBC_NOPAD
和ALG_AES_BLOCK_128_ECB_NOPAD
每个对象实例都需要 34个字节的RAM 和 32个字节的持久性内存。
关于时间消耗,有4种可能的情况:
情况1:相同的瞬态密钥:
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(...)
情境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(...)
情境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(...)
情况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(...)
结论: init
非常快,与内存类型无关,因为EEPROM只能被读取并复制到Cipher
实例的内部(瞬态)内存中。虽然我可以想象一些具有高时间消耗要求的情况,但是34个RAM字节似乎太多而无法支付20ms。当然,您的平台上的确切结果可能会有所不同,但权衡效率将或多或少保持不变。
答案 1 :(得分:3)
这取决于您是使用持久性或临时密钥材料进行处理 如果你有持久的密钥材料:
init()
一次,因此需要大量时间。如果您有临时密钥材料:
init()
。我2年前做了一些重大测试,如果我没记错的话,两个选项之间没有或只有非常小的性能增量