纯本地密码管理器 PWA。每个账号密码对应一颗星辰;不同平台间使用相同账号密码的星辰会连成星座,让密码复用一目了然。
零外部依赖:纯原生 HTML/CSS/JS,Canvas 2D 模拟 3D 透视投影(无 WebGL / Three.js),IndexedDB 存储,Web Crypto 加密,支持离线 PWA。无任何网络请求,数据永不离开本机。
哈勃望远镜深空照片质感 + Linear/Apple 级极简 UI。
- 写实星云:启动时在离屏 Canvas 程序生成(屏幕 1.5 倍,只生成一次缓存)——自实现 value noise 的 fBm 分形叠加(6 octaves)生成大尺度云气,叠加沿噪声场方向排布的丝状纤维与少数致密亮核;配色严格低饱和(灰蓝 slate / 暗青灰 / 极少量暖尘埃与暗玫瑰),alpha 峰值 ≤ 0.35,大片留黑,「黑中见云」。
- 背景星场:1600 颗微小恒星(0.3–1.2px),真实色温分布(大部分蓝白/白,少数暖黄橙),极少数亮星带细腻十字衍射芒;背景随相机轻微视差。
- 数据星辰:白/蓝白核心(色温由 id 哈希决定)+ 极淡白色光晕;平台色去饱和后仅在最外层光晕以 15% 透明度微染,主要展示位在 UI(详情面板小光点);衍射十字光芒仅强度 > 80 出现(细、淡)。
- 星座连线:闲置
rgba(180,200,235,0.12)极细流动虚线;激活rgba(200,220,255,0.55)脉冲实线;诞生/湮灭/超新星/虫洞特效统一白与蓝白色调。 - 极简 UI:悬浮 pill 工具栏(纯文字字标 + pill 搜索框 + 圆形线条 "+" + "···" 溢出菜单);左下角 10px 状态行(静止 3 秒自动淡出);ghost 文字按钮(hover 仅微亮);下划线输入框(focus 线变亮);全站唯一强调色为暖白
rgba(235,240,250,1);过渡统一cubic-bezier(0.32,0.72,0,1)。
- 透视投影:
screenX = cx + x * FOV / (z + camDist),近大远小;相机绕 Y 轴旋转(含 0.1°/帧缓慢自转)+ X 轴小角度俯仰(±0.6 rad)+ 前后推进(camDist 250–2600)。 - 星际尘埃层:约 120 颗稀疏尘埃粒子(白/蓝白,透明度 0.05–0.2),3D 空间较差自转 + 正弦伪湍流 + 鼠标轻微引力扰动;additive 混合;视锥裁剪。
- 星辰 3D 化:位置含 z 坐标(哈希派生 -200~+200,同平台聚集保留);每帧按深度从远到近排序(画家算法);远处星辰(scaleF < 0.35)自动降级为圆点。
- 特效:星辰诞生(光束粒子流 → 落点膨胀)、星辰湮灭(收缩 → 爆发粒子消散)、超新星合并(伴星汇聚 → 碰撞爆发强光)、虫洞同步(螺旋粒子漩涡 → 收缩爆发光环)。
设置面板中可选 自动 / 高 / 中 / 低 四档(选择持久化保存):
| 模式 | 尘埃数 | 特性 |
|---|---|---|
| 高 | 200(移动端 100) | 全部特性 |
| 自动(默认) | 120(移动端 60) | 帧率持续 < 30fps 自动降级:尘埃减半 → 关闭扰动 → 完全 2D 模式 |
| 中 | 80(移动端 40) | 关闭鼠标扰动 |
| 低 | 40(移动端 20) | 精简特性,无扰动 |
左下角状态行实时显示当前 fps(静止 3 秒自动淡出,交互时淡入)。
⚠ 必须通过本地静态服务器访问(http://localhost 或 https://),因为:
crypto.subtle(Web Crypto API)仅在安全上下文下可用;- Service Worker(PWA 离线)同样要求安全上下文。
任选一种方式,在项目根目录启动:
# Python
python -m http.server 8000
# Node.js
npx serve .然后浏览器访问 http://localhost:8000。打开后可通过浏览器菜单「安装应用」将 StellarVault 安装为独立 PWA。
- 首次打开:设置主密码(两次输入确认)。
- ⚠ 主密码丢失,数据将无法恢复! 应用不存储主密码本身,无法找回,请务必牢记。
- 解锁后进入星图:点击「+ 添加」点亮第一颗星辰。
- 之后每次打开:输入主密码解锁星图。
- 星图导航(3D):拖拽 = 旋转视角(绕 Y 轴环视 + X 轴俯仰);滚轮 = 前后推进(改变相机距离);双击空白处 或设置中「回到星图中心」复位视角;点击星辰时相机 0.8 秒平滑飞行(easeInOutCubic)到该星辰前方。移动端:单指旋转、双指捏合调整距离、长按星辰弹出菜单。
- 工具栏:左侧纯文字字标,中间搜索 pill + 「全部/星座」tab,右侧圆形 "+" 添加与 "···" 溢出菜单(收纳:导入 / 导出 / 同步 / 合并伴星 / 设置 / 锁定)。
- 星辰:大小/亮度由密码强度决定;强度 > 60 的星辰带十字光芒;颜色对应平台类型(办公蓝 / 社交紫 / 金融金 / 娱乐红 / 购物绿 / 其他灰)。
- 星座:相同「账号 + 密码」的星辰自动连线(金色流动虚线管道)。点击任一星,其所属星座高亮为脉冲实线。底部可切换「全部 / 星座」视图,设置面板中可查看去重统计("发现 N 个星座,M 颗伴星可合并")。
- 超新星合并(去重):详情面板伴星区点击「合并伴星至此星」,或设置面板「一键合并全部星座」——伴星化作光球汇聚主星,碰撞爆发强光后重复条目被删除,仅保留一颗星。
- 搜索:顶部搜索框实时过滤,不匹配的星辰变暗。
- 详情:点击星辰打开右侧详情面板,可复制账号/密码、查看密码(显示 3 秒后自动恢复掩码)、点击伴星跳转。
| 格式 | 说明 |
|---|---|
| 通用 CSV | platform,account,password,note,首行标题可选,支持引号包裹含逗号字段 |
.starmap |
本应用加密备份格式(需用本库主密码解密) |
| Bitwarden | Bitwarden 导出的 JSON(读取 items[].login) |
| Chrome | Chrome 密码导出 CSV(name,url,username,password)或同构 JSON |
- 导入前逐条检测相同
platform + account,可逐条选择 覆盖 / 跳过 / 重命名,或 全部覆盖 / 全部跳过。 - 导入时每条数据化为流星飞入星图,错误行记录在导入日志中。
.starmap(推荐):用主密钥 AES-256-GCM 加密的 JSON 备份。- 明文 CSV(危险):二次确认 + 醒目警告后导出。⚠ 明文文件任何人均可直接读取,用后请立即安全删除。
纯静态页面没有服务器,采用同步包方式:
- 发送端:同步 → 发送同步包 → 输入(或随机生成)6 位临时口令 → 生成加密文本块并复制;
- 接收端:同步 → 接收同步包 → 粘贴文本 + 输入同一口令 → 导入合并;
- 合并协议:按
(id, updatedAt)比对,只传差异条目;时间新的覆盖旧的;id + updatedAt完全相同但内容不同的条目列为冲突提示。
可选 WebSocket 中继:同步 → 中继标签页,连接自建 ws:// 中继实时传输。极简 Node 中继脚本(保存为 relay.js,node relay.js 运行):
// 极简 WebSocket 同步中继(需 npm i ws)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8765 });
const rooms = new Map(); // room → Set<ws>
wss.on('connection', (ws) => {
ws.on('message', (data) => {
let msg;
try { msg = JSON.parse(data); } catch { return; }
if (msg.type === 'join') {
ws._room = msg.room;
if (!rooms.has(msg.room)) rooms.set(msg.room, new Set());
rooms.get(msg.room).add(ws);
} else if (msg.type === 'sync' && ws._room) {
// 转发给房间内其他成员
(rooms.get(ws._room) || []).forEach((peer) => {
if (peer !== ws && peer.readyState === 1) peer.send(JSON.stringify(msg));
});
}
});
ws.on('close', () => {
if (ws._room && rooms.has(ws._room)) rooms.get(ws._room).delete(ws);
});
});
console.log('StellarVault 中继已启动: ws://0.0.0.0:8765');- 加密:PBKDF2(SHA-256,100,000 次迭代,32 字节随机盐)派生 AES-256-GCM 密钥;每条密码使用独立 12 字节随机 IV,存储格式
base64(iv):base64(密文)。 - 主密码只存在于内存;IndexedDB 中仅存盐与「用主密钥加密已知常量」的验证器(解锁时尝试解密验证,不存主密码哈希本身)。
- 解密后的明文密码仅驻留内存,查看密码 3 秒后自动恢复掩码;点击「立即锁定」或刷新页面即清空内存密钥与明文缓存。
- ⚠ 主密码丢失 = 数据永久无法恢复(应用在多处醒目警告)。
- 明文 CSV 导出是高危操作,需二次确认。
| 快捷键 | 功能 |
|---|---|
Ctrl + F |
聚焦搜索框 |
Ctrl + N |
添加星辰 |
Esc |
关闭全部面板/弹窗 |
stellar-vault/
index.html # 页面结构与全部面板/弹窗
css/cosmos.css # 基础布局与排版(近黑深空、极简字标、ghost 按钮)
css/glass.css # 极简玻璃拟态(24px 模糊、单层柔影、下划线输入框)
js/cosmos.js # 3D 星云渲染引擎(透视投影、星云粒子、相机、特效)
js/stars.js # 星辰数据模型、3D 位置算法、密码强度评估
js/constellations.js # 重复密码分组、星座统计与视图过滤(连线绘制在引擎内)
js/crypto.js # PBKDF2 + AES-256-GCM 加密
js/db.js # IndexedDB 封装(meta / stars / syncLog)
js/import.js # CSV/JSON 导入导出(.starmap / Bitwarden / Chrome)
js/sync.js # 同步包合并协议 + 可选 WebSocket 中继客户端
js/app.js # 主程序入口与全部 UI 逻辑
manifest.json # PWA 清单
sw.js # Service Worker(cache-first 离线缓存)
icons/icon.svg # 应用图标
各 JS 文件通过 <script> 按依赖顺序加载,模块间以全局命名空间通信(VaultCrypto / DB / Stars / Constellations / Cosmos / ImportExport / Sync / App),不使用 ES modules。
能防:
- 设备丢失/被他人借用时的离线读取:数据全程 AES-256-GCM 加密存储,无主密码无法解密
- 数据库文件被拷贝:同样无法脱离主密码解密
- 意外窥屏:密码默认掩码,查看 3 秒自动恢复;复制密码 30 秒后自动清空剪贴板
- 明文导出误用:二次确认 + 醒目警告;CSV 导出已做 Excel 公式注入转义
不防(请务必了解):
- 解锁状态下的本机恶意软件/浏览器扩展(它们可读取内存与 DOM)
- 主密码本身被钓鱼、被旁观者看到
- 弱主密码被离线暴力破解(请使用足够长且复杂的主密码;10 万次 PBKDF2 只能延缓、不能阻止弱密码被爆破)
- 同步包通过不安全渠道传输且临时口令过弱
- ✅ XSS:全部用户可控字段经
textContent/转义渲染,无危险innerHTML拼接 - ✅ 敏感数据:明文密码不进日志/持久层/不可见 DOM 属性;锁定时清空内存密钥与解密缓存
- ✅ 加密:PBKDF2-SHA256 ×100,000 + AES-256-GCM;salt/IV 均来自
crypto.getRandomValues - ✅ 同步包:同一套 PBKDF2(10 万次迭代)+ 随机盐,含格式校验
- ✅ 导入:文件大小上限 10MB 防 DoS;CSV 导出防公式注入
- ✅ Service Worker 仅缓存静态资源,不涉及用户数据
- ✅ 零外部请求、零第三方依赖、无
eval/new Function
欢迎 Issue 与 Pull Request。修改后请确保:所有 js/*.js 通过 node --check;不引入任何外部依赖;涉及 UI 的改动保持现有极简深空美术方向。
MIT © StellarVault Contributors