crypto-protocol-diagram

crypto-protocol-diagram

热门

从源代码、RFC、学术论文、伪代码、非正式描述、ProVerif (.pv) 或 Tamarin (.spthy) 模型中提取协议消息流,并生成带有密码学注释的 Mermaid 序列图。适用于绘制加密协议图、可视化握手或密钥交换流程、从规范或 RFC 中提取消息流、绘制 ProVerif 或 Tamarin 模型图,或为 TLS、Noise、Signal、X3DH、Double Ratchet、FROST、DH 或 ECDH 协议绘制序列图。

6336Star
545Fork
更新于 2026/7/30
SKILL.md
只读
名称
crypto-protocol-diagram
描述

从源代码、RFC、学术论文、伪代码、非正式描述、ProVerif (.pv) 或 Tamarin (.spthy) 模型中提取协议消息流,并生成带有密码学注释的 Mermaid 序列图。适用于绘制加密协议图、可视化握手或密钥交换流程、从规范或 RFC 中提取消息流、绘制 ProVerif 或 Tamarin 模型图,或为 TLS、Noise、Signal、X3DH、Double Ratchet、FROST、DH 或 ECDH 协议绘制序列图。

加密协议图

生成一个 Mermaid sequenceDiagram(写入文件)和一个 ASCII 序列图(内联打印),输入可以是:

  • 源代码:实现加密协议的代码,或
  • 规范:RFC、学术论文、伪代码、非正式描述、ProVerif (.pv) 或 Tamarin (.spthy) 模型。

使用的工具: Read、Write、Grep、Glob、Bash、WebFetch(用于 URL 规范)。

diagramming-code 技能(可视化代码结构)不同,本技能提取的是协议语义:谁向谁发送了什么,每一步执行了什么密码学变换,以及存在哪些协议阶段。

如需调用图、类层次结构或模块依赖关系图,请改用 diagramming-code 技能。

何时使用

  • 用户要求绘制、可视化或提取加密协议
  • 输入是实现握手、密钥交换或多方协议的源代码
  • 输入是 RFC、学术论文、伪代码或形式化模型(ProVerif/Tamarin)
  • 用户指定了特定协议(TLS、Noise、Signal、X3DH、FROST)

何时不使用

  • 用户想要调用图、类层次结构或模块依赖关系图——请使用 diagramming-code
  • 用户想要形式化验证协议——请使用 mermaid-to-proverif(在生成图之后)
  • 输入没有加密协议语义(没有参与方,没有消息交换)

拒绝理由

理由 错误原因 正确操作
"协议很简单,我可以凭记忆画图" 基于记忆的图会遗漏步骤并颠倒箭头方向 系统地阅读源代码或规范
"既然有代码,我就跳过规范路径" 代码可能与规范不一致——两条路径能发现不同的错误 当两者都存在时,先运行规范工作流,然后注释代码差异
"密码学注释是可选的装饰" 没有密码学注释,图就只是消息流——对安全审查无用 注释每一个密码学操作
"中止路径很明显,不需要 alt 块" 隐式的中止处理会隐藏缺失的错误检查 使用 alt 块显示每个中止/错误路径
"我不需要先检查示例" 示例定义了预期的输出质量标准 在处理不熟悉的输入之前,先研究相关示例
"ProVerif/Tamarin 模型是代码,不是规范" 形式化模型是规范——它们描述的是预期行为,而非实现 .pv.spthy 文件使用规范工作流(S1–S5)

工作流

协议图进度:
- [ ] 步骤 0:确定输入类型(代码/规范/两者)
- [ ] 步骤 1(代码)或 S1–S5(规范):提取协议结构
- [ ] 步骤 6:生成 sequenceDiagram
- [ ] 步骤 7:验证并交付

步骤 0:确定输入类型

在执行任何其他操作之前,对输入进行分类:

