Thread: Secure File Deletion

  1. #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;
    }

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    I didn't look too hard, but it seems okay to me.

    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.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    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

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  4. #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.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Grr... I already told you elsewhere: go and investigate Eraser.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    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."

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    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.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    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()
    Last edited by zacs7; 05-05-2009 at 07:28 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. System
    By drdroid in forum C++ Programming
    Replies: 3
    Last Post: 06-28-2002, 10:12 PM