使用单个Cipher对象或两个不同的对象进行解密和加密操作?

时间:2016-05-03 12:05:57

标签: java cryptography javacard

如您所知,当我们想要使用Java卡进行加密操作时,我们必须使用Cipher个对象。我的问题实际上与效率有关。假设我想使用AES密钥执行一些加密解密操作。

以下哪种策略更好?

  1. 定义两个不同的Cipher个对象,并使用单个键初始化它们,但不同的模式(MODE_ENCRYPTMODE_DECRYPT)。然后,对于每个操作,我只需要在适当的对象上调用doFinal()方法。
  2. 定义单个Cipher对象,每次调用doFinal()方法之前,使用正确模式对对象执行init()方法调用。

2 个答案:

答案 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_NOPADALG_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(...)

11 ms

情境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 ms

情境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 ms

情况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 ms

结论: init非常快,与内存类型无关,因为EEPROM只能被读取并复制到Cipher实例的内部(瞬态)内存中。虽然我可以想象一些具有高时间消耗要求的情况,但是34个RAM字节似乎太多而无法支付20ms。当然,您的平台上的确切结果可能会有所不同,但权衡效率将或多或少保持不变。

答案 1 :(得分:3)

这取决于您是使用持久性或临时密钥材料进行处理 如果你有持久的密钥材料:

  • 选项1需要更多的EEPROM,但由于您在生成或导入密钥材料时只调用init()一次,因此需要大量时间。
  • 因此选项2是不可取的

如果您有临时密钥材料:

  • 选项1需要更多的EEPROM,并且几乎不存在时间提升,因为您无论如何都需要调用init()。我2年前做了一些重大测试,如果我没记错的话,两个选项之间没有或只有非常小的性能增量
  • 选项2需要更少的EEPROM并降低代码的复杂性,因此需要