信号 输入类型
源文件扩展名(.py.rs.go.ts.js.cpp.c 代码
函数/类定义、导入语句 代码
RFC 风格的章节标题(§Section X.YMUST/SHALL 关键词) 规范
Algorithm/Protocol/Figure 标签、数学符号 规范
ProVerif 文件(.pv),包含 processletin/out 规范
Tamarin 文件(.spthy),包含 rule--[...]-> 规范
描述协议的纯文本或编号步骤 规范
同时包含源文件和规范文档 两者(用 ⚠️ 注释差异)
  • 仅代码 → 跳转到下面的步骤 1
  • 仅规范 → 跳转到下面的规范工作流(S1–S5)
  • 两者 → 先运行规范工作流,然后使用代码阅读步骤验证实现是否与规范图一致,并用 ⚠️ 注释任何差异
  • 不明确 → 询问用户:“这是源代码文件、规范文档,还是两者都有?”

步骤 1:定位协议入口点

使用 Grep 搜索函数名、类型名和注释,以揭示协议:

# 查找握手、会话、轮次、阶段入口点
rg -l "handshake|session_init|round[_0-9]|setup|keygen|send_msg|recv_msg" {targetDir}

# 查找使用的密码学原语
rg "sign|verify|encrypt|decrypt|dh|ecdh|kdf|hkdf|hmac|hash|commit|reveal|share" \
    {targetDir} --type-add 'src:*.{py,rs,go,ts,js,cpp,c}' -t src -l

从最高层的编排函数开始阅读——即调用握手阶段或主协议循环的函数。

步骤 2:识别参与方和角色

从以下内容中提取参与者名称:

  • 结构体/类名:ClientServerInitiatorResponderProverVerifierDealerPartyCoordinator
  • 携带角色状态的函数参数名
  • 声明协议角色的注释
  • 设置两方或多方场景的测试夹具

将这些映射到 Mermaid participant 声明。使用简短、可读的别名:

participant I as Initiator
participant R as Responder

步骤 3:追踪消息流

跟踪状态转换和网络发送/接收。查找以下模式:

模式 含义
send(msg) / recv() 直接消息交换
serialize + transmit 发送结构化消息
返回值传递给另一方的函数 逻辑消息(进程内)
round1_outputround2_input 基于轮次的 MPC 步骤
结构体字段名为 ephemeral_keyciphertextmactag 消息内容

对于进程内协议实现(双方在同一进程中运行),当函数调用边界代表部署中本应是网络边界时,将其视为逻辑消息发送。

步骤 4:注释密码学操作

在每个协议步骤中,识别并标记:

操作 图注释
密钥生成 Note over A: keygen(params) → pk, sk
DH / ECDH Note over A,B: DH(sk_A, pk_B)
KDF / HKDF Note over A: HKDF(ikm, salt, info)
签名 Note over A: Sign(sk, msg) → σ
验证 Note over B: Verify(pk, msg, σ)
加密 Note over A: Enc(key, plaintext) → ct
解密 Note over B: Dec(key, ct) → plaintext
承诺 Note over A: Commit(value, rand) → C
哈希 Note over A: H(data) → digest
秘密共享 Note over D: Share(secret, t, n) → {s_i}
阈值组合 Note over C: Combine({s_i}) → secret

保持注释简洁——使用数学简写,而非代码。

步骤 5:识别协议阶段

使用 rectNote 块将消息步骤分组为命名阶段:

常见需要检测的阶段:

  • 设置/密钥生成:参与方密钥创建、可信设置、参数生成
  • 握手/初始化:临时密钥交换、随机数交换、版本协商
  • 认证:身份证明、证书交换、签名验证
  • 密钥派生:从共享秘密派生会话密钥
  • 数据传输/主协议:加密的应用数据交换
  • 终结/拆除:会话关闭、MAC 验证、中止处理

检测中止/错误路径,并使用 alt 块显示它们。


规范工作流(S1–S5)

当输入是规范文档而非源代码时,使用此路径。完成 S1–S5 后,继续执行上面代码工作流中的步骤 6(生成 sequenceDiagram)和步骤 7(验证并交付)。

步骤 S1:摄取规范

获取完整的规范文本:

  • 提供了文件路径 → 使用 Read 工具读取
  • 提供了 URL → 使用 WebFetch 获取
  • 内联粘贴 → 直接从对话上下文中处理

然后识别规范格式,并阅读
references/spec-parsing-patterns.md
以获取针对特定格式的提取指南:

格式 信号
RFC RFC XXXXMUST/SHALL/SHOULD、ABNF 语法、带编号的章节文本
学术论文/伪代码 Algorithm XProtocol XFigure X、编号步骤、数学模式中的 /
非正式描述 编号列表、“A sends B ...”、纯英文描述
ProVerif (.pv) processletin(ch, x)out(ch, msg)!(复制)
Tamarin (.spthy) rule--[ ]->Fr(~x)!Pk(A, pk)In(m)Out(m)

如果规范引用了已知的命名协议(TLS、Noise、Signal、X3DH、Double Ratchet、FROST),也请阅读
references/protocol-patterns.md
以使用其规范流程作为骨架,并填充规范特定的细节。

步骤 S2:提取参与方和角色

识别所有协议参与者。查找:

  • 命名角色:在文本或伪代码中:AliceBobClientServerInitiatorResponderProverVerifierDealerParty_iCoordinatorSigner
  • 章节标题:“Parties”、“Roles”、“Participants”、“Setup”、“Notation”
  • ProVerif:顶层进程名(let ClientProc(...)let ServerProc(...)
  • Tamarin:规则名和事实参数(例如 !Pk($A, pk)$A 是一个参与方)

将每个角色映射到 Mermaid participant 声明。使用短 ID 和描述性别名(参见
references/mermaid-sequence-syntax.md 中的命名约定)。

步骤 S3:提取消息流

追踪每个参与方发送给谁以及顺序。按格式的提取模式:

RFC / 非正式描述:

  • 箭头符号:A → B: msgA -> B
  • 句子模式:“A sends B ...”、“B responds with ...”、“A transmits ...”、“upon receiving X, B sends Y”
  • 编号步骤:按顺序提取,从上下文中推断发送者/接收者

伪代码:

  • 带有显式 sender/receiver 参数的函数签名
  • send(party, msg) / receive(party) 调用
  • 返回值作为下一步中另一方函数的输入

ProVerif (.pv):

  • out(ch, msg) — 在通道 ch 上发送
  • in(ch, x) — 在通道 ch 上接收,绑定到 x
  • 匹配同一通道上的 out/in 对以识别消息流
  • !(复制)表示处理多个会话的角色

Tamarin (.spthy):

  • In(m) 前提 — 接收消息 m
  • Out(m) 结论 — 发送消息 m
  • 规则名和规则顺序揭示协议轮次
  • Fr(~x) — 参与方生成的新鲜随机值
  • --[ Label ]-> 事实 — 安全注释,而非消息

保留顺序和轮次结构。在最终图中使用 par 块对并发发送(广播)进行分组。

步骤 S4:提取密码学操作

对于每个协议步骤,识别执行的密码学操作以及执行这些操作的参与方:

规范符号 操作 图注释
keygen()Gen(1^λ) 密钥生成 Note over A: keygen() → pk, sk
DH(a, B)g^ab DH / ECDH Note over A,B: DH(sk_A, pk_B)
KDF(ikm)HKDF(...) 密钥派生 Note over A: HKDF(ikm, salt, info) → k
Sign(sk, m)σ ← Sign 签名 Note over A: Sign(sk, msg) → σ
Verify(pk, m, σ) 验证 Note over B: Verify(pk, msg, σ)
Enc(k, m){m}_k 加密 Note over A: Enc(k, plaintext) → ct
Dec(k, c) 解密 Note over B: Dec(k, ct) → plaintext
H(m)hash(m) 哈希 Note over A: H(data) → digest
Commit(v, r)com 承诺 Note over A: Commit(value, rand) → C
ProVerif senc(m, k) 对称加密 Note over A: Enc(k, m) → ct
ProVerif pk(sk) 公钥派生 Note over A: pk = pk(sk)
ProVerif sign(m, sk) 签名 Note over A: Sign(sk, m) → σ

识别安全条件和中止路径:

  • 文本:“if verification fails, abort”、“only if ...”、“reject if ...”
  • 伪代码:assertrequireif ... abort
  • ProVerif:if m = expected then ... else 0
  • Tamarin:矛盾事实或限制引理

这些在最终图中变为 alt 块。

步骤 S5:标记规范歧义

在进入步骤 6 之前,检查是否存在空白:

  • 不明确的消息顺序:从轮次结构或章节顺序推断;用 ⚠️ ordering inferred from spec structure 注释
  • 隐含的参与方:如果某个参与方的角色是隐含的但未命名,给它一个描述性名称并注明推断
  • 缺失的步骤:如果规范省略了该协议规范模式所需的步骤,注释:
    ⚠️ spec omits [step] — canonical protocol requires it
  • 未指定的密码学:如果规范说“encrypt”但没有指定方案,注释:⚠️ encryption scheme not specified
  • ProVerif/Tamarin:私有通道(用 new c 声明或作为私有自由名称的 c)表示带外通道——请注明

<!-- 代码路径(步骤 1–5)和规范路径(步骤 S1–S5)都从这里继续 -->

步骤 6:生成 sequenceDiagram

按照
references/mermaid-sequence-syntax.md
中的规则生成 Mermaid 语法。

完整性优于简洁性。 显示每种不同的消息类型。省略重复的循环迭代(改用 loop 块),但绝不省略不同的协议步骤。

正确性优于美观性。 图必须与代码实际执行的操作一致。如果代码与已知规范不一致,注释差异:

Note over A,B: ⚠️ spec requires MAC here — implementation omits it

步骤 7:验证并交付

在交付之前:

  • [ ] 每个声明的参与者实际发送或接收至少一条消息
  • [ ] 箭头指向正确的方向(发送者 → 接收者)
  • [ ] 密码学操作位于正确的参与方(执行该操作的参与方)
  • [ ] 如果使用了协议阶段,没有箭头出现在阶段块之外
  • [ ] alt 块覆盖了已知的中止/错误路径
  • [ ] 图渲染没有语法错误(检查
    references/mermaid-sequence-syntax.md
    中的常见陷阱)
  • [ ] 如果发现规范差异,用 ⚠️ 注释

将图写入文件。 选择从协议名称派生的文件名,例如 noise-xx-handshake.mdx3dh-key-agreement.md。写入具有以下结构的 Markdown 文件:

# <协议名称> 序列图

\`\`\`mermaid
sequenceDiagram
    ...
\`\`\`

## 协议摘要

- **参与方:** ...
- **轮次复杂度:** ...
- **关键原语:** ...
- **认证:** ...
- **前向保密性:** ...
- **注意:** [规范偏差或安全观察,或“无”]

写入文件后,在响应中内联打印一个 ASCII 序列图,后跟协议摘要。说明输出文件名,以便用户知道在哪里找到 Mermaid 源文件。

遵循
references/ascii-sequence-diagram.md
中的所有绘图约定,包括内联输出格式。


决策树

── 输入是规范文档(不是代码)?
│  └─ 步骤 S1:识别格式,阅读 references/spec-parsing-patterns.md
│
── 输入是源代码(不是规范)?
│  └─ 步骤 1:grep 搜索握手/轮次/发送/接收入口点
│
── 同时提供了规范和代码?
│  └─ 先运行规范工作流(S1–S5)构建规范图,
│     然后阅读代码并用 ⚠️ 注释差异
│
── 规范是已知协议(TLS、Noise、Signal、X3DH、FROST)?
│  └─ 阅读 references/protocol-patterns.md 并使用规范流程作为骨架
│
── 规范是 ProVerif (.pv) 或 Tamarin (.spthy)?
│  └─ 阅读 references/spec-parsing-patterns.md → 形式化模型部分
│
── 规范消息顺序不明确?
│  └─ 从轮次/章节结构推断,用 ⚠️ 注释
│
── 无法从规范中识别参与方?
│  └─ 检查“Parties”/“Notation”部分;对于 ProVerif 读取进程名;
│     对于 Tamarin 读取规则名和事实参数
│
── 不知道哪些代码文件实现了协议?
│  └─ 步骤 1:grep 搜索握手/轮次/发送/接收入口点
│
── 无法从结构体名称中识别参与方?
│  └─ 读取测试文件——测试设置揭示了角色
│
── 协议在进程内运行(没有网络调用)?
│  └─ 将角色边界处的函数参数传递视为消息
│
── MPC / 阈值协议,有 N 个参与方?
│  └─ 阅读 references/protocol-patterns.md → MPC 部分
│
── Mermaid 语法错误?
│  └─ 阅读 references/mermaid-sequence-syntax.md → 常见陷阱
│
└─ ASCII 绘图约定?
   └─ 阅读 references/ascii-sequence-diagram.md

示例

代码路径examples/simple-handshake/

  • protocol.py — 两方认证密钥交换(X25519 DH + Ed25519 签名 + HKDF + ChaCha20-Poly1305)
  • expected-output.md — 该技能应为该协议生成的精确 ASCII 图和 Mermaid 文件

规范路径(ProVerif)examples/simple-proverif/

  • model.pv — 在 ProVerif 中建模的 HMAC 挑战-响应认证
  • expected-output.md — 逐步提取演练(参与方、消息流、密码学操作)以及该技能应生成的精确 ASCII 图和 Mermaid 文件

在处理不熟悉的输入之前,先研究相关示例。


支持文档