我在Java中使用模式“ AES / CBC / pkcs7padding”在2个设备之间进行通信。
建立通信后,两个设备之一将分配一个随机IV并将其发送到另一设备。接收者将使用此IV实例化一个cryptoCipher和一个解密Cipher(请参见下面的代码)。
注意:在这里,我只输入用于加密的代码,但是我们具有用于解密的类似代码。
IV矢量已在通信开始时发送。然后,我们希望2个设备交换加密的消息而不再发送IV。
如果我们的理解是正确的,则只要没有消息丢失,两个设备都应该知道在XOR中使用的当前“向量”是什么。
但是,Java代码无法正常运行:
如果我连续两次调用crypto(),它将产生相同的加密数据。
这不是我们期望的,因为我们认为第一次加密的结果将是第二次加密的“向量”(此向量与https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#CBC上所示的plainText之间的XOR)。
我们的理解错了吗?我们在实现过程中错过了什么吗?
private Cipher mEncryptionCipher;
private void createEncryptionCipher(byte[] iv) {
mEncryptionCipher = null;
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
mEncryptionCipher = Cipher.getInstance("AES/CBC/pkcs7padding", "BC");
mEncryptionCipher.init(Cipher.ENCRYPT_MODE, mAESKey, ivParameterSpec);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}
private byte[] encrypt(byte[] data) {
if (mEncryptionCipher == null) {
Log.e(TAG, "Invalid mEncryptionCipher!");
return null;
}
try {
int sizeOfEncryptedData = computeLengthAfterPKCS7Padding(data.length);
byte[] encodedData = new byte[sizeOfEncryptedData];
int cipherBytes = mEncryptionCipher.update(data, 0, data.length, encodedData, 0);
//allways call doFinal
cipherBytes += mEncryptionCipher.doFinal(encodedData, cipherBytes);
return encodedData;
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (ShortBufferException e) {
e.printStackTrace();
} catch (STException e) {
e.printStackTrace();
}
return null;
}
最佳答案
正如其他人建议的那样,请尽可能使用TLS。
否则,至少要从TLS的设计中汲取教训(错误)。在TLS 1.0(https://tools.ietf.org/html/rfc2246)中,CBC密码状态是在单独的记录中维护的,我认为这是您试图在“数据包”中进行的操作。在TLS 1.1(https://tools.ietf.org/html/rfc5246)中对此进行了更改,以便每个记录都包含一个明确的IV。每条记录的IV“应随机选择,并且必须不可预测”。因此,每个记录都是独立加密的。
请特别注意RFC 5246中安全性分析的这一部分:
F.3。显式IV
[CBCATT]描述了针对TLS的选定明文攻击,具体取决于
知道IV的记录。使用旧版TLS [TLS1.0]
先前记录的CBC残基为IV,因此
启用了此攻击。此版本使用显式IV,以
防范这种攻击。
也有其他陷阱在等着您,因此我回到我的第一个建议:尽可能使用TLS。
编辑:糟糕,TLS 1.1 RFC实际上是https://tools.ietf.org/html/rfc4346,它具有相同的F.3节。
关于java - vector 在Java中不会随着“AES/CBC/pkcs7padding”而改变,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51444347/