对于文件加密,『不使用 AEAD』是否是一个好方案?

136 天前
 MFWT

这个问题困扰我有一段时间了

背景:想写个文件加密软件,作为练手项目,目前大致的想法是:

  1. 读取文件元数据(文件名,文件类型,自定义数据...)
  2. 生成 IV ,以及某个 Magic number
  3. 使用某种加密算法对上述数据加密
  4. 不停增加 nonce ,分一定长度的块(比如 64KB 一个块)/流式,对文件本体进行加密

目前备选的加密方式有:

写到这里就产生了一个问题:我应该对这个文件使用带有 AEAD 的加密算法,还是普通算法?

考虑到这么一个问题,我需要的侧重点是文件如果损坏,应该尽可能少地损坏。假设,文件中某个 bit 被翻转了,AEAD 算法会因为 MAC 校验不正确而拒绝解密,导致整块解密失败(换句话说,可能有连续的一个 64KB 块无法解密)

而如果使用非 AEAD 的流加密算法,比如单纯的 Chacha20 ,然后在加解密前后配个简单的校验和( CRC32 ,CityHash 什么的),可以在解密之后,如果发生校验错误,可以提示用户并强制输出,尽可能减少损失

问一下各位朋友,不知道这种想法是否正确,或者说还有更好的方案?

2203 次点击
所在节点    信息安全
20 条回复
SuperMild
136 天前
我也考虑过类似的问题,为了速度还是选择 AES ,然后用脚本记录校验和,实现了两个关键功能:检查文件是否损坏、备份到另一个硬盘。(参考我这个项目 https://github.com/ahui2016/local-buckets

后来,我又有另一个想法,就是不做加密,只做备份功能,加密交给 veracrypt (参考我另一个项目 https://github.com/ahui2016/wuliu

这两个项目都顺便加上了标签、备注之类的属性,方便管理文件。
SuperMild
136 天前
加密还有个问题,文件内容不可以搜索,有时甚至希望文件名也不暴露信息,那就连文件名都不可以搜索了,查找资料很不方便。交给 veracrypt 加密反而更方便。
MFWT
136 天前
@SuperMild 文件备份是真的,但是考虑到极端情况,『这是最后一份备份』了,那么相比较于丢失一段内容,还不如只有部分字节丢失,然后依靠可能有的上层纠错,或者可忽略的错误(比如视频文件,可能会马赛克一下而已)来使用文件
liuminghao233
136 天前
用户需求不明确, 怎么定义方案好坏
MFWT
136 天前
@SuperMild 这一点我考虑的是,在加密文件头部留下一些元数据,这样原文件怎么改名都可以
tool2dx
136 天前
早期 U 盘遇到过,现在很少遇到 bit 被翻转的。

我搜了一下,老外说现在 ssd 主控里,都有类似 winrar 5%恢复校验数据。( Each sector on every storage device has built in ECC data. )

读出来的文件,自动就被修正的。
MFWT
136 天前
@liuminghao233 速度是次要考虑因素(当然也越快越好),但是要求如果加密文件有损坏,解密过程应该尽可能不被中断,可以选择继续解密(即使对应输出内容已经不对)。可以顺带引出的就是不能选择 CFB 之类的有较大错误扩散加密方式
liuminghao233
136 天前
@MFWT 既然不关心数据完整性,aead 直接就排除了, 没必要再纠结这些
tool2dx
136 天前
@MFWT “但是要求如果加密文件有损坏,解密过程应该尽可能不被中断,可以选择继续解密”

那你应该加额外恢复卷的,我加过,挺简单的,不难。
tool2dx
136 天前
就我个人而言,还是偏向于用 AEAD ,自己 hash 都不用算,直接算法内置了。

主要没遇到过 bit 翻转情况,真遇到过,可能就会倾向于楼主的外置 hash 算法。
MFWT
136 天前
@tool2dx Bit 翻转可能少见,但是随机掉几个字节之类的也有碰到过
leonshaw
136 天前
最后不比 auth tag 不就行了。要关注的应该是错误会不会扩散,比如 GCM 是 stream cipher 所以不会扩散。
hxndg
136 天前
推荐 AEAD 就是为了加密并认证,我觉得文件 bit 翻转小概率事件,不值得考虑。如果你希望并存,看一下 stream aead ,google tink 提供的加密有这个。如果你就是为了不传播,找个 aes 就完了
jim9606
136 天前
你似乎没搞明白 AEAD 中的认证是用来干啥的。没有认证,一段随机生成的数据都可以被解密得到一段无意义的"明文",而且没有办法判断是正确还是密文损坏/密码错误。如果你在明文加密前加 hash,就是认证后加密,加密后加 hash 就是加密后认证,这两种都差于 AEAD 。
用不用 AEAD 并不影响部分损坏工况的后果。
你这个方案的问题是如果存储的 IV 损坏,所有 block 都不能正确解密,因为每个 block 都依赖正确的 IV 。
htfcuddles
136 天前
AEAD 用来防各种选择密文攻击的,如果是离线解密没有必要。减少错误扩散应该选流密码并且不依赖前一组明文的分组密码工作模式,比如 OFB
tywtyw2002
136 天前
楼主你可以看看 https://github.com/FiloSottile/age 的加密算法,还有 Cryptomator 的。

很早之前研究过,现在可能记得不大清楚了。大概是每个文件根据主密匙通过算法生成文件密匙。(文件的密钥是存在文件头部的,经过主密钥加密,这个每个文件的加密密钥都不同,只有主密钥才能解开文件密钥)。

文件分成 32kb 的 chunk 用 chacha20 也好,aes 也罢。用文件的密钥来加密 chunk ,每个 chunk 有个头部,头部包括这个 chunk 的 nonce 和 crc 。

这样的话只要文件的密钥不损坏,最多就是损失一个 chunk 了。
MFWT
136 天前
@tywtyw2002 我折腾过类似 SS 的加密代理,大致也是这样的思路,现在考虑的就是 Chunk 损失的问题。考虑到密文损坏一小部分都会导致一整个 chunk 不可读....当然这个问题更多的就是离线介质的可靠性问题了
MFWT
136 天前
@jim9606 看来我还是研究一下目前已有的实现比较好,毕竟练手的目的还是在于学习
e3c78a97e0f8
135 天前
你应该用 AEAD+冗余校正码。先 AEAD ,再冗余矫正。你想的那个方法安全漏洞太多了。
yinmin
135 天前
文件加密有 2 种,一种是用密码的,推荐:生成 64 字符的随机字符串,sha256(密码+随机字符串)做密钥 KEY 给 AES256 加密文件,随机字符串和加密后的文件合成一个文件。另一种是用证书的,推荐 ECC384 证书,先随机生成 256 位密钥 KEY 给 AES256 加密文件,然后 ECC384 公钥加密 KEY ,2 者合成一个文件。

推荐 AES-256-GCM 算法,可以保证数据的完整性。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1065471

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX