在保留IV的情况下,更改Cipher加/解密模式



当与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(全为零),并且似乎没有办法在手动实现整个CBC部分的情况下获得IV。在加密字节后从Cipher获取更新的IV中也提出了类似的问题,但是只提出了特定于CBC的解决方案,不适用于CBC模式。

您在这里将加密IV设置为全零:

new IvParameterSpec(zeroBytes)

所以如果你使用随机字节,然后你将这些随机字节作为你的iv,你要自己跟踪它们。

更新

从你的评论看来,你可能试图重新启动解密中流或中间块,与CBC模式,你可以使用密文的前块作为你的IV,只要你是块对齐在你的流或块

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

也就是说,你使用的init方法的密码不正确。如果您在init调用中提供IVParameterSpec,则不会生成内部IV(正如您在对其他答案的评论中所说)。它将使用全0的IV,因为这是init版本告诉它要做的。相反,使用像c.init(Cipher.ENCRYPT_MODE, secretKey)这样的init调用,然后使用上面的c.getIV()将IV取出。在这里查看Cipher的javadocs,了解我的意思。

最新更新