使用单个密码对象或两个不同的对象进行解密和加密操作?
Using a single Cipher object or two different objects for decrypt and encrypt operations?
如您所知,当我们要使用Java个卡片进行密码运算时,我们必须使用Cipher
个对象。我的问题实际上与效率有关。假设我想使用 AES 密钥执行一些 Encryption 和 Decryption 操作。
以下哪种策略更好?
- 定义两个不同的
Cipher
对象并用一个键初始化它们,但模式不同(MODE_ENCRYPT
和 MODE_DECRYPT
)。然后对于每个操作,我只需要在适当的对象上调用 doFinal()
方法。
- 定义单个
Cipher
对象,每次在调用 doFinal()
方法之前,以适当的模式对该对象执行 init()
方法调用。
这取决于您处理的是永久密钥还是临时密钥material。
如果你有持久键 material:
- 选项 1 需要更多的 EEPROM,但你有显着的时间提升,因为你只在生成或导入密钥 material 时调用
init()
一次。
- 因此选项 2 不可取
如果您有临时密钥 material:
- 选项 1 需要更多的 EEPROM,并且时间提升几乎不存在,因为无论如何您都需要调用
init()
。我在 2 年前做了一些主要测试,如果我没记错的话,这两个选项之间存在 none 或非常小的性能差异
- 选项 2 需要较少的 EEPROM 并降低了代码的复杂性,因此是可取的
首先,根据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 re-initialized
using the init(Key, byte, byte[], short, short)
method.
这意味着如果你使用非零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);
结果:每个 11 毫秒 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);
结果:每个 18 毫秒 init(...)
情况三:同一个持久键:
key1 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_128, false);
...
cipher.init(key1, Cipher.MODE_DECRYPT);
cipher.init(key1, Cipher.MODE_ENCRYPT);
结果:每个 12 毫秒 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);
结果:每个 19 毫秒 init(...)
结论: init
与存储器类型无关,确实非常快,因为 EEPROM 仅被读取并复制到 [=25 的内部(瞬态)存储器中=] 实例。虽然我可以想象一些对时间消耗要求很高的情况,但 34 个 RAM 字节似乎太多了,无法支付 20ms。当然,在您的平台上,确切的结果可能会有所不同,但权衡效率或多或少会保持不变。
如您所知,当我们要使用Java个卡片进行密码运算时,我们必须使用Cipher
个对象。我的问题实际上与效率有关。假设我想使用 AES 密钥执行一些 Encryption 和 Decryption 操作。
以下哪种策略更好?
- 定义两个不同的
Cipher
对象并用一个键初始化它们,但模式不同(MODE_ENCRYPT
和MODE_DECRYPT
)。然后对于每个操作,我只需要在适当的对象上调用doFinal()
方法。 - 定义单个
Cipher
对象,每次在调用doFinal()
方法之前,以适当的模式对该对象执行init()
方法调用。
这取决于您处理的是永久密钥还是临时密钥material。
如果你有持久键 material:
- 选项 1 需要更多的 EEPROM,但你有显着的时间提升,因为你只在生成或导入密钥 material 时调用
init()
一次。 - 因此选项 2 不可取
如果您有临时密钥 material:
- 选项 1 需要更多的 EEPROM,并且时间提升几乎不存在,因为无论如何您都需要调用
init()
。我在 2 年前做了一些主要测试,如果我没记错的话,这两个选项之间存在 none 或非常小的性能差异 - 选项 2 需要较少的 EEPROM 并降低了代码的复杂性,因此是可取的
首先,根据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 re-initialized using the
init(Key, byte, byte[], short, short)
method.
这意味着如果你使用非零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);
结果:每个 11 毫秒 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);
结果:每个 18 毫秒 init(...)
情况三:同一个持久键:
key1 = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES,
KeyBuilder.LENGTH_AES_128, false);
...
cipher.init(key1, Cipher.MODE_DECRYPT);
cipher.init(key1, Cipher.MODE_ENCRYPT);
结果:每个 12 毫秒 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);
结果:每个 19 毫秒 init(...)
结论: init
与存储器类型无关,确实非常快,因为 EEPROM 仅被读取并复制到 [=25 的内部(瞬态)存储器中=] 实例。虽然我可以想象一些对时间消耗要求很高的情况,但 34 个 RAM 字节似乎太多了,无法支付 20ms。当然,在您的平台上,确切的结果可能会有所不同,但权衡效率或多或少会保持不变。