Кодировать CryptoStream в строку Base64 в блоках в C#
Существует метод (Version1), который кодирует входной поток, и есть функция Decrypt(), которая успешно декодирует кодированные данные. Но когда входные данные велики, может возникнуть ошибка OutOfMemory (в строке "string textEncrypted = Convert.ToBase64String (ms.ToArray ())").
Version1
private static Stream EncryptRijndael1(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16 * 1024];
int readed;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
}
}
string textEncrypted = Convert.ToBase64String(ms.ToArray());
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
Поэтому я изменил метод для обработки части массива по частям (куски). Вот Версия2. Это вызывает ошибку "смещение и длина должны ссылаться на позицию в строке" в строке Convert.ToBase64String (ms.ToArray (), offset, read).
Version2
private static Stream EncryptRijndael2(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
string textEncrypted = String.Empty;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16 * 1024];
int readed;
int offset = 0;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
textEncrypted += Convert.ToBase64String(ms.ToArray(), offset, readed);
offset += readed;
}
}
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
Тогда я сделал Version3. Он работает без ошибок, но длина выходных данных теперь больше, чем в версии 1, имеющей те же входные данные. Функция Decryt() выдает ошибку "Входные данные не являются допустимой строкой Base-64, поскольку она содержит неосновной 64-символ, более двух символов заполнения или недопустимый символ среди символов заполнения".
Version3
private static Stream EncryptRijndael3(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] bytesEncrypted;
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (MemoryStream ms = new MemoryStream())
{
string textEncrypted = String.Empty;
using (CryptoStream cs = new CryptoStream(ms, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
byte[] buffer = new byte[16*1024];
int readed;
while ((readed = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readed);
}
}
byte[] buffer1 = new byte[16*1024];
int readed1;
using (MemoryStream ms1 = new MemoryStream(ms.ToArray()))
{
while ((readed1 = (ms1.Read(buffer1, 0, buffer1.Length))) > 0)
{
if (readed1 < buffer1.Length)
{
var lastBuf = new List<Byte>();
for (int i = 0; i < readed1; i++)
{
lastBuf.Add(buffer1[i]);
}
textEncrypted += Convert.ToBase64String(lastBuf.ToArray());
continue;
}
textEncrypted += Convert.ToBase64String(buffer1);
}
}
bytesEncrypted = Encoding.ASCII.GetBytes(textEncrypted);
}
return new MemoryStream(bytesEncrypted);
}
Мой RijndaelManaged
private static RijndaelManaged RijndaelManagedWithConfig(byte[] key, byte[] iv)
{
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 128;
rjndl.Key = key;
rjndl.IV = iv;
rjndl.Mode = CipherMode.CBC;
rjndl.Padding = PaddingMode.PKCS7;
return rjndl;
}
Пожалуйста, помогите мне избавиться от ошибок или подскажите, как сделать процесс версии1 Convert.ToBase64String частично.
1 ответ
Я добился решения
private static Stream EncryptRijndael(byte[] key, byte[] iv, Stream plainText)
{
if (plainText == null)
return null;
byte[] buffer = new byte[5120 * 1024];
RijndaelManaged rjndl = RijndaelManagedWithConfig(key, iv);
using (var memoryStream = new MemoryStream())
{
int readedBytes;
using (var cs = new CryptoStream(memoryStream, rjndl.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
while ((readedBytes = (plainText.Read(buffer, 0, buffer.Length))) > 0)
{
cs.Write(buffer, 0, readedBytes);
}
}
using (var cryptoMemoryStream = new MemoryStream(memoryStream.ToArray()))
{
using (var base64MemoryStream = new MemoryStream())
{
using (ICryptoTransform transform = new ToBase64Transform())
{
using (var cryptStream = new CryptoStream(base64MemoryStream, transform, CryptoStreamMode.Write))
{
while ((readedBytes = cryptoMemoryStream.Read(buffer, 0, buffer.Length)) > 0)
{
cryptStream.Write(buffer, 0, readedBytes);
}
cryptStream.FlushFinalBlock();
}
return new MemoryStream(base64MemoryStream.ToArray());
}
}
}
}
}