Shredding a File with C# and the .NET Framework

Sun, 14 Sep 2008 05:00:41 +0000 - Author: Peter O.
The code below shows a way to shred files in C#, that is to delete a file so that its data cannot be recovered from the hard disk. The technique used here is to write random data to the file in ten passes. I would appreciate improvement. The code below follows, there are no restrictions to its use.
/*
 * (C) 2008 Peter O. 
 * Permission is granted to anyone to copy, modify,
 * and redistribute this file.  Attribution to the  
 * author would be appreciated but is not required.
 * No warranties are provided and all liabilities
 * are disclaimed.
 */
using System;
using System.IO;
using System.Security.Cryptography;
namespace PeterO
{
	public static class FileShredder
	{
		private static void ShreddingPass(FileStream stream, RNGCryptoServiceProvider rng){
				long size=stream.Length;
				byte[] buffer=new byte[4096];
				stream.Position=0;
				while(size>0){
					int trueLength=(int)Math.Min(4096,size);
					long oldPosition=stream.Position;
					// Fill buffer with random bytes
					rng.GetBytes(buffer);
					stream.Write(buffer,0,trueLength);
					// Flip bits of buffer and rewrite
					for(int i=0;i<trueLength;i++){
						buffer[i]^=(byte)0xFF;
					}
					stream.Position=oldPosition;
					stream.Write(buffer,0,trueLength);
					size-=4096;
					// Fill buffer with random bytes again
					rng.GetBytes(buffer);
					stream.Position=oldPosition;
					stream.Write(buffer,0,trueLength);
				}		
		}
		/// Deletes a file in a secure way, by filling the file with
		/// random data so that the data will no longer be recovered
		/// when the file is deleted.  No exception is thrown if the
		/// file does not exist.
		public static void Shred(string filename){
			// Check if file exists, just as File.Delete would.
			if(!File.Exists(filename))
				return;
			// Remove all attributes
			File.SetAttributes(filename,FileAttributes.Normal);
			// The option WriteThrough prevents data from being buffered before
			// writing to disk.  The option DeleteOnClose deletes the file when
			// the system closes it.
			using(FileStream stream=new FileStream(filename,
			                                       FileMode.Open,
			                                       FileAccess.Write,
			                                       FileShare.None,
			                                       4096,FileOptions.WriteThrough|FileOptions.DeleteOnClose)){
				RNGCryptoServiceProvider rng=new RNGCryptoServiceProvider();
				for(int i=0;i<5;i++){
					// Fill the file five times with random bytes
					ShreddingPass(stream,rng);
				}
			}
		}
	}
}