В проекте, который я делаю, я хочу предоставить пользователям возможность «безопасного» удаления файла — например, перезаписать его случайными битами или нулями. Есть ли простой способ сделать это в С#.NET? И насколько это было бы эффективно?
Безопасное удаление файла в C#.NET
Ответы (5)
Вы можете вызвать sysinternals SDelete, чтобы сделать это за вас. При этом используется API дефрагментации для обработки всех этих сложных пограничных случаев.
Используя API дефрагментации, SDelete может точно определить, какие кластеры на диске заняты данными, принадлежащими сжатым, разреженным и зашифрованным файлам.
Если вы хотите переупаковать эту логику в более удобную форму, API описан здесь.
Вы не можете безопасно удалить файл в журналируемой файловой системе. Единственная система без журналирования, которая все еще активно используется, — это fat32. В любой другой системе единственным способом безопасного удаления является уничтожение всего жесткого диска.
ИЗМЕНИТЬ
Причина, по которой безопасное удаление не работает, заключается в том, что данные, используемые для перезаписи файла, могут храниться не в том же месте, что и перезаписываемые данные.
Кажется, Microsoft предоставляет инструмент безопасного удаления, но, похоже, его нельзя использовать в качестве замены.
Единственный хороший способ предотвратить восстановление удаленного файла, кроме уничтожения диска, — это зашифровать файл перед его записью на диск.
Это вообще небезопасно. Вместо этого вы можете рассмотреть альтернативные решения, такие как шифрование.
Одним из решений было бы зашифровать содержимое файла данных. Каждый раз при обновлении файла будет использоваться новый ключ. Если вы хотите «надежно удалить» данные, просто «потеряйте» ключ шифрования и удалите файл. Физически файл по-прежнему будет находиться на диске, но без ключа шифрования восстановление будет невозможно.
Вот более подробное объяснение того, почему "безопасная" перезапись файлов небезопасна:
Без инструмента низкого уровня (вне среды выполнения .net) у вас нет доступа к расположению на физическом диске. Возьмите файловый поток на NTFS, когда вы «открываете файл для записи», у вас нет гарантии, что «обновленная» копия (в данном случае случайная версия 101010) будет храниться в том же месте (таким образом перезаписывая исходный файл). На самом деле чаще всего происходит вот что:
1) Файл x.dat хранится, начиная с кластера 8493489 2) Вы открываете файл x.dat для записи. То, что возвращает вам ОС, — это просто указатель на файловый поток, абстрагированный не только ОС, но и базовой файловой системой и драйверами устройств (например, аппаратным RAID), а иногда и самим физическим диском (SSD). Вы обновляете содержимое файла случайными 1 и 0 и закрываете файловый поток.
3) ОС, вероятно, может (и, вероятно, будет) записать новый файл в другой кластер (скажем, кластер 4384939). Затем он просто обновит MFT, указав, что файл x теперь хранится по адресу 4384939.
Для конечного пользователя это выглядит так, как будто существует только одна копия файла, и теперь в ней есть случайные данные, однако исходные данные все еще существуют на диске.
Вместо этого вам следует подумать о шифровании содержимого файла с помощью другого ключа при каждом сохранении файла. Когда пользователь хочет, чтобы файл был «удален», удалите ключ и файл. Физический файл может остаться, но без ключа шифрования восстановление будет невозможно.
Я бы сначала попытался просто открыть файл и перезаписать его содержимое, как обычно. Довольно тривиально на C#, я даже не буду писать. Однако я не знаю, насколько это будет безопасно. Во-первых, я совершенно уверен, что это не будет работать на флэш-накопителях и твердотельных накопителях, которые используют сложные алгоритмы для обеспечения выравнивания износа. Я не знаю, что там сработает, возможно, это нужно было бы сделать на уровне драйвера, возможно, это было бы вообще невозможно. На обычных дисках я просто не знаю, что будет делать Windows. Возможно, он сохранил бы и старые данные.