Lemoncchi / ac-web

本仓库为密码学应用实践课程的课程项目「中传放心传」的作业仓库
MIT License
0 stars 0 forks source link

观后感 #8

Open c4pr1c3 opened 1 year ago

c4pr1c3 commented 1 year ago

Pros

Cons

  1. 使用webstorage进行储存 意味着用户如果换一个浏览器登录系统或者不小心清除浏览器所有缓存记录,就丢失 私钥 了。在真实世界里,任何依赖于密码、密钥的安全体系,在设计时均需要考虑 忘记口令导出备份私钥 之类的真实用户需求。相比较于用于 身份验证 的口令,我们可以通过其他因素验证了用户身份之后,直接给重置一个新口令覆盖掉旧的被用户忘记的口令即可。但是如果是基于现代密码学的密钥保密机制加密出来的密文,丢失了私钥的密文数据,神仙难救。
  2. 只在下载过程中提供私钥到服务器,不保存到服务器,并不会造成安全问题 这是只看到了 终端持久化存储安全风险 ,而忽视了 通信链路风险运行时内存与CPU缓存信息泄露风险 。注意,安全风险 是一个概率问题。我们可以评估风险的高低,但不能完全否认风险的客观存在性。
  3. 使用其他客户端数据存储技术,依然会面临新问题:跨浏览器只是最基础的“跨设备”需求,继续往前,就是真正的“跨物理设备”了。网盘这个应用的最大价值恰恰就是天生具有 跨物理设备 的数据传输能力,而你们如果强依赖于客户端数据存储技术来保存用户私钥,那么相当于自废武功了。

Answers

李明萱

陈慕樵

王之饶

Lemoncchi commented 1 year ago

我来稍微 辩解 一下(下面的主要是在我实现的框架下进行的回复,后面我出去旅游之后听他们说他们对我的框架有一些大改)

我们这个项目一共有两种实现,一种是我实现的:比较偏向于 私有云盘 的实现,同时优先考虑性能和实际,然后再考虑安全性;

另外一种是另外两位同学从 dev 分支 fork 实现的:比较偏向于 共享文件广场 的实现,同时优先考虑安全性

由于王之饶同学在视频中之说明了他们后面实现的框架和功能(newcrypto 分支),没有提到我实现的框架(dev 分支),所以我觉得我也应该来说明一下我实现的框架和功能

我的框架

每一个用户在注册时,都会生成一个唯一的 文件加解密对称密钥,用于加密 该用户 上传的所有文件,此密钥被 服务器的公钥 加密后存储在数据库中,参见 代码

服务器需要严格保管自己的私钥

但是我在出去旅游前,将所有的加解密代码只是留出了接口(直接将明文的二进制赋值给了密文),还有几行代码没有实现,这些地方全部都用 TODO 标出了,这些是打算留给其他两位同学补全就行了,例如代码

但是两位同学好像并没有直接在我的基础上面补全我的框架,而是重新修改实现了和我原本设计不同的框架(例如实现了文件共享广场)

共享文件广场

dev 分支是有我来开发的,我走后其他两位同学在 dev 分支上完善实现了其他功能

其中我在 dev 分支中并没有采用 共享文件广场 的模式,每一个用户 只能看见与操纵自己上传的文件 (参见 代码文件广场功能 由王之饶同学在我旅游不在的时候重新开发的(我们认为开发两种不同的实现比较好,但是王之饶同学好像忘记了在 README 或者视频中提到我的框架了)

文件秒传

一开始我们就考虑到了 文件秒传 的问题,同时考虑到 同一个用户上传多个相同名称的文件的问题(比如用户 A 拥有两个 1.txt,但是其中的内容都不同),所以我们采用了使用 文件明文的 sha256 值的16进制字符串 作为服务器上文件的名称,参见 代码

但是,如老师所说,我们没有考虑到多个用户上传相同内容文件的问题:这会导致文件明文哈希值相同——>文件名在服务器中的存储名相同——>文件被覆盖

同时,由于每一个用户的 文件加密密钥 都不同,这会导致另外一个用户 B 在文件被覆盖后,无法正确解密自己的文件

下面在 用户不能上传同名文件,存在文件覆盖风险 中提到了解决方案

文件下载过期策略

这里我在设计框架时也考虑过老师所说的使用签名的方式

仅数据库方式的实现和使用密码学方法的实现有什么优缺点差异?

最开始我也想使用老师的方法,但是我能想到的使用签名的方式的优点是:可以在不使用数据库的情况下实现文件下载过期策略,这样可以避免 数据库所在的服务器被攻破 后,攻击者可以随意下载文件的问题。

但是我们工程由于目前还比较小,目前数据库与 web 服务器都在同一台机器上。所以就直接采用了数据库的方式

另外,何必 2 个字段用来判断文件下载次数是否超限?一个字段是不是就足够了?

代码 老师说得确实有道理,只不过我在想多留一些冗余信息可能也并没有坏处,以便于后期的扩展(比如新增用户查询自己当初设置的下载次数 & 当前已经使用的下载次数)

规模和性能

即使是 共享文件广场 应用,如果每一个文件都使用系统中所有已注册用户的公钥去加密生成一个专属的文件解密密钥,这个工作量和对应管理运营成本随着注册用户数量级的增长是否太不可控了?

在我的非 共享文件广场 实现中(dev 分支),也比较考虑性能。所以每一个用户的文件是使用自己的 对称密钥 加密的

关于 webstorage

这个我们之前也曾经讨论了很久,我认为如果要实现跨浏览器,用户密钥找回的话,那么最后的生杀大权还是掌控在服务器上的(服务器管理员是有能力解密查看每一个用户的明文的),这是我在 dev 分支的实现就是这样的

但是王之饶同学认为每个用户要将私钥存储在用户本地,不允许本人以外的任何人有能力查看

我认为两种实现都有实际的需求应用场景,但是如老师所说,还应该加上用户端 导出密钥 的功能,避免 用户如果换一个浏览器登录系统或者不小心清除浏览器所有缓存记录,就丢失私钥了

用户不能上传同名文件,存在文件覆盖风险

就像我之前所说的,这个问题我在最开始设计时就考虑到这个问题的,所以文件名是 存储在数据库中的

同时也可以同一个用户上传相同文件名且相同内容的文件

但是,如果用户 A 和用户 B 上传的文件的明文内容相同时,会出现先上传的文件被后上传的文件覆盖后,用户 A 无法正确解密自己的文件的问题

刚才已经通过将服务器端存储的文件名为 hash(二进制明文内容+当前用户ID) 修复了该 bug,从而实现了同一个用户上传相同明文文件时的秒传,参见 commit

作为生产环境版本软件运行组成部分的 nginx 配置文件 没有上传到 git 仓库?

加解密 & https 模块是分配给另外两位同学实现的(这里是王之饶同学),他好像确实忘记了

展示 匿名用户禁止上传文件

这里王之饶同学的展示方法确实有些不妥,应该展示 这行代码

我在写单元测试时,也考虑到了老师所说的问题,直接测试了许多后台接口

例如 测试代码:在 用户 B 登录的情况下,尝试直接通过 API 接口删除 用户 A 的文件,应该返回 403 错误