代码之家  ›  专栏  ›  技术社区  ›  Klathzazt

如何保证在运行时解密的文件被清除?

  •  3
  • Klathzazt  · 技术社区  · 17 年前

    使用C或C++,在我将文件解密到磁盘之后,如果应用程序崩溃或系统断电,不能正确地清除它,我怎么能保证它被删除?在Windows和Linux上使用C或C++?

    13 回复  |  直到 17 年前
        1
  •  7
  •   Bill the Lizard    17 年前

    不幸的是,没有100%万无一失的方法来确保在发生完全系统崩溃时删除文件。想想如果用户在文件在磁盘上时拔出插头会发生什么。再多的异常处理也不能保护您免受这种(最坏的)情况的影响。

    您可以做的最好的事情是,首先不要将解密的文件写入磁盘。如果文件以加密和解密的形式存在,那么这就是您的安全性的弱点。

    下一个最好的方法是使用Brian关于结构化异常处理的建议来确保临时文件得到清理。这不会保护你不受所有可能性的影响,但会有很大的帮助。

    任何

        2
  •  5
  •   housemaister    17 年前

    根本不要将解密后的文件写入磁盘。

    如果系统断电,文件仍在磁盘上,则可以访问磁盘,从而访问文件。

    例外情况是使用加密文件系统,但这超出了程序的控制范围。

        3
  •  4
  •   BatchyX    17 年前

    我不知道这在Windows上是否有效,但在Linux上,假设您只需要一个进程来访问解密的文件,您可以打开该文件,然后调用unlink()来删除该文件。只要进程保持打开状态,文件将继续存在,但当文件关闭或进程死亡时,文件将不再可访问。

        4
  •  4
  •   Brian R. Bondy    17 年前

    尽量完全避免:

    防止崩溃:结构化异常处理:

    __try and __except

    如果他们拔掉插头怎么办

    有一种方法可以防止这种情况。。。

    如果您在windows上,可以使用MoveFileEx和选项MOVEFILE\u DELAY\u直到\u重新启动,目标为NULL,以便在下次启动时删除该文件。这将防止计算机意外关闭未删除的文件。您还可以确保对此文件有一个独占打开的句柄(指定没有共享权限,例如file\u SHARE\u READ,并使用CreateFile打开它)。这样,就没有人能从中阅读了。

    所有这些都不是在磁盘上保存解密文件的借口,而是:

    • 还可以考虑通过\\\\的文件语法来编写大于Max路径的文件。这将确保windows资源管理器无法浏览该文件。

    • 您应该将文件设置为具有临时属性

    • 您应该将文件设置为具有隐藏属性

        5
  •  2
  •   Jonathan Leffler    17 年前

    在C(我也假设,在C++中),只要你的程序不崩溃,你可以登记一个 atexit() 处理程序来进行清理。避免使用 _exit() _Exit() 因为这些都绕过了 atexit() 处理程序。

    不过,正如其他人指出的,最好避免将解密后的数据写入磁盘。并且简单地使用 unlink()

        6
  •  1
  •   Johannes Schaub - litb    17 年前

    进程无法保护或监视自身。您唯一的可能性是启动第二个进程作为一种看门狗,它定期检查解密其他进程的运行状况。如果另一个进程崩溃,看门狗将注意到并删除文件本身。

    您可以使用hearth beats(定期轮询另一个进程以查看它是否仍处于活动状态)或使用从另一个进程本身发送的中断来实现这一点,如果它崩溃,这将触发超时。

    很明显,您需要一些锁定机制来防止切换到页面文件/交换分区。在Posix系统上,这可以由 m(un)lock* family of functions .

        7
  •  1
  •   baash05    17 年前

    当你从硬盘上删除文件时(不包括回收站),文件并没有真正消失。只删除指向该文件的指针。

    有没有看过那些间谍电影,他们覆盖硬盘6、8、24次,这就是为什么他们知道硬盘是干净的。。他们这样做是有原因的。 我会尽一切努力不存储文件的解密数据。或者,如果必须的话,将其设置为少量数据。甚至,不连贯的数据。

    如果你必须这样做,那么他们会尽力保护你。。但是,没有任何东西可以防止停电。

    祝你好运。

        8
  •  1
  •   Loki Astari    17 年前

    它是BSD UNIX的一部分,不确定它是否是标准的。
    但它会创建一个临时文件并自动取消链接,以便在关闭时将其删除。

    写入文件系统(即使是暂时写入)是不安全的。
    只有在你真的必须这样做的时候才这样做。


    我自己从来没有用过,所以没有推荐,但谷歌很快找到了一些。

        9
  •  1
  •   Max Lybbert    16 年前

    在C++中,应该使用 RAII 策略:

    class Clean_Up_File {
        std::string filename_;
        public Clean_Up_File(std::string filename) { ... } //open/create file
        public ~Clean_Up_File() { ... } //delete file
    }
    
    int main()
    {
        Clean_Up_File file_will_be_deleted_on_program_exit("my_file.txt");
    }
    

    RAII帮助实现了大量清理工作的自动化。您只需在堆栈上创建一个对象,并让该对象在其生命周期结束时进行清理(在对象超出范围时将调用的析构函数中)。 ScopeGuard 甚至让它变得更容易。

    但是,正如其他人所提到的,这只在“正常”情况下有效。如果用户拔下电脑插头,则无法保证文件将被删除。还可以取消删除该文件(即使在UNIX上也可以“ grep the harddrive ").


    此外,正如注释中指出的,在某些情况下,对象不会超出范围(例如 std::exit(int) 函数退出程序而不离开当前作用域),因此RAII在这些情况下不起作用。就我个人而言,我从不打电话 相反,我要么抛出异常(它将释放堆栈和调用析构函数;我认为这是一个异常出口),或者返回一个错误代码。 main() (这将调用析构函数,我也认为这是“异常退出”)。IIRC,发送一份 SIGKILL 也不调用析构函数,并且 不能被抓住,所以你也不走运。

        10
  •  0
  •   Tom Ritter    17 年前

    这是一个棘手的话题。通常,如果可以避免,您不希望将解密文件写入磁盘。但将它们保存在内存中并不总是保证它们不会作为页面文件的一部分写入磁盘或以其他方式写入磁盘。

    我很久以前读过有关这方面的文章,我记得Windows和Linux之间有一些区别,可以保证内存页不会写入磁盘,也不能写入磁盘;但我记不清了。

    如果你想做你的尽职调查,你可以查一下这个话题并阅读它。这一切都取决于你的威胁模型和你愿意防范什么。毕竟,你可以用压缩空气冷却RAM,然后从中取出加密密钥(实际上是在新的Christian Slater间谍秀上,我自己最大的敌人——我认为这是媒体对尖端、准确的计算机安全技术的最佳利用)

        11
  •  0
  •   n-alexander    17 年前

    更好的是,即使整个系统崩溃,该文件也会被删除,因为基本上只要您取消链接,它就会被删除。

    当然,这些数据不会从磁盘上被物理删除,因此它仍然可以被黑客攻击。

        12
  •  0
  •   David Thornley    17 年前

    请记住,计算机可以随时关闭电源。然后,你不喜欢的人可以用一张LinuxLiveCD启动,在不改变任何东西的情况下,以所需的任何详细程度检查你的磁盘。没有一个将明文写入磁盘的系统能够安全地抵御此类攻击,而且这样做并不困难。

    因此,如果需要安全性,需要确保没有明文被写入,这也意味着不能将明文写入交换空间或等效空间。了解如何在您为之编写的所有平台上将内存标记为不可下载。确保解密密钥和类似的内容与明文的处理方式相同:在任何情况下都不会写入磁盘,并保存在不可读取的内存中。

        13
  •  0
  •   Klathzazt    17 年前

    我将要实现的方法是对解密进行流式处理,这样内存中唯一的部分就是在使用数据时在读取过程中解密的部分。以下是管道示意图:

    这将是一个流式实现,因此内存中唯一的数据是我在任何给定点在应用程序中使用的数据。这使得一些事情变得棘手-考虑到许多传统的文件技巧不再可用,但由于实现将基于流,我仍然能够找到文件的不同点,这些点将被转换为加密流,在不同的部分解密。

    此实现不需要对文件或内存进行解密,并且与其他流消费者和提供者(fstream)兼容。

    这是我的“计划”。我以前没有在fstream上做过这种类型的工作,一旦我准备好做这方面的工作,我可能会发布一个问题。

    谢谢所有其他的答案-这是非常有益的。