У меня есть некоторые выпущенные данные для расшифровки с использованием AES/CBC/PKCS5Padding в Java. Я шифрую два значения 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
}
При шифровании я вижу, что вектор внутри шифра обновляется после каждого обновления(), как и ожидалось (последний зашифрованный текст — это вектор для последующих обновлений. Например, зашифрованныйA — это вектор шифра в момент, когда я вызываю update(B)
Код расшифровки
Cipher cipherB = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding");
cipherB.init(Cipher.DECRYPT_MODE, fileKey, 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) и устанавливает вектор в значение зашифрованного A
Можете ли вы заметить что-то неправильное в моем подходе? Известны ли какие-либо проблемы в AES/CBC/PKCS5Padding при использовании поставщика SunJCE по умолчанию?
Обновление: прочитав некоторые комментарии, позвольте мне добавить некоторые дополнительные пояснения.
условия связаны с блоками, используемыми для шифрования полезной нагрузки. первое условие простое, пока (истина), а второе — если (blockCount › 1). есть счетчик блоков, который уменьшается в каждом цикле. Код обновлен
Если A и B опущены при шифровании/дешифровании, данные файла были правильно расшифрованы.
Я попытался расшифровать прямой результат шифрования, например:
cipherB.update(cipher.update(A))
но я все еще получаю тот же пустой массив вместо A
Я не могу полагаться на запуск обновлений дважды, после возврата B путем запуска cipherB.update(encryptedB) что-то идет не так, и на расшифровку данных файла влияет вектор в шифре. Данные, которые я возвращаю, выглядят примерно так
(12 случайных байтов) Lorem Ipsum и т. д.
A
иB
, а такжеencryptedA
на самом деле состоят из полного блока (16 байт), это действительно странное поведение, но это не должно быть проблемой. Или, по крайней мере, я не вижу проблемы в таком поведении, поскольку вы всегда можете вызвать следующийupdate
, и это было бы хорошей практикой для защиты кода. Базовый JCE может измениться в будущем, и вы должны писать свой код, не предполагая слишком много. - person Artjom B.   schedule 05.11.2020condition
иother condition
его цикл while может зависеть от расшифровываемых данных. В крайнем случае вызовыupdate()
могут вообще ничего не возвращать (например, с шифром AEAD), и только вызовdoFinal()
возвращает что-либо. Я подозреваю, что OP нужен другой дизайн. - person President James K. Polk   schedule 05.11.2020encryptedA
иencryptedB
являются полными блоками: первыйcipherB.update(encryptedA)
ничего не возвращает, потому что во время расшифровки как минимум полный блок остается в буфере. Это связано с заполнением (в контексте CBC): последний блок может содержать дополнение (вплоть до размера всего блока), которое не будет определено до следующегоupdate
/doFinal
. По той же причине последующийcipherB.update(encryptedB)
возвращает только открытый текст, относящийся кencryptedA
,encryptedB
остается в буфере и т. д. - person user 9014097   schedule 06.11.2020update
. Попробуйте изучить CipherInputStream и CipherOutputStream. Поскольку вы пишете в файл, это должен быть альтернативный API, где вы можете прочитать из потока столько байтов, сколько вам нужно. (Я до сих пор не уверен, почему это проблема для вас.) - person Artjom B.   schedule 06.11.2020