首页 > 技术文章 > 美国国防部机密文件销毁算法

Chaobs 2015-10-20 01:50 原文

  当我们在系统里“删除”了一个文件时,并不意味着这个文件就一定从磁盘上清除了,很多优秀的文件恢复软件都可以恢复被删除的文件,这在一定程度上就带来了隐私泄露的隐患。好在现在很多软件,比如360、电脑管家等等软件都集成了文件粉碎的实用功能。今天介绍一种以前被用于美国国防部的机密文件销毁算法,并附上实现的代码(C)。

  算法介绍:

    美国国防部DOD5220.22M文件销毁标准包括以下三步:

  1. 将文件先用0x00覆盖,再用0x01覆盖,如此重复三次;
  2. 将文件用一个随机值覆盖;
  3. 将文件名改为一个单字符文件名,最后删除之。

   算法可靠性验证:

     此算法虽然已经不再被美国国防部采用,但也足够应付一般的环境,主流文件恢复软件恢复的可能性还有待验证。

  实现:

  • v 0.2.0 修改(这是给不读源码的朋友准备的)

    1.修正了file_size()返回值的错误;

    2.wipe()函数改为block_wipe(),但是我不知道它是否真的能提高效率。

本人的部分博文已经转移至chaosxie.top,本博客将不再更新,希望您能继续支持我!

  

  1 /*
  2  *    File Destroyer v 0.2.0 文件安全销毁
  3  *
  4  *    Copyright (C) 2015 Chaobs
  5  *
  6  *    This program is free software: you can redistribute it and/or modify
  7  *    it under the terms of the GNU General Public License as published by
  8  *    the Free Software Foundation, either version 3 of the License, or
  9  *    (at your option) any later version.
 10  *
 11  *    This program is distributed in the hope that it will be useful,
 12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  *    GNU General Public License for more details.
 15  *
 16  *    You should have received a copy of the GNU General Public License
 17  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 18  *
 19  *    E-mail: chaobs@outlook.com
 20  *    Blog: www.cnblogs.com/chaobs
 21  *
 22  *    用法: file-destroyer [filename1] <filename2>...
 23  *
 24  *     算法介绍:
 25  *     基于美国国防部DOD5220.22M标准进行文件销毁,包括以下三步:
 26  *     (1)将文件先用0x00覆盖,再用0x01覆盖,如此重复三次;
 27  *     (2)将文件用一个随机值覆盖;
 28  *     (3)将文件名改为一个单字符文件名,最后删除之。
 29  *
 30  *     算法可靠性验证:
 31  *     此算法虽然已经不再被美国国防部采用,但也足够应付一般的环境,对于主流文件恢复软件恢复的可能性还有待验证。
 32  *
 33  * |-------------------------------------------------------------------------------------------|
 34  * |    v 0.2.0更新:                                                                           |
 35  * |    (1)将原有的wipe()改为block_wipe(),block_wipe()采用成块的写入,可以提高程序运行效率。         |
 36  * |                                                                                           |
 37  * |     v 0.1.0更新:                                                                          |
 38  * |    (1)修正了file_size()无返回值的问题(感谢网友冰尘醉);                                        |
 39  * |    (2)将file_zize()的调用移到了循环的外部。                                                  |
 40  * |-------------------------------------------------------------------------------------------|
 41  */
 42 
 43 #include <stdio.h>
 44 #include <stdlib.h>
 45 #include <time.h>
 46 
 47 
 48 void notice(int i, char *s);    /* print short notice */
 49 
 50 /*
 51  * v 0.2.0 的 blokc_wipe()一次写入一整块,保证了性能。
 52  * core function
 53  */
 54 void block_wipe(FILE *f, char c);
 55 
 56 long file_size(FILE *f);    /* get the size of a file */
 57 
 58 int require(int c, char *s[]);
 59 
 60 
 61 int main(int argc, char *argv[])
 62 {
 63     int i, j;
 64     
 65     FILE *f;
 66 
 67     notice(1, argv[0]);
 68 
 69     if (argc < 2) {
 70         /* too few arguments */
 71         notice(2, argv[0]);
 72         exit(0);
 73     }
 74 
 75     if (!require(argc, argv)) {
 76         fprintf(stderr, "Cancel Operating.\n");
 77         exit(0);    /* cancel */
 78     }
 79 
 80     srand(time(NULL));    /* randomize */
 81 
 82     for (i = 1; i < argc; ++i) {
 83         /* process each file */
 84 
 85         if ((f = fopen(argv[i], "r+b")) == NULL) {/* fail to open file */
 86             fprintf(stderr, "Error when open %s:\n", argv[i]);
 87             exit(0);
 88         }
 89 
 90         for (j = 0; j < 3; ++j) {
 91             /* DOD5220.22M Step 1 */
 92             /* v 0.2.0 新增*/
 93             block_wipe(f, 0x00);
 94             block_wipe(f, 0x01);
 95         }
 96 
 97         block_wipe(f, rand() % 256);    /* Step 2 */ 
 98         
 99         if (rename(argv[i], "C")) {
100             /* Step 3*/
101             fprintf(stderr, "Error when rename %s\n", argv[i]);
102             exit(0);
103             
104             /* XXX:文件名冲突的解决?可以考虑使用tmpnam()吗?*/
105         }
106 
107         remove("C"); /* XXX:如果是一个符号连接怎样保证删除的是真正的文件? */
108         fclose(f);
109     }
110 
111     printf("Done! Destroy %d files\n", argc - 1);
112 
113     return 0;
114 }
115 
116 
117 /* implementation */
118 
119 void notice(int i, char *s)
120 {
121     if (i == 1) {
122         printf("\nFile Destroyer Copyright (C) 2015 Chaobs\n");
123         printf("This program comes with ABSOLUTELY NO WARRANTY.\n");
124         printf("This is free software, and you are welcome to redistribute under certain conditions.\n\n");
125     } else {
126         fprintf(stderr, "Usage: %s [filename1] <filename2> ...\n", s);
127     }
128 }
129 
130 void block_wipe(FILE *f, char c)
131 {
132     long len = file_size(f);
133 
134     fwrite(&c, sizeof(char), len, f);    /* 覆盖,直接一次性写入 */
135 
136 }
137 
138 long file_size(FILE *f)
139 {
140     long len;
141     fseek(f, 0, SEEK_END);    /* jump to the and of file */
142     len = ftell(f);
143     fseek(f, 0, SEEK_SET);    /* restore */ 
144     return len;    /*感谢网友冰尘醉*/
145 }
146 
147 
148 int require(int c, char *s[])
149 {
150     int i;
151     char ch;
152     for (i = 1; i < c; ++i) {
153         /* FIXME: the comfirm function can make mistakes and
154          * it is not convenient even can't work in some cases.
155          */
156         printf("Do you want to destroy %s ?(y/n) ", s[i]);
157         ch = getchar();
158         getchar(); /* '\n' */
159         if (ch == 'n')
160             return 0;
161     }
162 
163     return 1;
164 }

  后记:

  这篇博文纯属因为我的一个朋友从图书馆里找到一本老书(书名《TURBO PASCAL高级编程技术与实用程序集锦》,学苑出版社,1994,董占山),上面记录了这个“美国国防部机密文件销毁算法”,我一时觉得好玩就把它用C语言写了下来。我上一次在就说过:

  This is free software, and you are welcome to redistribute it under certain conditions.

  这也是我在源码前面加了一端GPL申明的原因,希望不要把讨论的焦点从代码本身放到别的问题上。

推荐阅读