Open c4pr1c3 opened 1 year ago
我来稍微 辩解 一下(下面的主要是在我实现的框架下进行的回复,后面我出去旅游之后听他们说他们对我的框架有一些大改)
我们这个项目一共有两种实现,一种是我实现的:比较偏向于 私有云盘
的实现,同时优先考虑性能和实际,然后再考虑安全性;
另外一种是另外两位同学从 dev
分支 fork 实现的:比较偏向于 共享文件广场
的实现,同时优先考虑安全性
由于王之饶同学在视频中之说明了他们后面实现的框架和功能(newcrypto
分支),没有提到我实现的框架(dev
分支),所以我觉得我也应该来说明一下我实现的框架和功能
每一个用户在注册时,都会生成一个唯一的 文件加解密对称密钥
,用于加密 该用户 上传的所有文件,此密钥被 服务器的公钥
加密后存储在数据库中,参见 代码
服务器需要严格保管自己的私钥
但是我在出去旅游前,将所有的加解密代码只是留出了接口(直接将明文的二进制赋值给了密文),还有几行代码没有实现,这些地方全部都用
TODO
标出了,这些是打算留给其他两位同学补全就行了,例如代码但是两位同学好像并没有直接在我的基础上面补全我的框架,而是重新修改实现了和我原本设计不同的框架(例如实现了文件共享广场)
dev
分支是有我来开发的,我走后其他两位同学在 dev
分支上完善实现了其他功能
其中我在 dev
分支中并没有采用 共享文件广场
的模式,每一个用户 只能看见与操纵自己上传的文件 (参见 代码)文件广场功能
由王之饶同学在我旅游不在的时候重新开发的(我们认为开发两种不同的实现比较好,但是王之饶同学好像忘记了在 README
或者视频中提到我的框架了)
一开始我们就考虑到了 文件秒传
的问题,同时考虑到 同一个用户上传多个相同名称的文件的问题(比如用户 A 拥有两个 1.txt
,但是其中的内容都不同),所以我们采用了使用 文件明文的 sha256 值的16进制字符串
作为服务器上文件的名称,参见 代码
但是,如老师所说,我们没有考虑到多个用户上传相同内容文件的问题:这会导致文件明文哈希值相同——>文件名在服务器中的存储名相同——>文件被覆盖
同时,由于每一个用户的 文件加密密钥 都不同,这会导致另外一个用户 B 在文件被覆盖后,无法正确解密自己的文件
下面在 用户不能上传同名文件,存在文件覆盖风险
中提到了解决方案
这里我在设计框架时也考虑过老师所说的使用签名的方式
仅数据库方式的实现和使用密码学方法的实现有什么优缺点差异?
最开始我也想使用老师的方法,但是我能想到的使用签名的方式的优点是:可以在不使用数据库的情况下实现文件下载过期策略,这样可以避免 数据库所在的服务器被攻破 后,攻击者可以随意下载文件的问题。
但是我们工程由于目前还比较小,目前数据库与 web 服务器都在同一台机器上。所以就直接采用了数据库的方式
另外,何必 2 个字段用来判断文件下载次数是否超限?一个字段是不是就足够了?
代码 老师说得确实有道理,只不过我在想多留一些冗余信息可能也并没有坏处,以便于后期的扩展(比如新增用户查询自己当初设置的下载次数 & 当前已经使用的下载次数)
即使是
共享文件广场
应用,如果每一个文件都使用系统中所有已注册用户的公钥去加密生成一个专属的文件解密密钥,这个工作量和对应管理运营成本随着注册用户数量级的增长是否太不可控了?
在我的非 共享文件广场
实现中(dev 分支),也比较考虑性能。所以每一个用户的文件是使用自己的 对称密钥
加密的
这个我们之前也曾经讨论了很久,我认为如果要实现跨浏览器,用户密钥找回的话,那么最后的生杀大权还是掌控在服务器上的(服务器管理员是有能力解密查看每一个用户的明文的),这是我在 dev
分支的实现就是这样的
但是王之饶同学认为每个用户要将私钥存储在用户本地,不允许本人以外的任何人有能力查看
我认为两种实现都有实际的需求应用场景,但是如老师所说,还应该加上用户端 导出密钥
的功能,避免 用户如果换一个浏览器登录系统或者不小心清除浏览器所有缓存记录,就丢失私钥了
就像我之前所说的,这个问题我在最开始设计时就考虑到这个问题的,所以文件名是 存储在数据库中的
同时也可以同一个用户上传相同文件名且相同内容的文件
但是,如果用户 A 和用户 B 上传的文件的明文内容相同时,会出现先上传的文件被后上传的文件覆盖后,用户 A 无法正确解密自己的文件的问题
刚才已经通过将服务器端存储的文件名为 hash(二进制明文内容+当前用户ID)
修复了该 bug,从而实现了同一个用户上传相同明文文件时的秒传,参见 commit
加解密 & https 模块是分配给另外两位同学实现的(这里是王之饶同学),他好像确实忘记了
匿名用户禁止上传文件
这里王之饶同学的展示方法确实有些不妥,应该展示 这行代码
我在写单元测试时,也考虑到了老师所说的问题,直接测试了许多后台接口
例如 测试代码:在 用户 B
登录的情况下,尝试直接通过 API
接口删除 用户 A
的文件,应该返回 403
错误
Pros
Git
管理整个小学期的实践过程和结果,可以看到每个同学都有使用Git
的工作记录,好评。Cons
如果直接 Fork 上游仓库 代码就对我的批改工作更友好了。如果 fork 上游仓库代码的话,就可以更方便我批改时查阅你们的具体变更了,比如 这个小组的代码变更情况一目了然 。保留这一段原始评价,在审查你们的代码仓库的时候发现了通过 PR 方式可以看到你们对上游仓库的变更 。视频版报告时长超时“严重”:
视频时长限制在 10 分钟以内
。在网盘时代早期,也有所谓「公共分享文件」功能,所有人都可以看到一些「面向所有人的分享文件」,类似你们目前实现(实际上这是你们基于的基础代码设计者的设计与实现方式)的这种
共享文件广场
模式。但这种模式目前在国内肯定是被监管叫停、明令禁止的,很容易被用来传播黄赌毒与反动内容,网盘运营商无法承担政策违规风险。「共享文件广场」这个功能本身属于真实世界的 禁区 功能,因此, 你们的实践成果最大的问题 就是: 偏题 。你们没有按照任务要求去实现网盘
,而是做了一个共享文件广场
。从本次大作业的总体需求来思考:既然整个网盘的核心特色就是『加密无处不在』,那么
文件秒传
这个功能实际上是一个不该去实现的功能(所以我们作业里的要求也是可选
)。服务端没有文件所有者的私钥,无法解密文件;同一个文件,多次执行加密操作得到的密文一定是不同的。因此,如果想要实现秒传,就只剩下在数据库里存储明文文件的散列值这一条路,这样后续才能通过在客户端计算待上传文件哈希值后在服务器端检索该哈希值实现「文件秒传」。但这样做的话,相当于还是在踩坑「侵犯用户隐私」:原来服务器上已经有人上传过这个文件了。另外,不必再重复上传
不等于不允许上传
。换句话来说,用户A拥有文件a,用户B拥有文件b,文件a的内容和文件b的内容完全一样。如果用户A删除了文件a,那么用户B的文件b也无法访问了吗?当然,如果是用户A自己网盘里已有重复文件,那么不允许他往自己网盘里重复上传还有一点道理。你们的
文件下载过期策略
的设计没有用到 密码学理论与技术 ,你们可以想想为什么我要在任务描述里提示【 数字签名 消息认证码 Hash Extension Length Attack Hash算法与HMAC算法的区别与联系 】
?仅数据库方式的实现和使用密码学方法的实现有什么优缺点差异?另外,何必 2 个字段用来判断文件下载次数是否超限?一个字段是不是就足够了?即使是
共享文件广场
应用,如果每一个文件都使用系统中所有已注册用户的公钥去加密生成一个专属的文件解密密钥,这个工作量和对应管理运营成本随着注册用户数量级的增长是否太不可控了?我们虽然是布置了一个“作业”让你们去完成,但是既然我们是小学期的综合实践,那么我们的研发应该更多地从生产实践视角去设计,而不能仅仅停留在功能验证。 规模和性能 的可伸缩性成本评估是我们在小学期综合实践中非常难得的一次实践成长机会。关于
webstorage
方式存储用户私钥的弊端分析我就直接照搬我在畅课平台上的回复如下:使用webstorage进行储存
意味着用户如果换一个浏览器登录系统或者不小心清除浏览器所有缓存记录,就丢失私钥
了。在真实世界里,任何依赖于密码、密钥的安全体系,在设计时均需要考虑忘记口令
和导出备份私钥
之类的真实用户需求。相比较于用于身份验证
的口令,我们可以通过其他因素验证了用户身份之后,直接给重置一个新口令覆盖掉旧的被用户忘记的口令即可。但是如果是基于现代密码学的密钥保密机制加密出来的密文,丢失了私钥的密文数据,神仙难救。只在下载过程中提供私钥到服务器,不保存到服务器,并不会造成安全问题
这是只看到了终端持久化存储安全风险
,而忽视了通信链路风险
和运行时内存与CPU缓存信息泄露风险
。注意,安全风险
是一个概率问题。我们可以评估风险的高低,但不能完全否认风险的客观存在性。跨物理设备
的数据传输能力,而你们如果强依赖于客户端数据存储技术来保存用户私钥,那么相当于自废武功了。匿名用户禁止上传文件
时存在一个认知谬误:看不到上传页面,不代表匿名用户就无法上传文件。在现实世界中,很多开发者也抱有类似的想法:我把关键字段、关键操作页面通过前端代码隐藏起来了,用户看不到了,就无法访问对应数据和功能了。记住,网安金科玉律: 永远不要相信来自于用户的一切输入数据 。攻击者会使用浏览器开发者工具、会使用burpsuite
等流量分析与调试工具发现隐藏的 HTML 表单元素、被注释掉的前端代码、甚至是根据已有功能的黑盒分析盲猜和推断隐蔽接口调用方式。此时,服务端(后端)验证才是守住安全底线的王道。Answers
中间证书颁发机构
里没有添加签发网站所用 SSL 证书的中级 CA 证书为信任。推荐阅读 SE 上这个帖子 以及这篇帖子的镜像帖子 详细了解服务器用证书
和CA 用证书
两者之间的差异。不应使用根CA证书直接签发网站证书,而是使用中间CA证书来签发网站证书。在实际生产实践中,根CA证书通常都是离线保存的,中间CA证书可以在线联网保存。具体三级CA证书签发方法可以参考我的 c4pr1c3/ac-demo 。李明萱
outdated
内容也舍不得删除。对于交作业来说,我可以理解,并表示感同身受。但是如果是以后的生产实践、科研项目,要有紧扣主题
和讲重点
的意识。该删除的无关内容,坚决删除。不要苦劳,要功劳。nginx 配置文件
没有上传到 git 仓库?陈慕樵
symmetric_generate()
函数定义和相关调用代码定义来看,你的改动是有机会合并到dev
分支的,这里可能是存在一些对于代码实现风格偏好的分歧导致的内部沟通问题,并非不可调和的代码实现方案差异。你们可能还是更需要按照功能模块进行任务分工,避免同一个功能模块多人同时实现。王之饶
使用 nginx 反代之后访问分享链接 404 ,但是使用本地代码直接访问时 200
的问题,根据你的个人总结技术报告里的 nginx 配置文件代码片段,我推测可能需要修改proxy_pass http://localhost:5001;
-->proxy_pass http://localhost:5001/;
。除此之外,你可能还需要增加一条 Nginx 配置指令proxy_set_header X-Forwarded-Prefix /;
到location
指令配置代码块里。