I try write and read back string from file. Use this code for the write:
...
Aes aes = Aes.Create();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(passwordBytes, salt, 185000, HashAlgorithmName.SHA512);
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
createstream.Write(salt, 0, salt.Length);
using (DeflateStream compresstream = new DeflateStream(createstream, CompressionLevel.Optimal))
{
using (CryptoStream cryptostream = new CryptoStream(compresstream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] str = Encoding.UTF8.GetBytes("TestString")!;
byte[] strl = BitConverter.GetBytes(str.Length);
cryptostream.Write(strl, 0, 4);
cryptostream.Write(str, 0, str.Length);
byte[] str1 = Encoding.UTF8.GetBytes("TestString2")!;
byte[] strl1 = BitConverter.GetBytes(str1.Length);
cryptostream.Write(strl1, 0, 4);
cryptostream.Write(str1, 0, str1.Length);
}
}
And this for the read back:
...
readstream.Read(salt, 0, salt.Length);
...
Aes aes = Aes.Create();
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(passwordBytes, salt, 185000, HashAlgorithmName.SHA512);
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
using (DeflateStream decompresstream = new DeflateStream(readstream, CompressionMode.Decompress))
{
using (CryptoStream decryptostream = new CryptoStream(decompresstream, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
byte[] str = new byte[4];
decryptostream.Read(str, 0, str.Length);
int size = BitConverter.ToInt32(str, 0);
byte[] strl = new byte[size];
decryptostream.Read(strl, 0, size);
string result = Encoding.UTF8.GetString(strl);
byte[] str1 = new byte[4];
decryptostream.Read(str1, 0, str1.Length);
int size1 = BitConverter.ToInt32(str1, 0);
byte[] strl1 = new byte[size1];
decryptostream.Read(strl1, 0, size1);
string result1 = Encoding.UTF8.GetString(strl1);
Console.WriteLine($"String: {result} {result1}");
Console.ReadLine();
}
}
My problem is...after reading back, i get this result: String: TestString TestStrin. Why cryptostream is cut my string?
If i write the digits, the CryptoStream is read correctly for all. How to right write or read string correctly use CryptoStream?
Try switching to ReadExactly
(available since .net-7.0) from Read
:
using (DeflateStream decompresstream = new DeflateStream(readstream, CompressionMode.Decompress))
using (CryptoStream decryptostream =
new CryptoStream(decompresstream, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
byte[] str = new byte[4];
decryptostream.ReadExactly(str, 0, str.Length);
int size = BitConverter.ToInt32(str, 0);
byte[] strl = new byte[size];
decryptostream.ReadExactly(strl, 0, strl.Length);
string result = Encoding.UTF8.GetString(strl);
byte[] str1 = new byte[4];
decryptostream.ReadExactly(str1, 0, str1.Length);
int size1 = BitConverter.ToInt32(str1, 0);
byte[] strl1 = new byte[size1];
decryptostream.ReadExactly(strl1, 0, strl1.Length);
string result1 = Encoding.UTF8.GetString(strl1);
Console.WriteLine($"String: {result} {result1}");
}
If you are running earlier version then you will need to implement it yourself for example via while
cycle. Something along these lines:
public static class StreamExts
{
public static void ReadExactlyOrTillEnd(this Stream stream, byte[] buffer)
{
if (buffer.Length == 0)
{
return;
}
var read = -1;
var total = 0;
while (total < buffer.Length && read != 0)
{
read = stream.Read(buffer, total, buffer.Length - total);
total += read;
}
}
}
Read more:
Stream.Read
:
Returns: The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.