Encrypting/Decrypting a file using C# and RSA - c#

I am trying to encrypt and then decrypt an XML file using RSA and C# and while I'm really close, there's a problem. Once it's decrypted, almost all of the file is there but there's a hiccup toward the end. It's either a gap toward the end of the file or more data is appended to the very end of the file.
Here is my encrypt method:
public static bool Encrypt(ProcessingHolder ph)
{
FileInfo inFile = ph.encryptedFI;
FileInfo outFile = ph.unEncryptedFI;
X509Certificate2 daCert = new X509Certificate2(keyFP, daCertPassword);
RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)daCert.PrivateKey;
bool done = false;
FileStream fs = null;
FileStream fso = null;
try
{
//opens the file to encrypt into a filestream object
fs = inFile.OpenRead();
//240 is what the iOS side is using
//algorithm that calculates max bytes ((KeySize - 384) / 8) + 37
//(returns 245)
int chunkSize = 245;
fso = outFile.OpenWrite();
byte[] buffer = new byte[chunkSize];
int totalRead = 0;
while (totalRead < fs.Length)
{
int readBytes = fs.Read(buffer,0, chunkSize);
totalRead += readBytes;
//check to see if the final chunk of data is less than 245 so as not to write empty buffer
if (readBytes < chunkSize) buffer = new byte[readBytes];
//byte[] encr = new byte[readBytes];
//actual encryption
//encr = RSA.Encrypt(buffer, false);
byte[] encr = RSA.Encrypt(buffer, false);
fso.Write(encr, 0, encr.Length);
}
fso.Flush();
fso.Close();
fs.Close();
done = true;
}
catch (Exception ex)
{
Debug.WriteLine("Decrypt failed with message " + ex.Message);
done = false;
}
finally
{
if (fs != null) fs.Close();
if (fso != null) fso.Close();
}
return done;
}
}
and here is my decrypt method:
public static bool Decrypt(ProcessingHolder ph)
{
FileInfo inFile = ph.encryptedFI;
FileInfo outFile = ph.unEncryptedFI;
X509Certificate2 daCert = new X509Certificate2(keyFP, daCertPassword);
RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)daCert.PrivateKey;
bool done = false;
FileStream fs = null;
FileStream fso = null;
try
{
fs = inFile.OpenRead();
int chunkSize = 256;
fso = outFile.OpenWrite();
byte[] buffer = new byte[chunkSize];
int totalRead = 0;
while (totalRead < fs.Length)
{
int readBytes = fs.Read(buffer, 0, chunkSize);
totalRead += readBytes;
//check to see if the final chunk of data is less than 245 so as not to write empty buffer
//if (readBytes < chunkSize) buffer = new byte[readBytes];
byte[] decr = RSA.Decrypt(buffer, false);
fso.Write(decr, 0, decr.Length);
}
fso.Flush();
fso.Close();
fs.Close();
done = true;
}
catch (Exception ex)
{
Debug.WriteLine("Decrypt failed with message " + ex.Message);
done = false;
}
finally
{
if (fs != null) fs.Close();
if (fso != null) fso.Close();
}
return done;
}
banging my head against the wall here, thanks in advance

What happens during encrypting if the file is not a multiple of the length of the chunk size? Ie. a file 500 bytes long would read two sets of 245, but they have 10 bytes left over? This might be loosing the last few bytes at the end or adding extra values?
Maybe you need to add a header to the file with the size in bytes of the decrypted file so that the decrypter knows where to stop and a way to pad out the final block during encryption

Related

How to execute decrypted file automatically without specifying it's path?

