在保留IV的同时更改密码加密/解密模式

时间:2013-03-25 08:16:13

标签: java cryptography mifare

当与DESfire EV1标签交互时,AES-CBC用于保护通信。在加密和发送消息之后,需要使用加密产生的IV来解密响应:

Cipher c = Cipher.getInstance("AES/CBC/NoPadding");
c.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(zeroBytes));

byte[] encrypted_response = transceive(c.doFinal(message));

// TODO: cipher needs to be re-set to DECRYPT_MODE while retaining the IV
c.init(Cipher.DECRYPT_MODE, ...?);

byte[] response = c.doFinal(encrypted_response);

不幸的是,Cipher.getIV()返回初始IV(全零),似乎没有办法让IV不能手动实现整个CBC部分。在Get updated IV from Cipher after encrypting bytes中,我们会提出类似的问题,但只提供针对特定解决方案的解决方案,这些解决方案不适用于CBC模式。

2 个答案:

答案 0 :(得分:2)

您可以在此处将加密IV设置为全零:

new IvParameterSpec(zeroBytes)

因此,如果您使用随机字节,然后您将随机字节作为您的iv,请自行跟踪它们。

更新

从您的评论中看起来您可能正在尝试重新启动解密中游或中间块,使用CBC模式,您可以使用前一个密文块作为您的IV,只要您在流或块中进行块对齐。 / p>

答案 1 :(得分:0)

您可以通过调用Cipher来获取c.getIV()对象的IV,这将返回带有IV数据的字节数组。然后,您可以将其插入解密端的IVParametersSpec

也就是说,您正在使用Cipher的init方法。如果您在init调用中提供IVParameterSpec,它将不会生成内部IV(正如您在对其他答案的评论中所述)。它将改为使用全零的IV,因为那是init版本告诉它做的。相反,使用对c.init(Cipher.ENCRYPT_MODE, secretKey)之类的初始化调用,然后使用上面的c.getIV()来获取IV。查看密码here的javadocs以了解我的意思。