问题描述
我正在使用Java中的AES / CBC / PKCS5Padding发布一些解密数据。 我正在加密两个值A和B,然后加密文件中的数据。加密的值按描述的顺序写入文件中。 在解密各个字节的字节时,它们的位置正确(通过调试确认),并且解密函数的输入正确,在那里没有填充问题。
加密代码:
byte[] iv = {..........};
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE,fileKey,ivParameterSpec);
byte[] encryptedA = cipher.update(A);
byte[] encryptedB = cipher.update(B);
while( true){
if( blocks > 1 ) {
encrypted = cipher.update(data);
}
else {
encrypted = cipher.doFinal(data);
}
blocks--;
//write bytes to file
}
加密时,我可以看到密码中的向量在每次update()之后都按预期进行了更新(最后一个密文是后续更新的向量。例如,cryptoA是我调用update()时密码的向量B)
解密代码
Cipher cipherB = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
cipherB.init(Cipher.DECRYPT_MODE,ivParameterSpecB);
byte[] decryptedA = cipherB.update(encryptedA);
byte[] decryptedB = cipherB.update(encryptedB);
while( true){
if(blocks > 1 ) {
decrypted = cipherB.update(encryptedBytes);
}
else {
decrypted = cipherB.doFinal(encryptedBytes);
}
blocks--;
//write bytes to file
}
这时发生的事情很奇怪。
对cipherB.update(encryptedA)的首次呼叫 完全没有任何作用。它返回一个空数组,并且不更新密码中的向量。 对cipherB.update(encryptedB)的第二次呼叫 返回上次呼叫中我期望的值(cipherB.update(encryptedA),它是原始值:A),将向量设置为cryptonA
的值您能发现我的做法有什么问题吗?使用默认的SunJCE提供程序时,AES / CBC / PKCS5Padding中是否存在任何已知问题?
-
条件围绕用于加密有效负载的块。第一个条件是while(true),而第二个条件是if(blockCount> 1)。在每个循环中都有一个减少的块计数器。代码已更新
-
如果在加密/解密过程中省略了A和B,则表示文件数据已正确解密
-
我尝试解密加密的直接结果 例如:
cipherB.update(cipher.update(A))
但是我仍然得到相同的空数组而不是A
解决方法
明文和密文块彼此不一对一对应。您需要将整个输出捕获为byte []并自己解压缩。
, AES/CBC/PKCS5Padding
模式适用于块,因此更新将仅向您返回“已填充”的块,而doFinal将向您返回其余的块。 AES使用128位块,因此update
方法仅返回16字节的倍数。还有最后一个带有填充的块。因此,您的假设cipherB.update(cipher.update(A))
在这种情况下不起作用。
我并没有真正遵循条件if(blocks > 1 )
您可以使用以下代码来处理密码块(简化版):
byte[] decrypted = null;
byte[] buffer = new byte[BUFFER_SIZE];
InputStream in = ..;
for (int bytesRead=in.read(buffer); bytesRead>=0; bytesRead=in.read(buffer)) {
decrypted = cipher.update(buffer,bytesRead);
// process the chunk
}
decrypted = cipher.doFinal();
// process the chunk
这样,您是否处理单个块都没有关系。
当 update 方法直接返回加密或解密的块而不考虑输入大小时,也存在“流密码”或模式,例如AES/CTR
模式或Salsa20
密码