【问题标题】:Rewrite a file in-place with Python使用 Python 就地重写文件
【发布时间】:2020-03-17 22:09:06
【问题描述】:

它可能取决于每个操作系统,也取决于硬件,但是 Python 中有没有办法要求对文件的写操作“就地”发生,即 在同一个地方 原始文件的,即如果可能在磁盘上的相同扇区上?

示例:假设sensitivedata.raw,必须加密一个 4KB 文件:

with open('sensitivedata.raw', 'r+') as f:  # read write mode
    s = f.read()
    cipher = encryption_function(s)  # same exact length as input s
    f.seek(0)
    f.write(cipher)  # how to ask this write operation to overwrite the original bytes?

示例2:用相同大小的空字节内容替换文件,以避免使用取消删除工具来恢复它(当然,要正确执行此操作,我们需要多次遍历,使用随机数据而不仅仅是空字节,但这里只是提供一个想法)

with open('sensitivedata.raw', 'r+') as f:
    s = f.read()
    f.seek(0)
    f.write(len(s) * '\x00')  # totally inefficient but just to get the idea
os.remove('sensitivedata.raw')

PS:如果真的很大程度上取决于操作系统,我主要对 Windows 案例感兴趣


附带问题:如果在 SSD 的情况下不可能,这是否意味着如果您在生活中一次在 SSD 上以明文形式写入敏感数据(例如:明文密码,加密私钥或其他任何东西等),那么没有办法确定这些数据真的被删除了吗?即唯一的解决方案是 100% 擦除磁盘并用随机字节填充它许多遍?对吗?

【问题讨论】:

  • 大多数文件系统将文件实现为字节流,因此您只能通过将n 字节替换为n 字节来就地修改文件。如果不重写数据,您将无法扩展或收缩文件。
  • @chepner 确实如此,出于这个原因,在我的 2 个示例中,我将 n 字节替换为 n 字节。
  • 小旁注:加密数据应该让它更大一点。即使不需要IV(大多数好的方案都使用IV),并且密钥始终由用户输入提供,从不存储,如果您不存储一些额外数据(HMAC,幻数,无论如何)使用数据,您无法以编程方式知道解密是否正确。您不希望用户使用"password" 加密,然后不小心在解密端丢了一个字母(例如,输入"pasword"),并最终得到无法恢复的完整垃圾,除非他们猜到错字和重新加密,然后正确解密。

标签: python python-3.x file io


【解决方案1】:

这是一个不可能强加的要求。虽然在大多数旋转磁盘驱动器上,这会自动发生(没有理由将新数据写入其他地方,因为它可以直接覆盖现有数据),SSD不能这样做(当他们声称这样做,他们就是在对操作系统撒谎)。

SSD 不能重写块;他们只能擦除一个块,或写入一个空块。 “重写”的实现是写入一个新块(如果没有足够的新数据,则从原始块读取以填充该块),然后(最终,因为它相对昂贵)擦除旧块以使它可用于将来的写入。

更新解决附带问题:唯一真正安全的解决方案是让您的驱动器穿过木片机,然后用磨石碾碎残骸。 :-) 实际上,在大多数情况下,SSD 上的漏洞窗口应该相对较短;擦除扇区的成本很高,因此即使是不支持TRIM 的 SSD 通常也会在后台执行此操作,以确保未来的(廉价)写入操作不会被(昂贵的)擦除操作所阻碍。仔细想想,这并不是那么糟糕。当然,数据在逻辑擦除后的一段时间内仍可见。但是它在您删除它之前之前是可见的一段时间,所以这一切所做的只是将漏洞窗口延长(秒,分钟,小时,天,取决于驱动器);错误在于首先将敏感数据存储到永久存储中;即使使用极端的(木片机+磨石)解决方案,其他人也可能在您考虑加密/销毁数据之前偷偷进入并复制数据。

【讨论】:

  • 感谢您的回答。 SSD真的没有办法获取块的“位置”并要求稍后重写吗?
  • 这将由磁盘驱动程序处理;它通常不是您可以从 Python 访问的东西。
  • @Basj:不可能。逻辑扇区是您可以访问的所有内容,并且在这些重写期间会更新从逻辑扇区到物理扇区的映射。您能做的最好的事情就是完成您的重写,然后使用一些外部实用程序在驱动器本身上立即触发TRIM(命令“返回并实际擦除您现在放弃的所有块”)。即使那样,也不能完全保证。从历史上看,一些 SSD 未能真正实现按需 TRIM(他们只是说“是的,我已经完成了”,并在他们喜欢的时候执行实际工作)。
  • @ShadowRanger 很高兴知道。我在最后编辑了问题以添加链接的附带问题,您的最后一条评论似乎回答它是正确的。你确认吗?如果是这样,那就太可怕了!
  • @Basj:是的,这基本上是正确的。在实践中,随着时间的推移,人们假设驱动器将被动清除逻辑上空但物理写入的扇区,这样下次需要它们时就不会争先恐后地清除它们(正如我所说,这是最昂贵的东西之一驱动器可以;相比之下,读取和写入便宜)。但是,如果您不能相信TRIM 会得到兑现,就没有办法保证它。您总是可以购买以纪念它而闻名的驱动器,但是对于您出售/分发给他人的软件,您会被他们运行的任何垃圾所困扰。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-10
  • 2011-04-22
  • 1970-01-01
  • 2016-02-15
  • 2011-03-01
  • 2021-06-09
  • 1970-01-01
相关资源
最近更新 更多