2026-10-28 11:52:37 +08:00
|
|
|
|
# Simple Password
|
|
|
|
|
|
|
|
|
|
|
|
一个干净、纯本地的密码生成器。单文件 `index.html`,双击即用,也可丢到任意静态托管上。
|
|
|
|
|
|
|
2026-10-28 15:25:47 +08:00
|
|
|
|
**在线使用 → https://password.yangyq.net/**
|
|
|
|
|
|
|
|
|
|
|
|

|
2026-10-28 11:52:37 +08:00
|
|
|
|
|
|
|
|
|
|
## 特点
|
|
|
|
|
|
|
|
|
|
|
|
- **纯前端,零依赖** — 一个 `index.html`,没有构建步骤、没有 CDN、没有任何外部请求。断网可用。
|
2026-10-28 13:57:29 +08:00
|
|
|
|
- **左设置、右操作** — 设置栏在左,不调任何设置时视线直接落到右侧的密码与「复制密码」。窄屏自动变上下排列,设置在上。
|
2026-10-28 11:52:37 +08:00
|
|
|
|
- **密码学安全随机** — 走 `crypto.getRandomValues` + 拒绝采样消除取模偏差,不用 `Math.random()`。
|
|
|
|
|
|
- **生成即复制** — 默认开启自动复制;剪贴板 API 不可用(如 `file://` 下的旧浏览器)时自动降级到 `execCommand`。
|
|
|
|
|
|
- **深浅色** — 跟随系统偏好,可手动切换并记住选择。首帧前定主题,不会白屏闪一下。
|
|
|
|
|
|
- **可调长度** — 4~64 位。选了「每类至少一位」时,下限自动收紧到所选类型数。
|
|
|
|
|
|
- **四类字符可选** — 小写 / 大写 / 数字 / 符号,四类全不选会被兜回小写,不会生成空密码。
|
|
|
|
|
|
- **排除易混淆字符** — 一键去掉 `0 O o 1 l I`,抄写不出错。
|
|
|
|
|
|
- **自定义排除** — 想避开 `@`、空格或某个符号,直接填进去。
|
|
|
|
|
|
- **强度与熵** — 按 `长度 × log₂(字符池)` 算真实熵,分五档给出评价,同时显示字符池规模。
|
|
|
|
|
|
- **批量候选** — 一次出 5 个,点任意一条即复制。
|
2026-10-28 15:25:47 +08:00
|
|
|
|
- **不保留记录** — 不记历史,`localStorage` 只存偏好设置与主题,不存密码。
|
|
|
|
|
|
|
|
|
|
|
|
## 界面
|
|
|
|
|
|
|
|
|
|
|
|
设置与主操作分居左右两栏 —— 不调设置的人,视线直接落到右侧的密码和「复制密码」上。
|
|
|
|
|
|
「复制密码」与「换一个」严格等大(实测 241×42,宽高差 0px),用渐变与实心填充区分主次。
|
|
|
|
|
|
|
|
|
|
|
|
浅色主题:
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
移动端自动转为上下单列,设置在输出之上:
|
|
|
|
|
|
|
|
|
|
|
|
<img src="./docs/mobile.png" alt="移动端" width="320">
|
2026-10-28 11:52:37 +08:00
|
|
|
|
|
|
|
|
|
|
## 使用
|
|
|
|
|
|
|
2026-10-28 15:25:47 +08:00
|
|
|
|
直接用浏览器打开 `index.html` 即可,无需服务器。
|
2026-10-28 11:52:37 +08:00
|
|
|
|
|
2026-10-28 15:25:47 +08:00
|
|
|
|
已经部署的在线版本:<https://password.yangyq.net/>
|
|
|
|
|
|
|
|
|
|
|
|
想在本地用 http 协议(例如需要真实剪贴板权限时):
|
2026-10-28 11:52:37 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
python -m http.server 8000
|
|
|
|
|
|
# 然后访问 http://127.0.0.1:8000/
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 快捷键
|
|
|
|
|
|
|
|
|
|
|
|
| 键 | 作用 |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| `空格` | 换一个密码 |
|
|
|
|
|
|
| `C` | 复制当前密码 |
|
|
|
|
|
|
| `点击密码` | 也可以复制 |
|
|
|
|
|
|
|
|
|
|
|
|
在输入框里打字时不会误触发。
|
|
|
|
|
|
|
|
|
|
|
|
## 关于安全
|
|
|
|
|
|
|
|
|
|
|
|
- 所有运算在浏览器里完成,**不联网、不上传、不写日志**。
|
|
|
|
|
|
- 用 `crypto.getRandomValues` 取随机数,并按「拒绝采样」丢弃落在偏置区间的值,避免取模带来的分布倾斜。
|
|
|
|
|
|
- 勾「每类至少一位」时,先从每类各取一位,剩余位从全池随机,最后整体洗牌 —— 保证覆盖的同时不引入位置可预测性。
|
2026-10-28 13:57:29 +08:00
|
|
|
|
- **不保留任何生成记录**。密码只存在于剪贴板与页面显示,刷新即失去痕迹;`localStorage` 里只存偏好设置与主题,不存密码。
|
2026-10-28 11:52:37 +08:00
|
|
|
|
|
|
|
|
|
|
## 浏览器支持
|
|
|
|
|
|
|
|
|
|
|
|
Chrome / Edge / Firefox / Safari 的近两年版本,以及移动端浏览器。
|
|
|
|
|
|
|
|
|
|
|
|
用到 `backdrop-filter`(毛玻璃)和 `crypto.getRandomValues`,老浏览器上会自动降级为不透明背景,功能不受影响。
|
|
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
index.html 全部内容:结构、样式、脚本
|
2026-10-28 15:25:47 +08:00
|
|
|
|
docs/ README 用的界面截图
|
2026-10-29 13:24:47 +08:00
|
|
|
|
logo/ 品牌 logo 多尺寸 PNG(5 档 × 带阴影/无阴影)
|
2026-10-28 11:52:37 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-10-29 13:24:47 +08:00
|
|
|
|
`docs/logo/` 里的图**只进仓库、不部署到站点**(`_sp_deploy.sh` 只覆盖 `index.html`),
|
|
|
|
|
|
所以线上访问 `https://password.yangyq.net/docs/logo/logo-1024.png` 会 404 —— 这是预期行为。
|
|
|
|
|
|
|
2026-10-29 14:59:52 +08:00
|
|
|
|
重新导出 logo(脚本在仓库外的 `_tooling/`,需要 `playwright` + `Pillow`)。
|
|
|
|
|
|
**先 `cd _tooling/` 再跑**,脚本按 `__dirname/../simple_password` 定位仓库:
|
2026-10-29 13:24:47 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-10-29 14:59:52 +08:00
|
|
|
|
cd ../_tooling
|
|
|
|
|
|
node _sp_logo_export.js # 输出到 docs/logo/:logo-{64,128,256,512,1024}[-flat].png
|
|
|
|
|
|
python3 _sp_logo_verify.py # 像素判据 95 项:白边比例 / 主体居中 / 阴影朝向 / 圆角
|
|
|
|
|
|
python3 _sp_logo_verify_falsify.py # 反证 6 条:证明上面那套判据抓得住 bug
|
2026-10-29 13:24:47 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-10-29 14:59:52 +08:00
|
|
|
|
> ⚠️ **不要在不同机器上重跑覆盖仓库里的 PNG**。仓库里这 10 张是在 Windows 侧生成的,
|
|
|
|
|
|
> 换到 WSL(或另一台机器)重跑,字体度量与阴影模糊实现不同,产物**逐字节全不一样**
|
|
|
|
|
|
> —— 实测 10/10 文件 md5 全变,阴影版最大通道差到 255。判据仍是 95/95 通过、
|
|
|
|
|
|
> 几何关系一致,但 diff 会是一大堆无法 review 的二进制变更。真要重跑就接受这一点,
|
|
|
|
|
|
> 别把它当成"脚本坏了"。
|
|
|
|
|
|
|
2026-10-29 13:24:47 +08:00
|
|
|
|
尺寸是 64/128/256/512/1024 五档,每档两版:`logo-N.png` 带品牌阴影(用于展示场合)、
|
|
|
|
|
|
`logo-N-flat.png` 无阴影(用于 favicon、深色底、贴边摆放)。画布是正方形,
|
|
|
|
|
|
白边控制在 shadow 8% / flat 3%(旧版 41%)。
|
|
|
|
|
|
|
2026-10-28 11:52:37 +08:00
|
|
|
|
## 开发校验
|
|
|
|
|
|
|
|
|
|
|
|
改完 `index.html` 后建议跑一遍(脚本在仓库外的 `_tooling/`,配合 `jsdom` 与 `playwright`):
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-10-29 14:59:52 +08:00
|
|
|
|
cd ../_tooling
|
2026-10-28 13:57:29 +08:00
|
|
|
|
node _sp_test.js # 功能判据(jsdom,78 条)
|
|
|
|
|
|
node _sp_visual.js # 真实浏览器几何 / 对比度 / 多视口(114 条)
|
|
|
|
|
|
node _sp_clip.js # 真实剪贴板端到端(19 条)
|
|
|
|
|
|
node _sp_file_check.js # file:// 双击直开(15 条)
|
|
|
|
|
|
node _sp_falsify.js # 反向注入,证明功能判据有牙齿(22 条)
|
|
|
|
|
|
node _sp_visual_falsify.js # 反向注入,证明几何判据有牙齿(6 条)
|
2026-10-28 11:52:37 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-10-28 13:57:29 +08:00
|
|
|
|
反向注入必须单独跑视觉那套:`_sp_falsify.js` 只喂 `_sp_test.js`(jsdom 不做布局),
|
|
|
|
|
|
把「按钮等大」「两栏左右」这类几何 bug 注进去根本影响不到被测判据,
|
|
|
|
|
|
会表现成"注入后仍全绿",看着像判据没牙齿,其实是靶子选错。
|
|
|
|
|
|
|
2026-10-28 15:25:47 +08:00
|
|
|
|
重拍 README 截图:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-10-29 14:59:52 +08:00
|
|
|
|
cd ../_tooling
|
2026-10-28 15:25:47 +08:00
|
|
|
|
node _sp_shots.js # 输出到仓库 docs/:dark.png / light.png / mobile.png
|
|
|
|
|
|
node _sp_shot_verify.js # 断言被截图的那个页面状态是对的(26 条)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-10-29 14:59:52 +08:00
|
|
|
|
> ⚠️ 截图同样是**跨机器不可复现**的:手机视口实测 Windows 780×2490、WSL 780×2510,
|
|
|
|
|
|
> 字体度量差异导致高度不同。判据只断言几何关系,别断言绝对页高,也别拿另一侧的图覆盖仓库。
|
|
|
|
|
|
|
2026-10-28 15:25:47 +08:00
|
|
|
|
> 截图脚本与判据脚本分开,是因为判据脚本的截图(`_sp_shots` 目录)尺寸与时机跟着判据走,
|
|
|
|
|
|
> 会带 toast、焦点框、320px 极端视口;README 需要的是干净的产品图。混在一起改判据就会把图搞脏。
|
|
|
|
|
|
|
2026-10-28 11:52:37 +08:00
|
|
|
|
## License
|
|
|
|
|
|
|
|
|
|
|
|
MIT
|