Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 更改密码加密/解密模式,同时保留IV_Java_Cryptography_Mifare - Fatal编程技术网

Java 更改密码加密/解密模式,同时保留IV

Java 更改密码加密/解密模式,同时保留IV,java,cryptography,mifare,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));

当与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部分。在一个类似的问题中,只提出了特定于CTR的解决方案,这些解决方案不适用于CBC模式。

您在此处将encrypt IV设置为全零:

new IvParameterSpec(zeroBytes)
因此,如果您使用随机字节,然后您将使用这些随机字节作为您的iv,请自己跟踪它们

更新


从您的评论来看,您可能正在尝试重新启动解密中流或中段,使用CBC模式,您可以使用上一个密文块作为IV,只要您在流或段中是块对齐的。

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


也就是说,您错误地使用了
init
密码方法。如果在
init
调用中提供IVParameterSpec,它将不会生成内部IV(如您在对另一个答案的评论中所说)。它将使用全零的IV,因为这是
init
版本告诉它的。相反,使用对init的调用,如
c.init(Cipher.ENCRYPT\u MODE,secretKey)
然后使用上面的
c.getIV()
将IV取出。查看javadocs for Cipher,了解我的意思。

在您的代码片段中,实际上,您希望实现正确解密的是初始IV(全零)。对于第一次加密,IV实际上是零。但是,在第一次传递doFinal()之后,密码中的内部IV会发生变化,我需要获取它的值以传递给下一个Cipher.init()。如果我在没有IvParameterSpec参数的情况下调用Cipher.init(),IV也将重置为零。这是一个初始化向量,您只需要在初始化时担心它,没有结果IV,它不会被计算,对于cbc,每个块使用前一个块的密文作为初始化向量,除了必须提供的第一个,用于加密和解密的初始IV必须相同。顺便说一句,对于加密的安全性,它还需要是不重复和不可预测的,而所有的零都不是。好的,现在你已经很明显了。IV分别是最后一次解密/加密操作的输入/输出,因此获取它并不太困难。如果你把它变成一个答案而不是一个评论,我会接受:)不,那不是静脉注射,也不是jbtule说的那样。IV可以通过开放通道进行通信。它应该是随机的,但不需要保密。IV不会随密码的状态而改变,因为它是一个初始值,因此名为初始化向量。正如我在问题中所写的,c.getIV()返回的不是上次加密后的IV状态,而是提供给init()的IV,使得该函数调用对重新初始化密码无效(@ge0rg这是因为这些IV是相同的。当你加密某些东西时,IV不会改变。如果你使用
c.init(模式,密钥)正确地生成了一个随机IV,你可以使用
c.getIV()你读过我的答案的下半部分吗?我需要澄清:如果你把每个块的CBC加密看作一个单独的过程,第二个块的IV就是第一个块的密文——这就是我所说的IV改变的意思。关于IV是全零的,我知道它是不安全的,但是它是RE。根据DESfire规范的要求,我无法更改它。那么,您不正确地考虑IV,使用该术语将无法得到正确的答案。该值与第二块明文异或,即实际上只是第一块密文-
加密的\u响应中的16字节
array.Se用e表示图表。