V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MFWT
V2EX  ›  信息安全

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

  •  
  •   MFWT · 2024-08-16 12:07:54 +08:00 · 2613 次点击
    这是一个创建于 381 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    目前备选的加密方式有:

    • AES-256-GCM
    • Chacha20-Poly1305
    • AES-256-CTR
    • Chacha20

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

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

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

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

    20 条回复    2024-08-17 15:02:13 +08:00
    SuperMild
        1
    SuperMild  
       2024-08-16 12:20:11 +08:00
    我也考虑过类似的问题,为了速度还是选择 AES ,然后用脚本记录校验和,实现了两个关键功能:检查文件是否损坏、备份到另一个硬盘。(参考我这个项目 https://github.com/ahui2016/local-buckets

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

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

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

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

    那你应该加额外恢复卷的,我加过,挺简单的,不难。
    tool2dx
        10
    tool2dx  
       2024-08-16 12:51:35 +08:00
    就我个人而言,还是偏向于用 AEAD ,自己 hash 都不用算,直接算法内置了。

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

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

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

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

    推荐 AES-256-GCM 算法,可以保证数据的完整性。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5876 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 01:55 · PVG 09:55 · LAX 18:55 · JFK 21:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.