Sending/Receiving File over Encrypted NetworkStream

stavesacre

Member
Joined
Dec 5, 2003
Messages
6
I am having trouble sending (receiving?) a file over an encrypted networkstream. Here is my send/receive code. The program does not appear to be either sending or receiving the file, not sure which. Any thoughts!??! This is a major headache, cause it seems as if im just missing something simple. Let me know if you need any more information....or maybe if theres a better method.

Thank-you in advance!


public void sendFile(String fileName, Stream networkStream)
{
FileStream fin = new FileStream(fileName,FileMode.Open, FileAccess.Read);

byte[] bin = new byte[100];
long rdlen = 0;
long totlen = fin.Length;
int len;

CryptoStream encStream = new CryptoStream(networkStream, tripleDES.CreateEncryptor(), CryptoStreamMode.Write);
Console.WriteLine("Encrypting...");

while(rdlen < totlen)
{
len = fin.Read(bin, 0, 100);
encStream.Write(bin, 0, len);
rdlen = rdlen + len;
Console.WriteLine("{0} bytes processed", rdlen);
}

encStream.Close();
}

---

public void receiveFile(FileStream fs, NetworkStream ns)
{
byte[] bin = new byte[100];
long rdlen = 0;
int len = 100;
CryptoStream decStream = new CryptoStream(fs, tripleDES.CreateDecryptor(), CryptoStreamMode.Write);

Console.WriteLine("Decrypting...");

while(ns.DataAvailable)
{
len = ns.Read(bin, 0, 100);
decStream.Write(bin, 0, len);
rdlen = rdlen + len;
Console.WriteLine("{0} bytes processed", rdlen);
}

decStream.Close();
}
 
Maybe i dont full understand CryptoStream? I am decrypting whatever I write to decStream. So Im reading from the network stream into a byte array, then Writing that byte array to decStream, which writes it to the FileStream.

Is that not the way to do it?
 
To be honest Ive never tried writing to a decryption stream that way. I personally would have based the decStream on the network stream and decrypted the bytes as they arrive and just write out the raw bytes to the file stream.
If you step through your code in the debugger does the client appear to send any data? If so is the receiving end getting it?

edit: typo
 
Last edited by a moderator:
actually. we have found that stepping through the code allows it to work. It has changed slighty, but still the same basic idea. Any thoughts now?
 
Weve got it to the point where sometimes it works, and sometimes it doesnt. Which sounds like blocking/flushing problem? Im not sure.

Stepping through the receive code....

----

public void sendFile(String fileName, Stream networkStream)
{
FileStream fin = new FileStream(fileName,FileMode.Open, FileAccess.Read);

//Create variables to help with read and write.
byte[] bin = new byte[100]; //This is intermediate storage for the encryption.
long rdlen = 0; //This is the total number of bytes written.
long totlen = fin.Length; //This is the total length of the input file.
int len; //This is the number of bytes to be written at a time.

CryptoStream encStream = new CryptoStream(networkStream, tripleDES.CreateEncryptor(), CryptoStreamMode.Write);
Console.WriteLine("Encrypting...");

//Read from the input file, then encrypt and write to the output file.
while(rdlen < totlen)
{
len = fin.Read(bin, 0, 100);
encStream.Write(bin, 0, len);
rdlen = rdlen + len;
//Console.WriteLine("{0} bytes processed", rdlen);
}

encStream.Close();
}


---


public void receiveFile(FileStream fs, NetworkStream ns)
{
while(!ns.DataAvailable){}
byte[] bin = new byte[100];
long rdlen = 0;
int len = 100;

//CryptoStream decStream = new CryptoStream(ns, tripleDES.CreateDecryptor(), CryptoStreamMode.Read);
CryptoStream decStream = new CryptoStream(fs,tripleDES.CreateDecryptor(), CryptoStreamMode.Write);
Console.WriteLine("Decrypting...");

while(len > 0)
{
//len = ns.Read(bin, 0, 100);
//len = decStream.Read(bin, 0, len);
len = ns.Read(bin, 0, len);
rdlen = rdlen + len;
decStream.Write(bin,0,len);
//Console.WriteLine("{0} bytes processed", rdlen);
}
decStream.FlushFinalBlock();
decStream.Close();


//decStream.Close();
ns.Close();
fs.Close();
}
 
How are you declaring the variable tripleDES? Trying to do the same thing here and just want to make sure Im getting things right.
 
Class Var:

TripleDESCryptoServiceProvider tripleDES;


Constructor:

tripleDES = new TripleDESCryptoServiceProvider();
tripleDES.Key = Encoding.Unicode.GetBytes("foobar12foob".ToCharArray());
tripleDES.IV = Encoding.Unicode.GetBytes("foob".ToCharArray());
 
Just tried that here and it worked fine - the transferred file was identical to the original. However I was running both ends on the same PC. How large a file are you transferring? I tested it here with a couple of MP3s about 5M in size quite happily.

When you sometimes it works and sometimes it doesnt how does it fail?
 
Last edited by a moderator:
Just tried it with my boot.ini file (322 bytes) - worked a treat

sending code is
C#:
	class Class1
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
		System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient("localhost",12345);
		Send s = new Send();
		s.sendFile("c:\\boot.ini",tcp.GetStream());
		}

		 
	}

	public class Send
	{

		TripleDESCryptoServiceProvider tripleDES;

		public Send()
		{
			tripleDES = new TripleDESCryptoServiceProvider();
			tripleDES.Key = Encoding.Unicode.GetBytes("foobar12foob".ToCharArray());
			tripleDES.IV = Encoding.Unicode.GetBytes("foob".ToCharArray());

		}

		public void sendFile(String fileName, Stream networkStream)
		{
			FileStream fin = new FileStream(fileName,FileMode.Open, FileAccess.Read);

			//Create variables to help with read and write.
			byte[] bin = new byte[100]; //This is intermediate storage for the encryption.
			long rdlen = 0; //This is the total number of bytes written.
			long totlen = fin.Length; //This is the total length of the input file.
			int len; //This is the number of bytes to be written at a time.

			CryptoStream encStream = new CryptoStream(networkStream, tripleDES.CreateEncryptor(), CryptoStreamMode.Write);
			Console.WriteLine("Encrypting...");

			//Read from the input file, then encrypt and write to the output file.
			while(rdlen < totlen)
			{
				len = fin.Read(bin, 0, 100);
				encStream.Write(bin, 0, len);
				rdlen = rdlen + len;
				//Console.WriteLine("{0} bytes processed", rdlen);
			}

			encStream.Close();
		}
	}

and receiving code is
C#:
	class Class1
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			//
			// TODO: Add code to start application here
			//
			Receive r = new Receive();
			System.IO.FileStream fs = System.IO.File.OpenWrite("c:\\test.txt");
			System.Net.Sockets.TcpListener tcp = new TcpListener(12345);
tcp.Start();

			r.receiveFile(fs,tcp.AcceptTcpClient().GetStream());
			System.Console.ReadLine();
		}

	}
}

public class Receive
{
	TripleDESCryptoServiceProvider tripleDES;

	public Receive()
	{
		tripleDES = new TripleDESCryptoServiceProvider();
		tripleDES.Key = Encoding.Unicode.GetBytes("foobar12foob".ToCharArray());
		tripleDES.IV = Encoding.Unicode.GetBytes("foob".ToCharArray());

	}

	public void receiveFile(FileStream fs, NetworkStream ns)
	{
		while(!ns.DataAvailable){}
		byte[] bin = new byte[100];
		long rdlen = 0;
		int len = 100;

		CryptoStream decStream = new CryptoStream(fs,tripleDES.CreateDecryptor(), CryptoStreamMode.Write);
		Console.WriteLine("Decrypting...");
		
		while(len > 0)
		{
			len = ns.Read(bin, 0, len);
			rdlen = rdlen + len;
			decStream.Write(bin,0,len);
			Console.WriteLine("{0} bytes read, {1} total bytes", len, rdlen);
		}
		decStream.FlushFinalBlock();
		decStream.Close();

		ns.Close();
		fs.Close();
	}
 
Back
Top