C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 05-04-2009, 11:29 PM   #1
Registered User
 
mihnea's Avatar
 
Join Date: May 2009
Posts: 2
Smile Secure File Deletion

Hello everybody!

I have developed a portable secure file deletion utility. I want to ask you if you think my approach is enough in terms of ensuring the adequate security. If so, I could extend my application to support recursive directories structures, as well as multiple files selection.

Another question would be how to implement secure overwriting of free space on the disc. Can it be done in a portable manner? Even if not, what are my options?

Thank you for reading my post!

Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/* 4 MB buffer */
#define BUFFER_SIZE (4 * 1024 * 1024)

#define MAX_UNSIGNED_CHAR_VAL 255

#define MAX_DELETE_ITERATIONS 32

/* Securely erases a file on the disc, by overwriting,
   a given number of times, its content with a random
   sequence of bytes. */
int DeleteFile(const char* const fileName, unsigned int overwriteCount)
{
	FILE* fileToErase;
	long fileSize, filePosition;
	unsigned char* buffer;
	size_t bytesToWrite;
	unsigned int i, j;

	if ((fileToErase = fopen(fileName, "rb+")) == NULL)
		return -1;

	if (overwriteCount > MAX_DELETE_ITERATIONS)
		overwriteCount = MAX_DELETE_ITERATIONS;

	/* Sets the file stream to be unbuffered */
	setbuf(fileToErase, NULL);

	/* Determines the file length */
	fseek(fileToErase, 0, SEEK_END);
	fileSize = ftell(fileToErase);

	printf("\nStarting the wipe of file \"%s\" ...\n", fileName);

	if (fileSize > 0)
	{
		/* Allocates the buffer on the heap */
		buffer = (unsigned char*)malloc(BUFFER_SIZE * sizeof(unsigned char));

		/* Data overwrite iteration */
		for (i = 0; i < overwriteCount; i++)
		{
			/* Initializes the random generator */
			srand((unsigned int)time(NULL));
			
			/* Initializes the random buffer */
			for (j = 0; j < BUFFER_SIZE; j++)
				buffer[j] = (unsigned char)(rand() % (MAX_UNSIGNED_CHAR_VAL + 1));
			
			printf("\nWipe iteration %u ... ", i + 1);
			
			/* Moves the file pointer to the beginning of the file */
			fseek(fileToErase, 0, SEEK_SET);
			filePosition = 0;

			/* Data overwriting block */
			while (filePosition < fileSize)
			{
				if (filePosition + BUFFER_SIZE <= fileSize)
					bytesToWrite = BUFFER_SIZE;
				else
					bytesToWrite = (size_t)(fileSize - filePosition);

				fwrite(buffer, sizeof(unsigned char), bytesToWrite, fileToErase);

				printf("#");

				filePosition += (long)bytesToWrite;
			}

			printf("   Done\n");
		}

		free(buffer);
	}

	fclose(fileToErase);
                          
	if (remove(fileName) < 0)
		return -2;

	return 0;
}

int main(int argc, char** argv)
{
	unsigned int iterationsCount;
	
	if ( (argc != 3) || ((iterationsCount = (unsigned int)atoi(argv[2])) == 0) )
	{
		fprintf(stderr, "\nUsage: wipeit file_path iterations_count\n");
		return -1;
	}
	
	if (DeleteFile(argv[1], iterationsCount) < 0)
	{
		fprintf(stderr, "\nCould not delete the file \"%s\".\n", argv[1]);
		return -2;
	}

	printf("\nFile \"%s\" deleted successfully.\n", argv[1]);
	return 0;
}
mihnea is offline   Reply With Quote
Old 05-04-2009, 11:42 PM   #2
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,379
I didn't look too hard, but it seems okay to me.

Quote:
Another question would be how to implement secure overwriting of free space on the disc. Can it be done in a portable manner? Even if not, what are my options?
You can access the free space on the disk by causing it to not be free anymore -- i.e., open a file, and start writing to it until you run out of disk space. Then secure-delete this file. If you write random data, you've done pass 1 of the secure deletion already.

I doubt that will cause every single sector of unallocated space to be overwritten, but portably, it's the best you can do I think.
__________________
"Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot
brewbuck is online now   Reply With Quote
Old 05-05-2009, 05:06 AM   #3
and the hat of sweating
 
Join Date: Aug 2007
Location: Toronto, ON
Posts: 3,119
Why do you call srand() inside your loop?
Just call it once in main().
__________________
"I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008
cpjust is offline   Reply With Quote
Old 05-05-2009, 06:06 AM   #4
Registered User
 
mihnea's Avatar
 
Join Date: May 2009
Posts: 2
Quote:
Originally Posted by cpjust View Post
Why do you call srand() inside your loop?
Just call it once in main().
Not inside the writing loop, just at each file writing iteration. Therefore, rewriting the file x times with x different pseudo-random sequences.
mihnea is offline   Reply With Quote
Old 05-05-2009, 06:11 AM   #5
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,352
Grr... I already told you elsewhere: go and investigate Eraser.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is offline   Reply With Quote
Old 05-05-2009, 07:12 AM   #6
Ex scientia vera
 
Join Date: Sep 2007
Posts: 426
Quote:
Originally Posted by laserlight View Post
Grr... I already told you elsewhere: go and investigate Eraser.
Alright, perhaps he did that. Why can't he post this here, in the hope of someone having information on this, to ask for an extra opinion?

OT:

The FBI and such agencies use some devices that can detect magnetic residue on the hard drives. If write random data over the file, then you take that random data and write the exact opposite of it, e.g.

1010 1010 = Normal
0101 0101 = Opposite

You will have flipped the bits. You do this several times, and in theory, this should then only leave magnetic residue that, when "recovered", only gives the random garbage data.
__________________
"What's up, Doc?"
"'Up' is a relative concept. It has no intrinsic value."
IceDane is offline   Reply With Quote
Old 05-05-2009, 07:15 AM   #7
C++ Witch
 
laserlight's Avatar
 
Join Date: Oct 2003
Location: Singapore
Posts: 10,352
Quote:
Originally Posted by IceDane
Alright, perhaps he did that. Why can't he post this here, in the hope of someone having information on this, to ask for an extra opinion?
Then he should have mentioned it in that other thread instead of cross posting all over the place.
__________________
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar

Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
laserlight is offline   Reply With Quote
Old 05-05-2009, 07:22 AM   #8
Woof, woof!
 
zacs7's Avatar
 
Join Date: Mar 2007
Location: Australia
Posts: 3,139
IMO it won't work everywhere, depending on how the "files" are stored.

For example with SSDs, again depending on implementation, if the device has wear levelling you might not even end up writing the blocks to where they were in the first place. And thus leaving the original data in the original block (potentially).

Also,
* Why the cast on malloc()
* sizeof(char) is always 1
* There's a few "dangerous" casts
* Where's the error checking? :\. i.e. the result of malloc()
__________________
"I.T. gets the chicky-babes" - M. Kelly
bakefile | vim

Last edited by zacs7; 05-05-2009 at 07:28 AM.
zacs7 is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
A development process Noir C Programming 30 10-28-2009 04:24 AM
Memory Address kevinawad C++ Programming 18 10-19-2008 10:27 AM
Post... maxorator C++ Programming 12 10-11-2005 08:39 AM
Dikumud maxorator C++ Programming 1 10-01-2005 06:39 AM
System drdroid C++ Programming 3 06-28-2002 10:12 PM


All times are GMT -6. The time now is 07:21 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22