Need help T_T
I'm running the code below to Decrypt an exe File I'm trying to Run it and Automatically execute the Decrypted file would it be possible to execute it without saving it's data to the disk?
I'm also trying to run it without the need of specifying the encrypted file name but have no idea what changes need to be done for this to happen or if it's even possible.
FileInfo encFile = new FileInfo("7GNTBBASDADASDASDASDASDASDASDASDSW7VBKGUX5TB5XBXDG3W4DWC6K6JBMTG7C2OYEHNPSN4PE6JYLJDUA"); // < File name in the current directory
const int ReadBufferSize = 64 * 1024;
static void Main(string[] args)
{
{
// DECRYPTION
FileInfo encFile = new FileInfo("7GNTBBASDADASDASDASDASDASDASDASDSW7VBKGUX5TB5XBXDG3W4DWC6K6JBMTG7C2OYEHNPSN4PE6JYLJDUA"); // < File name in the current directory
byte[] iv = Convert.FromBase64String("SWW/HAWEWQF/F2d/WrSSA==");
byte[] key = Convert.FromBase64String("ASDSADSAwwqIM221vASXG1221nqk=");
// DECRYPTION
// DECRYPTION
using (FileStream inp = encFile.OpenRead())
using (AesManaged aes = new AesManaged())
{
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
aes.IV = iv;
aes.Key = key;
using (CryptoStream cs = new CryptoStream(inp, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
// crypted file structure: {name length x4}{full file name}{data length x8}{data}{sha512 hash of data x64}
byte[] nameLengthBits = new byte[2];
if (cs.Read(nameLengthBits, 0, 2) != 2)
{
Console.Error.WriteLine("ERROR: Failed reading file name size");
return;
}
ushort nameLength = BitConverter.ToUInt16(nameLengthBits, 0);
byte[] originalName = new byte[nameLength];
if (cs.Read(originalName, 0, nameLength) != nameLength)
{
Console.Error.WriteLine("ERROR: Failed reading file name");
return;
}
string fileName = Encoding.UTF8.GetString(originalName);
byte[] dataLengthBits = new byte[8];
if (cs.Read(dataLengthBits, 0, dataLengthBits.Length) != dataLengthBits.Length)
{
Console.Error.WriteLine("ERROR: Failed reading data length");
return;
}
long dataLength = BitConverter.ToInt64(dataLengthBits, 0);
string outputFileName = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileName(fileName));
if (File.Exists(outputFileName))
{
}
byte[] decryptedHash;
long totalRead = 0;
using (FileStream outputStream = new FileStream(outputFileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
using (SHA512Managed hasher = new SHA512Managed())
{
byte[] buffer = new byte[ReadBufferSize];
long bytesRemaining = dataLength;
while (bytesRemaining > 0)
{
int readingThisRound = ReadBufferSize < bytesRemaining ? ReadBufferSize : (int)bytesRemaining;
int bytesRead = cs.Read(buffer, 0, readingThisRound);
totalRead += bytesRead;
// dump decrypted data to file
outputStream.Write(buffer, 0, bytesRead); }
//
//
hasher.TransformFinalBlock(buffer, 0, 0);
decryptedHash = hasher.Hash;}
byte[] originalHashBits = new byte[64];
if (cs.Read(originalHashBits, 0, originalHashBits.Length) != originalHashBits.Length) using (FileStream outputStream = new FileStream(outputFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
}
if (originalHashBits.SequenceEqual(decryptedHash))

How do I zip files in Xamarin for Android?

I have a function that creates a zip file a string array of files passed. The function does succeed in creating the zip file and the zip entry files inside it, but these zip entry files are empty. I've tried a couple of different methods - the function code below is the closest I've gotten to something working:
public static bool ZipFile(string[] arrFiles, string sZipToDirectory, string sZipFileName)
{
if (Directory.Exists(sZipToDirectory))
{
FileStream fNewZipFileStream;
ZipOutputStream zos;
try {
fNewZipFileStream = File.Create(sZipToDirectory + sZipFileName);
zos = new ZipOutputStream(fNewZipFileStream);
for (int i = 0; i < arrFiles.Length; i++) {
ZipEntry entry = new ZipEntry(arrFiles[i].Substring(arrFiles[i].LastIndexOf("/") + 1));
zos.PutNextEntry(entry);
FileStream fStream = File.OpenRead(arrFiles[i]);
BufferedStream bfStrm = new BufferedStream(fStream);
byte[] buffer = new byte[bfStrm.Length];
int count;
while ((count = bfStrm.Read(buffer, 0, 1024)) != -1) {
zos.Write(buffer);
}
bfStrm.Close();
fStream.Close();
zos.CloseEntry();
}
zos.Close();
fNewZipFileStream.Close();
return true;
}
catch (Exception ex)
{
string sErr = ex.Message;
return false;
}
finally
{
fNewZipFileStream = null;
zos = null;
}
}
else
{
return false;
}
}
I think it's got to do with the byte stream handling. I've tried this bit of code that handles the stream but it goes into an infinite loop:
while ((count = fStream.Read(buffer, 0, 1024)) != -1) {
zos.Write(buffer, 0, count);
}
fStream.Close();
I found a solution that is quite simple - I used the ReadAllBytes method of the static File class.
ZipEntry entry = new ZipEntry(arrFiles[i].Substring(arrFiles[i].LastIndexOf("/") + 1));
zos.PutNextEntry(entry);
byte[] fileContents = File.ReadAllBytes(arrFiles[i]);
zos.Write(fileContents);
zos.CloseEntry();
Using Read() on a FileStream returns the amount of bytes read into the stream or 0 if the end of the stream has been reached. It will never return a value of -1.
From MSDN:
The total number of bytes read into the buffer. This might be less than the number of bytes requested if that number of bytes are not currently available, orzero if the end of the stream is reached.
I'd modify your code to the following:
System.IO.FileStream fos = new System.IO.FileStream(sZipToDirectory + sZipFileName, FileMode.Create);
Java.Util.Zip.ZipOutputStream zos = new Java.Util.Zip.ZipOutputStream(fos);
byte[] buffer = new byte[1024];
for (int i = 0; i < arrFiles.Length; i++) {
FileInfo fi = new FileInfo (arrFiles[i]);
Java.IO.FileInputStream fis = new Java.IO.FileInputStream(fi.FullName);
ZipEntry entry = new ZipEntry(arrFiles[i].Substring(arrFiles[i].LastIndexOf("/") + 1));
zos.PutNextEntry(entry);
int count = 0;
while ((count = fis.Read(buffer)) > 0) {
zos.Write(buffer, 0, count);
}
fis.Close();
zos.CloseEntry();
}
This is nearly identical to the code I've used for creating zip archives on Android in the past.
Are you allowed to use SharpZip? It's really easy to use.
Here is a blog post I wrote to extract zip files
private static void upzip(string url)
{
WebClient wc = new WebClient();
wc.DownloadFile(url, "temp.zip");
//unzip
ZipFile zf = null;
try
{
zf = new ZipFile(File.OpenRead("temp.zip"));
foreach (ZipEntry zipEntry in zf)
{
string fileName = zipEntry.Name;
byte[] buffer = new byte[4096];
Stream zipStream = zf.GetInputStream(zipEntry);
using (FileStream streamWriter = File.Create( fileName))
{
StreamUtils.Copy(zipStream, streamWriter, buffer);
}
}
}
finally
{
if (zf != null)
{
zf.IsStreamOwner = true;
zf.Close();
}
}
}
private void ZipFolder(string[] _files, string zipFileName)
{
using var memoryStream = new MemoryStream();
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (var item in _files)
{
var demoFile = archive.CreateEntry(Path.GetFileName(item));
using var readStreamW = File.OpenRead(item);
using (var entryStream = demoFile.Open())
{
using (var streamWriter = new StreamWriter(entryStream))
{
readStreamW.Seek(0, SeekOrigin.Begin);
readStreamW.CopyTo(streamWriter.BaseStream);
}
}
}
}
using var fileStream = new FileStream(zipFileName, FileMode.Create);
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fileStream);
}

Converting stream encryption method from .NET to RT

I'm trying to convert Encryption/Decryption methods from managed .NET to WinRT version for use in Windows Store app. The managed .NET encryption methods are already used largely in production, so the assumption is they work correctly.
This is the managed .NET encryption method:
public static byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
public static void EncryptFile(string sInputFilename, string sOutputFilename, string sKey)
{
FileStream fsInput = null;
FileStream fsOutput = null;
CryptoStream cryptostream = null;
try
{
#region Prep
fsInput = new FileStream(sInputFilename, FileMode.Open, FileAccess.Read);
fsOutput = new FileStream(sOutputFilename, FileMode.Create, FileAccess.Write);
var cryptoDes = new DESCryptoServiceProvider { IV = iv, Key = Convert.FromBase64String(sKey), Mode = CipherMode.CBC };
var desEncrypt = cryptoDes.CreateEncryptor();
#endregion
cryptostream = new CryptoStream(fsOutput, desEncrypt, CryptoStreamMode.Write);
long startIndex = 0;
var bytearrayinput = new byte[64];
var byteCount = bytearrayinput.Length;
while (startIndex < fsInput.Length)
{
if (fsInput.Length - startIndex < byteCount)
{
byteCount = (int)(fsInput.Length - startIndex);
}
fsInput.Read(bytearrayinput, 0, byteCount);
cryptostream.Write(bytearrayinput, 0, byteCount);
startIndex += byteCount;
}
cryptostream.FlushFinalBlock();
}
finally
{
if (fsInput != null) { fsInput.Close(); }
if (cryptostream != null) { cryptostream.Close(); }
if (fsOutput != null) { fsOutput.Close(); }
}
}
This is the WinRT version that uses CryptographicEngine.
public static async Task EncryptContentFile(IRandomAccessStream inputStream, IRandomAccessStream outputStream, string key)
{
var iv = CryptographicBuffer.CreateFromByteArray(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
var keyMaterial = CryptographicBuffer.DecodeFromBase64String(key);
var cryptoProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.DesCbcPkcs7);
var symmetricKey = cryptoProvider.CreateSymmetricKey(keyMaterial);
var inStream = inputStream.AsStreamForRead();
var outStream = outputStream.AsStreamForWrite();
try
{
var size = (long)inputStream.Size;
var chunkSize = 64L;
//var finalChunk = false;
while (inStream.Position < size)
{
if (size - inStream.Position < chunkSize)
{
chunkSize = size - inStream.Position;
//finalChunk = true;
}
var chunk = new byte[chunkSize];
await inStream.ReadAsync(chunk, 0, (int)chunkSize);
var writeBuffer = CryptographicEngine.Encrypt(symmetricKey, chunk.AsBuffer(), iv).ToArray();
await outStream.WriteAsync(writeBuffer, 0, (int)chunkSize);
//await outStream.WriteAsync(writeBuffer, 0, finalChunk ? writeBuffer.Length : (int)chunkSize);
}
await outputStream.FlushAsync();
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
The goal is to be able to encrypt large files by reading and encrypting chunks of bytes. The problem that I have with the RT method is that everytime it encrypts a chunk, the encrypted bytes are larger by 8 bytes. I understand on the .NET side this is what CryptoStream.FlushFinalBlock() adds.
I tried trimming the bytes to the original size (the commented finalChunk code), but it didn't help.
How can I reliably encrypt in WinRT and have the final encrypted file be identical with what the .NET method produces.
Thank you
To answer my question, I found the problem. Windows Runtime doesn't support buffered encryption and will always treat data as a whole. While the .NET ICryptoTransform contains methods like TransformBlock and TransformFinalBlock, the RT API always uses treats data as final, which makes it impossible to encrypt large streams by chunks.
I ended up using BouncyCastle PCL library which worked out perfectly. Similarly, DesEngine in BouncyCastle has method ProcessBytes and DoFinal which correspond to the above mentioned .NET methods in ICryptoTransform.
Hope this helps someone.
private Task TransformStream_DesCbcPkcs7_WithProgress(bool forEncryption, Stream inputStream, Stream outputStream, byte[] key, byte[] iv, IProgress<int> progress)
{
return Task.Run(async () =>
{
// Initialize symmetric crypto engine
// Algorithm: DES
// Mode of operation: CBC
// Byte padding: PKCS#7
var engine = new PaddedBufferedBlockCipher(new CbcBlockCipher(new DesEngine()), new Pkcs7Padding());
engine.Init(forEncryption, new ParametersWithIV(new DesParameters(key), iv));
// Report progress if available
Action<int> report = x =>
{
if (progress != null)
progress.Report(x);
};
var size = inputStream.Length;
var current = inputStream.Position;
var chunkSize = 1024 * 1024L;
var lastChunk = false;
report(0);
await Task.Yield();
// Initialize DataReader and DataWriter for reliable reading and writing
// to a stream. Writing directly to a stream is unreliable.
using (var reader = new BinaryReader(inputStream))
using (var writer = new BinaryWriter(outputStream))
{
while (current < size)
{
if (size - current < chunkSize)
{
chunkSize = (uint)(size - current);
lastChunk = true;
}
var chunk = new byte[chunkSize];
reader.Read(chunk, 0, (int)chunkSize);
// The last chunk must call DoFinal() as it appends additional bytes
var processedBytes = lastChunk ? engine.DoFinal(chunk) : engine.ProcessBytes(chunk);
writer.Write(processedBytes);
current = inputStream.Position;
report((int)(current * 100F / size));
await Task.Yield();
}
await outputStream.FlushAsync();
}
});
}

Transfer really large files using WebClient

My requirement is to transfer a zip file of size 400MB or more; The following code works for at least 40MB; But for more I would have to change byte[] bytes = new byte[50000000]; to byte[] bytes = new byte[400000000]; and maxRequestLength to maxRequestLength="409600";
The problem is byte[] bytes = new byte[100000000]; returns an error regarding insufficient space. So how can I transfer large files using WebClient??
WebClient client = new WebClient();
client.AllowWriteStreamBuffering = true;
UriBuilder ub = new UriBuilder("http://localhost:57596/UploadImages.ashx");
ub.Query = "ImageName=" + "DataSet" + DataSetId + ".zip";
client.OpenWriteCompleted += (InputStream, eArguments) =>
{
try
{
using (Stream output = eArguments.Result)
{
output.Write(ImagesAux, 0, (int)ImagesAux.Length);
//numeroimagem++;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
//throw;
}
};
client.OpenWriteAsync(ub.Uri);
in UploadImages.ashx
public void ProcessRequest(HttpContext context)
{
//context.Response.ContentType = "text/plain";
//context.Response.Write("Hello World");
string ImageName = context.Request.QueryString["ImageName"];
string UploadPath = context.Server.MapPath("~/ServerImages/");
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[50000000]; //
int bytesToRead = 0;
while ((bytesToRead =
context.Request.InputStream.Read(bytes, 0, bytes.Length)) != 0)
{
stream.Write(bytes, 0, bytesToRead);
stream.Close();
}
}
}
in Web.config
<httpRuntime targetFramework="4.5" maxRequestLength="40960"/>
You should never load everything in memory then write all back to disk, but instead you should load pieces and write them to disk while you are reading them.
When you've done reading you close the stream you are writing to.
Otherwise as soon as you reach sizes as GB you can get an OutOfMemory really quick.
So I would change the writing bytes to disk from this:
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[50000000]; //
int bytesToRead = 0;
while ((bytesToRead = context.Request.InputStream.Read(bytes, 0, bytes.Length)) != 0)
{
stream.Write(bytes, 0, bytesToRead);
stream.Close();
}
}
to this:
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[1024];
long totalBytes = context.Request.InputStream.Length;
long bytesRead = 0;
int bytesToRead = bytes.Length;
if (totalBytes - bytesRead < bytes.Length)
bytesToRead = (int)(totalBytes - bytesRead);
bytes = new byte[bytesToRead];
while ((bytesToRead = context.Request.InputStream.Read(bytes, bytesRead, bytes.Length)) != 0)
{
stream.Write(bytes, bytesRead, bytes.Length);
bytesRead += bytes.Length;
if (totalBytes - bytesRead < bytes.Length)
bytesToRead = (int)(totalBytes - bytesRead);
bytes = new byte[bytesToRead];
}
stream.Close();
}
1024 would be the buffer size.

Streaming image over ssl socket doesn't come across correctly

I'm trying to securely transfer files between 2 devices, so I'm using an SslStream attached to a TcpClient. Documents and text files come across just fine, but image files don't show up correctly. The following is the server code:
listener = new TcpListener(IPAddress.Any, 1337);
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidationCallback), new LocalCertificateSelectionCallback(CertificateSelectionCallback));
var certificate = Connection.GetClientCertificate(((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
try
{
sslStream.AuthenticateAsServer(certificate, true, SslProtocols.Default, true);
sslStream.ReadTimeout = 5000;
sslStream.WriteTimeout = 5000;
var messageData = ReadMessage(sslStream);
var mode = messageData[0];
var tokenBytes = messageData.Splice(1, 16);
var fileNameBytes = messageData.Splice(17, 128);
var fileBytes = messageData.Splice(146);
var fileName = Encoding.ASCII.GetString(fileNameBytes).TrimEnd('\0');
using (var tempFile = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write))
{
tempFile.Write(fileBytes, 0, fileBytes.Length);
tempFile.Flush();
}
if (mode == 0)
tempFiles.Add(fileName);
Process.Start(fileName);
}
catch (AuthenticationException e)
{
MessageBox.Show("The other side failed to authenticate.");
}
finally
{
sslStream.Close();
client.Close();
}
}
And ReadMessage is defined as follows:
private static byte[] ReadMessage(SslStream sslStream)
{
byte[] buffer = new byte[2048];
MemoryStream stream = new MemoryStream();
int bytes = -1;
while (bytes != 0)
{
bytes = sslStream.Read(buffer, 0, buffer.Length);
stream.Write(buffer, 0, bytes);
}
return stream.ToArray();
}
And then the client code is this:
TcpClient client = new TcpClient();
client.Connect(new IPEndPoint(IPAddress.Parse(ip), 1337));
SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(CertificateValidationCallback), new LocalCertificateSelectionCallback(CertificateSelectionCallback));
var certificate = Connection.GetClientCertificate(ip);
try
{
sslStream.AuthenticateAsClient(ip, new X509CertificateCollection() { certificate }, SslProtocols.Default, false);
sslStream.ReadTimeout = 5000;
sslStream.WriteTimeout = 5000;
sslStream.Write(data);
}
catch (AuthenticationException e)
{
MessageBox.Show("The other side failed to authenticate.");
}
finally
{
sslStream.Close();
client.Close();
}
And the code that calls into it just does:
var fileBytes = File.ReadAllBytes(file);
var tokenBytes = Encoding.UTF8.GetBytes(token);
var fileNameBytes = Encoding.UTF8.GetBytes(Path.GetFileName(file));
var buffer = new byte[145 + fileBytes.Length];
buffer[0] = 1;
for (int i = 0; i < 16; i++)
{
buffer[i + 1] = tokenBytes[i];
}
for (int i = 0; i < fileNameBytes.Length; i++)
{
buffer[i + 17] = fileNameBytes[i];
}
for (int i = 0; i < fileBytes.Length; i++)
{
buffer[i + 145] = fileBytes[i];
}
SocketConnection.Send(ip, buffer);
Is there anything inherently wrong with what I'm doing, or do I need to do something different for images?
EDIT: I have changed it to reflect the current code, and also, after doing a dump of the raw bytes on both ends, it looks like for some reason the bytes are getting rearranged when they come over the wire. Is there any way to ensure that the bytes come across in the original order?
In ReadMessage you're writing bytes.Length bytes to the stream, regardless of the number of bytes that were actually read. Try:
private static byte[] ReadMessage(SslStream sslStream)
{
byte[] buffer = new byte[2048];
MemoryStream stream = new MemoryStream();
int bytes = -1;
while (bytes != 0)
{
bytes = sslStream.Read(buffer, 0, buffer.Length);
// Use "bytes" instead of "buffer.Length" here
stream.Write(buffer, 0, bytes);
}
return stream.ToArray();
}
Based on your follow-up, you're also taking the file data from the wrong point in the buffer, and so you're losing the first byte of the file.
Your code should be:
var fileBytes = messageData.Splice(145); // File data starts at 145, not 146
Is this possibly a conflict between endianness? If the bytes from the server are ABCDEF and the client is seeing the image bytes as BADCFE then that's the issue.
I haven't worked with image files, but when I read a short or an int instead of a String from the bytes coming in over the wire, I do something like this:
int intFromStream = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(byteArrayWithLength4, 0));

Categories

Resources