Introduction
This is an attempt to make it a little more secure to delete files using C#. Let's face it: using File.Delete
doesn't really delete the file; it just makes the OS think that the file doesn't exist. The space on the disc that the file occupied is marked as free and available for writing, but the file's data is not removed and can be recovered quite easily. The file is not gone until the space it occupied is overwritten, preferably several times.
I have put together a simple class that can be used to accomplish the procedure of writing garbage data to the file before deleting it. To take it a step further, I truncate the file to 0 bytes and change the file-dates. However, the step to change the file dates only seems to work on FAT 16/32 and not NTFS. After running several tests with Ontrack EasyRecovery, PC Inspector File Recovery and GetDataBack, I could not recover any of the files. I even ran Disk Investigator after deleting a text-file, checking the individual clusters, and I couldn't get a single word back from the file.
Background
The background to this project is simple. After using file-wipers/shredders for years now, I wanted to see what could be accomplished with .NET.
Using the Code
There is only one method that you need to call, namely WipeFile
and the code is as shown below. So, all you really have to do is call WipeFile
and supply the full path of the file to be deleted, as well as the number of times you want to overwrite it.
public void WipeFile(string filename, int timesToWrite)
{
try
{
if (File.Exists(filename))
{
File.SetAttributes(filename, FileAttributes.Normal);
double sectors = Math.Ceiling(new FileInfo(filename).Length/512.0);
byte[] dummyBuffer = new byte[512];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
FileStream inputStream = new FileStream(filename, FileMode.Open);
for (int currentPass = 0; currentPass < timesToWrite; currentPass++)
{
UpdatePassInfo(currentPass + 1, timesToWrite);
inputStream.Position = 0;
for (int sectorsWritten = 0; sectorsWritten < sectors; sectorsWritten++)
{
UpdateSectorInfo(sectorsWritten + 1, (int) sectors);
rng.GetBytes(dummyBuffer);
inputStream.Write(dummyBuffer, 0, dummyBuffer.Length);
}
}
inputStream.SetLength(0);
inputStream.Close();
DateTime dt = new DateTime(2037, 1, 1, 0, 0, 0);
File.SetCreationTime(filename, dt);
File.SetLastAccessTime(filename, dt);
File.SetLastWriteTime(filename, dt);
File.Delete(filename);
WipeDone();
}
}
catch(Exception e)
{
WipeError(e);
}
}
I have added some events just to be able to keep track of what's happening during the process.
PassInfoEvent
- Returns which pass is running and the total number of passes to be run.
SectorInfoEvent
- Returns which sector is being written to and the total number of sectors to be written to.
WipeDoneEvent
- An indicator that the wipe process is done.
WipeErrorEvent
- Returns the exception if anything went wrong.
Acknowledgements
I'd like to thank PIEBALDconsult for his time and help in the forum while working with this.
History
- 7 January, 2008 -- Original version posted
- 14 January, 2008 -- First update