Неправильный размер зашифрованных данных (AES)
Мне нужно выполнить шифрование массива байтов []. Я использовал пример, доступный в Microsoft. К сожалению, зашифрованные данные усекаются до размера, кратного 16. Если в примере данных я добавлю 8 раз байт 0, данные будут зашифрованы должным образом. Padding был установлен, но я не вижу ничего, чтобы изменить его. Как решить эту проблему, данные не становятся отрезанными.
public byte[] EncryptAES(byte[] plainBytes)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] FKey = encoding.GetBytes("A002AD9AD73C402190C3E733D82CEA00");
byte[] FIV = encoding.GetBytes("zyxwvutsrqponmlk");
// Check arguments.
if (plainBytes == null || plainBytes.Length <= 0)
throw new ArgumentNullException("plainText");
if (FKey == null || FKey.Length <= 0)
throw new ArgumentNullException("Key");
if (FIV == null || FIV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
// Create an RijndaelManaged object
// with the specified key and IV.
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = FKey;
rijAlg.IV = FIV;
rijAlg.Padding = PaddingMode.Zeros;
rijAlg.Mode = CipherMode.CBC;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
// plainBytes.Length = 2216
csEncrypt.Write(plainBytes, 0, plainBytes.Length);
// encrypted.Length = 2208
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
4 ответа
CryptoStream
:
Вы всегда должны явно закрывать свой объект CryptoStream после того, как вы закончили использовать его, вызвав метод Close. Это очищает поток и вызывает обработку всех оставшихся блоков данных объектом CryptoStream. Однако если перед вызовом метода Close возникает исключение, объект CryptoStream может не закрыться. Чтобы метод Close вызывался всегда, поместите вызов метода Close в блоке finally оператора try/catch.
(Мой акцент)
Итак, позвоните Close
прежде чем пытаться что-либо сделать с результатами.
По сути, заполнение используется для обработки последнего блока последовательности зашифрованных блоков. Так как CryptoStream
не знает, сколько раз вы намереваетесь позвонить Write()
, он не применяет заполнение или запись окончательного незавершенного блока, пока вы не вызовете Close
,
(Или, как указывает Монкибой, FlushFinalBlock
также может использоваться, чтобы указать, что вы закончили)
Попробуй это
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(plainBytes, 0, plainBytes.Length);
}
encrypted = msEncrypt.ToArray();
}
Также важно соблюдать осторожность при расшифровке данных с помощью
CryptoStream
. Рекомендуется читать с использованием
loop
. Вызов
Read
только один раз может привести к усеченным результатам.
using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Read))
{
plainTextBytes = new byte[cleanCipherBytes.Length];
int read = 0, rem = plainTextBytes.Length;
do
{
read = crypto.Read(plainTextBytes, read, rem);
rem -= read;
}
while (read > 0);
}
Это заняло у меня довольно много времени, чтобы понять. Я надеюсь, что это сэкономит чье-то время.