commit 853531c07c89c894a4b7690fae970c1f98ffab19 Author: laoyang Date: Wed Oct 28 11:52:37 2026 +0800 feat: 密码生成器 simple_password 初版 (#1) 单文件 index.html,纯 HTML + CSS + JS,零外部依赖,双击即用。 功能: - 长度 4~64 可调;选「每类至少一位」时下限自动收紧到所选类型数 - 小写 / 大写 / 数字 / 符号四类可选,全不选会兜回小写而非生成空密码 - 生成即复制;剪贴板 API 不可用时降级到 execCommand - 排除易混淆字符(0 O o 1 l I)与自定义排除 - 真实熵值(长度 × log2(字符池))与五档强度评价 - 批量生成 5 个候选、最近 6 条历史(仅本机 localStorage) - 深浅色跟随系统并可手动切换,首帧前定主题避免闪烁 - 快捷键:空格换一个、C 复制 实现要点: - 随机数走 crypto.getRandomValues + 拒绝采样,消除取模偏差 - 「每类至少一位」= 各类先取一位 + 剩余全池随机 + 整体洗牌, 避免固定位置带来的可预测性 验证:功能判据 80 条、浏览器几何/对比度/多视口 105 条、 真实剪贴板端到端 18 条全绿;24 条反向注入全部命中。 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9a7fb51 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# 统一换行符:仓库内一律 LF,避免 Windows 提交后被转成 CRLF, +# 部署到 Linux 上再出现整文件 diff。 +* text=auto eol=lf + +# 图片是二进制,别做换行转换 +*.png binary +*.jpg binary +*.webp binary +*.ico binary \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d847ab6 --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +# Simple Password + +一个干净、纯本地的密码生成器。单文件 `index.html`,双击即用,也可丢到任意静态托管上。 + +![深色](./docs/dark.png) + +## 特点 + +- **纯前端,零依赖** — 一个 `index.html`,没有构建步骤、没有 CDN、没有任何外部请求。断网可用。 +- **密码学安全随机** — 走 `crypto.getRandomValues` + 拒绝采样消除取模偏差,不用 `Math.random()`。 +- **生成即复制** — 默认开启自动复制;剪贴板 API 不可用(如 `file://` 下的旧浏览器)时自动降级到 `execCommand`。 +- **深浅色** — 跟随系统偏好,可手动切换并记住选择。首帧前定主题,不会白屏闪一下。 +- **可调长度** — 4~64 位。选了「每类至少一位」时,下限自动收紧到所选类型数。 +- **四类字符可选** — 小写 / 大写 / 数字 / 符号,四类全不选会被兜回小写,不会生成空密码。 +- **排除易混淆字符** — 一键去掉 `0 O o 1 l I`,抄写不出错。 +- **自定义排除** — 想避开 `@`、空格或某个符号,直接填进去。 +- **强度与熵** — 按 `长度 × log₂(字符池)` 算真实熵,分五档给出评价,同时显示字符池规模。 +- **批量候选** — 一次出 5 个,点任意一条即复制。 +- **最近生成** — 只存在本机 `localStorage`,最多 6 条,可一键清空。 + +## 使用 + +直接打开 `index.html` 即可。 + +想用 http 协议(例如需要真实剪贴板权限时): + +```bash +python -m http.server 8000 +# 然后访问 http://127.0.0.1:8000/ +``` + +## 快捷键 + +| 键 | 作用 | +|---|---| +| `空格` | 换一个密码 | +| `C` | 复制当前密码 | +| `点击密码` | 也可以复制 | + +在输入框里打字时不会误触发。 + +## 关于安全 + +- 所有运算在浏览器里完成,**不联网、不上传、不写日志**。 +- 用 `crypto.getRandomValues` 取随机数,并按「拒绝采样」丢弃落在偏置区间的值,避免取模带来的分布倾斜。 +- 勾「每类至少一位」时,先从每类各取一位,剩余位从全池随机,最后整体洗牌 —— 保证覆盖的同时不引入位置可预测性。 +- 历史记录存在 `localStorage` 里,任何能访问这台机器的人都能看到。**在共用电脑上建议用完点「清空」**,或干脆关掉自动复制、不复制到历史。 + +## 浏览器支持 + +Chrome / Edge / Firefox / Safari 的近两年版本,以及移动端浏览器。 + +用到 `backdrop-filter`(毛玻璃)和 `crypto.getRandomValues`,老浏览器上会自动降级为不透明背景,功能不受影响。 + +## 目录 + +``` +index.html 全部内容:结构、样式、脚本 +``` + +## 开发校验 + +改完 `index.html` 后建议跑一遍(脚本在仓库外的 `_tooling/`,配合 `jsdom` 与 `playwright`): + +```bash +node _sp_test.js # 功能判据(jsdom,80 条,含反向注入 24 条) +node _sp_visual.js # 真实浏览器几何 / 对比度 / 多视口(约 101 条) +node _sp_clip.js # 真实剪贴板端到端(18 条) +``` + +## License + +MIT \ No newline at end of file diff --git a/docs/dark.png b/docs/dark.png new file mode 100644 index 0000000..467f66f Binary files /dev/null and b/docs/dark.png differ diff --git a/docs/light.png b/docs/light.png new file mode 100644 index 0000000..c668722 Binary files /dev/null and b/docs/light.png differ diff --git a/docs/mobile.png b/docs/mobile.png new file mode 100644 index 0000000..8a6b8ef Binary files /dev/null and b/docs/mobile.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..d55c987 --- /dev/null +++ b/index.html @@ -0,0 +1,1852 @@ + + + + + +Simple Password · 密码生成器 + + + + + + + + + +
+ +
+
+ +
+ Simple Password + Generator +
+
+ + +
+ +
+
+ + +
+
+
+ 生成的密码 + 自动复制 +
+ +
+ +
+ + +
+ +
+
+
+ — + — +
+
+ +

+
+ +

+ 空格 换一个 + C 复制 + 点击密码 也可以复制 +

+
+ + +
+ +
+ + + + +
+ +
+
+ + 16位 +
+ +
+ +
+
+ 字符组成 + +
+
+
+ +
+ + + + + +
+ +
+ + + 自定义排除字符 + +
+ +

这些字符不会出现在生成的密码中,可留空。

+
+
+ +
+
+ +
+
+
+

候选密码

+ +
+
  • 点右上角一次生成多个备选,点任意一条即复制。
+
+ +
+
+

最近生成

+ +
+
  • 还没有记录。生成并复制后会自动保存在本机。
+
+
+
+ +
+ 全程本地运算·使用 Web Crypto 密码学安全随机数·不联网、不上传、不留痕 +
+
+ +
+ + 已复制 +
+ + + + + + \ No newline at end of file