染卷不卷'blog

12年站长,AI实践中。互联网 IT行业,工作见闻、技术教程全分享。

程序源码 / 软件应用

自建一个”零知识”私人加密云盘LitAOSS:加密存储,前端解密

本篇目录

写在前面

把文件放到任何一家网盘服务商,本质上都是把钥匙和箱子一起交给对方——服务商在服务端持有解密能力,能看你存了什么、叫什么名字。对个人自用场景来说,我更想要的是一个”即使服务器被完全攻破,攻击者也拿不到我文件“的系统方案,而且最好无需客户端APP 直接网页访问即可。

  • 零知识:服务端不接触明文、不接触密钥,连文件名都是密文
  • 浏览器端加密:AES-256-GCM + AES-KW + PBKDF2(500k),密钥层级 + 域分离设计
  • 零持久化:解锁材料只在页面内存,刷新即锁定
  • MFA + 删除/恢复二次验证,软删除 + 最小化 OSS 权限
  • 完整的备份体系:一致性快照、OSS 加密异地副本、MD5 跳过、一键恢复
  • 轻量部署:Go 单二进制 + SQLite,个人服务器即可跑起来

LitAOSS 就是为此写的:一个主打个人自用的安全私人网盘。文件在浏览器里加密后再上传,后端全程只搬运密文,连文件名都是加密的——这是一套零知识(Zero-Knowledge)架构。

零知识的直观含义:数据库泄露 + OSS 凭证泄露 + 备份泄露全加在一起,没有你的主密码,一切都是乱码。

一、安全架构:零知识是怎么做到的

系统的核心是一套两级密钥层级,全部在浏览器端完成运算,服务器接触不到主密码。

  • 两次独立的 PBKDF2 派生(域分离):登录验证用的 Auth Hash 和解包 Account Key 用的密钥来自不同的派生路径(裸 salt / salt‖"account-key"),两者互不泄露。
  • Account Key 是随机生成的,不是从密码直接推出来的。这带来一个很实用的性质:修改主密码只需要重新包装 Account Key,所有文件内容和文件名完全不用动。
  • 每个文件一把独立的 File Key:单个文件的密钥泄露不影响其他文件。
  • 文件名同样加密:服务端数据库里的 name_encrypted 是 Account Key 加密的密文,服务器不知道你存的是”合同.pdf”还是别的什么。

服务端手里只有什么

数据服务端视角
文件内容AES-256-GCM 密文(存 OSS)
文件名Account Key 加密的密文
File Key被包装的密文,自己解不开
主密码从未收到过(只收到单向派生的 Auth Hash)
登录凭证PBKDF2 500 万次迭代强度的 Auth Hash

零持久化:钥匙不落盘

解锁材料(主密码、Session Token、Master Key)只存在于页面内存中:

  • 刷新页面、开新标签页、关闭页面、点”锁定”——一律要求重新输入主密码
  • 不写 localStorage、不写 cookie、不落地任何密钥材料

传输与接口安全

  • 强制 HTTPS(Web Crypto API 只在安全上下文可用,这也是部署硬性要求)
  • CSP 安全策略 + 一组安全响应头
  • 登录失败 5 次锁定 15 分钟
  • 可选 MFA(TOTP) 登录二次验证;删除文件、恢复备份这两个危险操作额外要求 TOTP 复验
  • 上传/下载走预签名 URL,浏览器直传直读 OSS,密文不经过后端业务逻辑

二、主要功能

文件管理

  • 加密上传:浏览器本地加密 → 预签名 URL 直传 OSS
  • 加密下载:拉取密文 → 本地解密 → 落盘
  • 文件夹管理、重命名、批量删除
  • 网格 / 列表双视图、存储用量统计
  • 修改密码 / 一键锁定

预览与在线编辑

  • 图片、文本在线预览:支持 jpg/png/gif/webp/svg 及常见代码、文本格式
  • 预览前做类型 + 大小双重校验(超过 200MB 或类型不支持直接拦截,不发起任何网络请求)
  • 文本在线编辑:保存自动生成版本历史,可随时回看旧版本

软删除(OSS 不物理删)

删除文件时,OSS 上的对象不真正删除,只是在前端页面不再展示,这也是为了安全性考虑:

  1. 误删可追溯、可恢复
  2. OSS 权限只需要 PutObject/GetObject,完全不需要 DeleteObject——凭证万一泄露,攻击者也删不了数据

如果开启了二次验证,首次软删除会触发MFA验证,后续删除不再验证(仅限当前会话不验证)。

三、极为重要的备份与恢复

用零知识网盘必须想清楚一件事:数据库就是你的密钥库。文件密钥、加密文件名、OSS 对象键全在里面——数据库丢了且没备份,即使主密码正确,OSS 上的文件也永久无法解密。所以LitAOSS支持本地+OSS异地双备份容灾支持。

本地备份:

  • 三种触发方式:手动一键备份 / 每日定时(默认 03:00)/ 文件操作后自动触发(带 5 分钟防风暴间隔)
  • VACUUM INTO 一致性快照:包含 WAL 中未 checkpoint 的数据,是真正等于当前时刻的完整副本
  • 自动清理,保留最近 N 份(默认 10)

OSS 加密异地副本:

  • 每次备份可顺手上传一份加密副本到 OSS,异地容灾
  • 上传前用 scrypt(数据库口令) + AES-256-GCM 加密——没配置数据库口令就拒绝上传,杜绝明文备份上云
  • 明文 MD5 与本地台账比对,内容没变自动跳过,不浪费存储

恢复:

  • 本地备份、OSS 备份都支持一键恢复,恢复走 TOTP 二次验证
  • 恢复采用暂存机制:先写入 .restore 文件,重启服务端时应用——不会打断正在运行的服务

四、部署

技术架构比较轻量,主打个人使用。

组件选型
前端React 18 + TypeScript + Vite + TailwindCSS
后端Go + Gin(交叉编译单二进制,Linux/Windows 直接跑)
数据库SQLite(WAL 模式)
对象存储阿里云 OSS

用 Nginx 反代 + Let’s Encrypt 签证书即可。HTTPS 是必须的(上文说过,Web Crypto 只在安全上下文工作——我第一次部署时就因为纯 HTTP 踩过这个坑,首次设置页面会直接报错)。

location / {
root /www/wwwroot/pan.ranjuan.cn/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
# 反代后端
location /api/ {
proxy_pass http://127.0.0.1:8780;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
proxy_set_header X-Host $host:$server_port;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 30s;
proxy_read_timeout 86400s;
proxy_send_timeout 30s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

五、最后

使用LitAOSS 私人加密云盘你需要知晓以下限制:

限制原因
忘记主密码 = 数据永久丢失服务端没有明文、没有后门,这是零知识的对价
没有全文搜索、服务端缩略图服务端根本看不懂内容,只能全在浏览器做
必须 HTTPSWeb Crypto 的安全上下文要求
目前仅支持阿里云 OSS个人项目,按需扩展
前端是信任根所有加密逻辑都在前端,务必保证 npm 依赖可信、走 HTTPS

另外提醒:data/目录(数据库 + 备份)等同于密钥库,要像备份 OSS 一样备份它。

LitAOSS 项目开源地址:https://github.com/joolan/LitAOSS

染卷

本站文章也会定期同步到微信公众号,可以关注下避免错过~

建站 12年 24天
微信公众号

发表评论

邮箱不会公开,带 * 为必填。