Shredding a File with C# and the .NET Framework
Sun, 14 Sep 2008 01:00:41 -0400 - Author:
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);
}
}
}
}
}
