systemslibrarian/DeckBook
GitHub: systemslibrarian/DeckBook
一个基于扑克牌模拟一次性密钥本的密码学教育 PWA,通过交互式可视化和 CTF 挑战教授流密码原理与密钥重用攻击。
Stars: 0 | Forks: 0
# DeckBook
[](https://github.com/systemslibrarian/DeckBook/actions/workflows/ci.yml)
[](https://github.com/systemslibrarian/DeckBook/actions/workflows/lighthouse.yml)
一个基于卡片的 one-time keybook 演示,用于教学密钥分发、one-time pads、流密码以及密钥重用的危险。
DeckBook 是一款教育性的展览式 Web 应用(Cipher Museum 主题),它模拟了以下核心理念:
**牌的顺序就是密钥。线索只告诉你该使用哪个密钥。**
**[▶ 体验在线展览](https://systemslibrarian.github.io/DeckBook/)**
| 观看密码运行 | 破解重用的密钥 | 参与拦截挑战 |
| --- | --- | --- |
|  |  |  |
## 质量
- **无障碍性:** 在初始页面、所有参考面板展开以及挑战模式下,没有违反 WCAG 2.1 A/AA 标准的 axe-core 违规项,并由 CI 强制执行
([e2e/a11y.spec.ts](e2e/a11y.spec.ts))。支持完整的键盘操作、
屏幕阅读器标签,并在全局提供 `prefers-reduced-motion` 支持。
- **经过测试:** 针对所有纯逻辑的 54 个单元测试 (Vitest),以及 8 个 Playwright
端到端测试(完整的加密→分享→解密往返过程、挑战解题,
以及无障碍审计)。两套测试套件都会在每次通过 CI 推送时运行。
- **精简且离线:** 完全客户端运行,无需后端。生产环境的资源包大小约为
34 KB JS + 6 KB CSS(gzipped 压缩后),并可作为支持离线使用的 PWA 安装。
- **Lighthouse CI:** [lighthouse.yml](.github/workflows/lighthouse.yml)
在每次推送和拉取请求时,针对构建的站点运行
Lighthouse(桌面预设,运行 3 次),对无障碍性进行门控,并报告性能、最佳实践
和 SEO。每次运行都会上传一份公开报告(URL 位于作业日志中)。
## 灵感
本项目的灵感来源于 Solitaire 等手动加密教学材料,包括:
- https://steemit.com/steemiteducation/@shai-hulud/solitaire-encryption-low-tech-high-security-a-how-to
## 免责声明
DeckBook 是一个用于教育演示的工具,并非生产级密码学。
- 不要使用此应用来保护真实的机密。
- 对于真实的安全需求,请使用经过审计的现代密码学工具。
## 教学内容
- One-time 密钥材料和密钥标识符
- 为什么密钥重用会失败
- 为什么密钥分发很困难
- 手动/物理密钥本的操作风险
- 为什么存在现代密钥交换(包括后量子 KEM 背景)
## 密码工作原理
该密码是对 26 个字母 A–Z 进行的类似 Vigenere 的加/减运算。不同之处
在于其 keystream 来源于一副洗过的扑克牌。
1. **字母转换为数字。** `A = 0, B = 1, …, Z = 25`。空格、数字
和标点符号在加密前会被去除。
2. **卡牌转换为 keystream。** 每张牌都有一个稳定的值 `0..51`
(黑桃 A = 0,梅花 K = 51)。每张牌贡献一个
keystream 字母:
keystream[i] = deck[i].value mod 26
一个字母对应一张牌,因此一副完整的牌会产生 52 个 keystream 字母,
单副牌的密钥最多只能加密 52 个字母。26 个
字母表中的每个字母都恰好被两个牌面数字击中,因此 keystream
是均匀分布的。
3. **加密通过 mod 26 加法完成,解密通过减法完成。**
cipher[i] = ( plain[i] + keystream[i] ) mod 26
plain[i] = ( cipher[i] - keystream[i] + 26 ) mod 26
对于超过 52 个字母的消息,Advanced multi-deck 模式会依次消耗
额外的全新牌组(字母 0–51 使用第一副牌,
52–103 使用第二副,依此类推)。每副牌都只被使用一次。
通信双方必须已经持有相同的私有 DeckBook。只有 index
code(如 `LANTERN-42` 这样的公开标签)和密文会通过
公共信道传输。牌的顺序本身就是机密。
## 功能亮点
### 交互式学习
- **观看它如何工作** — 一个动画可视化工具,每次运行一张牌的密码运算。
一张牌从牌堆中翻出,变成一个 keystream 数字,并位移
您消息中的一个字母,带有播放/暂停/单步执行/速度控制。
它是一个沙盒,永远不会消耗真实的密钥。
- **实时字母频率直方图** — 当您在 Encrypt 面板中输入时,两个
柱状图会实时更新:您的明文(具有典型英语特征的尖峰图)
与您的密文(平坦图)的对比。“没有偏爱的字母”这一课,
瞬间可见。
- **带有 crib dragging 的密钥重用攻击实验室** — 使用
相同的密钥加密两条消息,然后手动破解它们。输入一个猜测的单词(“crib”),将其沿着
密文的差值滑动,并在猜测正确的位置观察另一条消息是如何泄露出来的。包含按排名的
“最接近英语特征位置”的提示。
攻击过程中绝不输入任何密钥或牌的顺序 — 仅仅是重用就会导致明文泄露。
- **QR / 分享链接传递** — 每条加密的消息都会生成一个 QR 码和
一个仅携带 index code 和密文的深度链接(绝不包含牌的顺序)。
在另一台设备上扫描它;只有当该设备已经持有
匹配的 DeckBook 时,它才能解密。一条穿越真实公共信道的真实消息。
- **可打印的物理牌表** — 打印样式表会将牌的顺序
输出为一张整洁的表格,以便您可以整理出真实的牌组并手动验证某个字母。
### 打造体验
- **挑战模式 ("Eve's Intercept")** — 一个可分享、可通过深度链接访问的 CTF 风格
谜题。一名操作员对两条消息重用了同一个密钥;您扮演
窃听者,并仅使用 crib dragging 恢复两条消息,带有实时进度
计量条和获胜时的彩带动画。包含从简单到困难的三个谜题;使用
`#play=` 分享特定谜题。
- **故事框架** — 一个正在进行的 Alice → Bob 任务,且有 Eve 在线监听,将
各个步骤、模拟器和挑战结合在一起,构成一个完整的叙事。
- **可安装、支持离线的 PWA** — Web manifest 和 service worker 使
DeckBook 可以安装在手机或博物馆自助终端上,并在没有
网络的情况下完全可用。Open Graph / Twitter 卡片为分享的链接提供了精致的预览。
### 对于教育工作者
- 一份随时可用的[教学指南](docs/teaching-guide.md)(教学目标、与应用映射的 45-60 分钟定时
课程、讨论问题、评估、
标准关联)以及一份可打印的[学生练习册](docs/worksheet.md)。
- 应用内的**For Educators** 面板和包含所有关键术语的**词汇表**。
### 引导式、整洁的布局
- **编号步骤流程** — 核心的发送/接收路径被标记为 1-5
(生成 → 选择密钥 → 准备牌组 → 加密 → 解密),并在 hero 区域提供简洁的
概述,因此一目了然就能看懂操作顺序。
- **可折叠的参考部分** — 说明性面板(密码工作原理、安全模型、什么是 DeckBook?
等)默认作为
可通过键盘操作的可折叠面板,保持页面简短;引导式演示
和 presenter 模式会自动展开它们导航到的任何内容。
### 核心密码和密钥管理
- 使用 `crypto.getRandomValues()` 进行安全的牌组生成(不使用 `Math.random()`)
- 使用 Fisher-Yates 洗牌算法结合拒绝采样以实现无偏整数选择
- 带有 0-51 一致映射的 52 张牌组模型
- DeckBook 模式:10 / 100 / 1,000 个密钥
- 人类可读的 index code 和由 SHA-256 派生的指纹
- 带有自上而下清单的接收方设置视图
- A-Z 模运算加密/解密
- 用于长明文的多副牌组消息模式
- Two-Party Simulator (Alice / 公共信道 / Bob)
- 已用/未用密钥跟踪和明确的重用警告
- 导入/导出 DeckBook JSON(用于教育模拟)
- 浏览器存储中的本地持久化
- 错误模拟面板
- 移动端响应式布局和无障碍改进
## 技术栈
- Vite
- TypeScript
- Vanilla CSS
- 完全客户端(无后端)
## 本地开发
### 1. 安装依赖
```
npm install
```
### 2. 运行开发服务器
```
npm run dev
```
### 3. 构建生产版本
```
npm run build
```
### 4. 在本地预览生产构建
```
npm run preview
```
## 测试
- **单元测试** 覆盖了纯密码、攻击分析、分享链接
和卡牌界面模块:
npm test
- **端到端测试** 驱动真实 UI 完整执行
协议 — 生成 DeckBook,加密,跟随分享链接,
并解密回原始明文 — 此外还包括“没有
DeckBook 的设备无法读取消息”的场景以及动画可视化工具:
npm run test:e2e
这两套测试套件都会在每次推送和拉取请求时通过
[ci.yml](.github/workflows/ci.yml) 自动运行。
## GitHub Pages 部署
此仓库包含一个位于 [deploy-pages.yml](.github/workflows/deploy-pages.yml) 的 Pages 工作流。
### 一次性仓库设置
1. 打开仓库 Settings。
2. 转到 Pages。
3. 将 Source 设置为 GitHub Actions。
### 发布流程
- 推送到 `main` 分支。
- 工作流会构建应用程序并将 `dist/` 部署到 GitHub Pages。
## 无障碍与移动端说明
UI 的设计使其能在小屏幕上使用,并支持键盘导航。
- 语义化的部分和清晰的标签
- 基于文本的 USED/UNUSED 状态指示器(不仅仅是颜色区分)
- 具有琥珀色点缀的高对比度暗色主题
- 响应式卡片/网格布局
- 触摸友好的控件和紧凑的移动端行为
- 通过 `prefers-reduced-motion` 提供减少动态效果的支持
## 安全模型(教育性)
该模型仅在满足以下条件时才展示其安全性:
1. 牌的顺序是使用密码学随机性生成的。
2. 双方事先共享相同的私有 DeckBook。
3. 每副牌的密钥只被使用一次。
4. 已使用的密钥永不重用。
5. 牌的顺序绝不通过公开渠道传输。
6. Index code 不会泄露牌的顺序。
7. 谨慎处理人为错误和消息长度限制。
## 项目结构
- [index.html](index.html) 应用程序外壳
- [src/cipher.ts](src/cipher.ts) 纯密码核心(加密/解密,牌组,洗牌)
- [src/analysis.ts](src/analysis.ts) 纯攻击/分析数学逻辑(crib dragging,频率)
- [src/share.ts](src/share.ts) 纯分享链接编码/解码(QR payload)
- [src/qr.ts](src/qr.ts) QR 图像渲染助手
- [src/visualizer.ts](src/visualizer.ts) 动画“观看它如何工作”面板
- [src/main.ts](src/main.ts) 应用逻辑和 UI 渲染
- [src/styles.css](src/styles.css) 视觉设计和响应式样式
- [src/challenge.ts](src/challenge.ts) "Eve's Intercept" CTF 谜题模块
- [docs/](docs/) 教学指南和学生练习册
- [scripts/generate-icons.mjs](scripts/generate-icons.mjs) PWA/社交图标生成器
- [tests/](tests/) 针对密码、分析、分享、卡牌界面和挑战模块的 Vitest 单元测试
- [e2e/](e2e/) Playwright 端到端冒烟测试
- [vite.config.ts](vite.config.ts) 用于静态部署的 Vite +est 配置
- [playwright.config.ts](playwright.config.ts) Playwright 配置(启动开发服务器)
- [ci.yml](.github/workflows/ci.yml) 构建 + 单元测试 + 端到端测试(包含 a11y)工作流
- [lighthouse.yml](.github/workflows/lighthouse.yml) + [lighthouserc.json](lighthouserc.json) Lighthouse CI
- [deploy-pages.yml](.github/workflows/deploy-pages.yml) GitHub Pages 部署工作流
## 许可证
MIT
标签:PWA, 一次性密码本, 安全教育, 密码学, 手动系统调用, 流密码, 特征检测, 自动化攻击